From 076279c261ef10067978714b33abe4e3f74f63c3 Mon Sep 17 00:00:00 2001 From: Q Date: Fri, 13 Oct 2023 23:52:46 +0300 Subject: [PATCH] move to json config. allow subfolders --- mirva/__init__.py | 2 +- mirva/mirva.py | 205 +++++++++++++++++++++++++++----------- mirva/resources/mirva.css | 15 +++ 3 files changed, 165 insertions(+), 57 deletions(-) diff --git a/mirva/__init__.py b/mirva/__init__.py index 9d936bd..062697a 100644 --- a/mirva/__init__.py +++ b/mirva/__init__.py @@ -1,4 +1,4 @@ -__version__ = "20230929.0" +__version__ = "20231013.0" def get_version(): diff --git a/mirva/mirva.py b/mirva/mirva.py index 28c78b1..d0fedef 100755 --- a/mirva/mirva.py +++ b/mirva/mirva.py @@ -1,10 +1,11 @@ import configparser +import json import os -import sys +import random import re import shutil import subprocess -import random +import sys import urllib.parse from argparse import ArgumentParser, HelpFormatter @@ -14,16 +15,13 @@ from tqdm import tqdm class Mirva: def __init__(self): - self.resource_src = os.path.join( - os.path.dirname(os.path.abspath(__file__)), "resources" - ) + self.resource_src = os.path.join(os.path.dirname(os.path.abspath(__file__)), "resources") self.resource_dir = ".mirva" self.medium_dir = os.path.join(self.resource_dir, "med") - self.config_file = os.path.join(self.resource_dir, "config.cfg") - self.config_backup = os.path.join(self.resource_dir, "config.cfg.bkp") - self.image_match = re.compile( - ".*\.jpg$|.*\.jpeg$|.*\.png$|.*\.gif$|.*\.tif$", re.I - ) + self.config_file = os.path.join(self.resource_dir, "config.json") + self.config_file_old = os.path.join(self.resource_dir, "config.cfg") + self.config_backup = os.path.join(self.resource_dir, "config.bkp") + self.image_match = re.compile(".*\.jpg$|.*\.jpeg$|.*\.png$|.*\.gif$|.*\.tif$", re.I) self.video_match = re.compile(".*\.mp4$", re.I) self.site_defaults = { "title": {"default": "", "help": "Title of the site"}, @@ -49,28 +47,27 @@ class Mirva: self.get_options() os.chdir(self.options.folder) self.file_list = self.get_files() + self.folder_list = self.get_folders() if self.run_commands["config"]: self.write_resources() updated = self.create_config() if updated: - print( - "Config created or updated: Check config contents: {}".format( - self.config_file - ) - ) + print("Config created or updated: Check config contents: {}".format(self.config_file)) if self.run_commands["build"]: self.get_config() self.create_posts() + self.create_folders() self.write_index() self.write_mediums() print("Gallery written.") def create_config(self): - self.config = configparser.RawConfigParser() - self.config.read(self.config_file) + self.get_config() config_changed = False + + ## SITE if not "SITE" in self.config: self.config["SITE"] = {} config_changed = True @@ -87,25 +84,55 @@ class Mirva: self.config["SITE"][key] = value config_changed = True + ## FOLDERS + if not "FOLDERS" in self.config: + self.config["FOLDERS"] = [] + config_changed = True + + path_list = [i["path"] for i in self.config["FOLDERS"]] + if self.options.add_back: + if not ".." in path_list: + self.config["FOLDERS"].insert(0, {"path": "..", "title": "Back", "thumb": '[guess]'}) + config_changed = True + + for d in self.folder_list: + if not d in path_list: + self.config["FOLDERS"].append({"path": d, "title": d, "thumb": '[guess]'}) + config_changed = True + + ## IMAGES + if not "IMAGES" in self.config: + self.config["IMAGES"] = [] + config_changed = True + + path_list = [i["path"] for i in self.config["IMAGES"]] for f in self.file_list: - if not f in self.config: + if not f in path_list: title, _ = os.path.splitext(f) title = title.replace("_", " ") - self.config[f] = {"title": title, "description": ""} + self.config["IMAGES"].append({"path": f, "title": title, "description": ""}) config_changed = True print("Added {}".format(f)) if self.options.purge: - unnecessary = [] - for f in self.config: - if f in ("SITE", "DEFAULT"): + unnecessary_files = [] + unnecessary_folders = [] + for i, f in enumerate(self.config["IMAGES"]): + if f["path"] not in self.file_list: + print("{} not found in files".format(f["path"])) + unnecessary_files.append(i) + for i, d in enumerate(self.config["FOLDERS"]): + if d["path"] == "..": continue - if f not in self.file_list: - print("{} not found in files".format(f)) - unnecessary.append(f) - for f in unnecessary: - del self.config[f] + if d["path"] not in self.folder_list: + unnecessary_folders.append(i) + if len(unnecessary_files) > 0: config_changed = True + if len(unnecessary_folders) > 0: + config_changed = True + + self.config["IMAGES"] = [d for i, d in enumerate(self.config["IMAGES"]) if i not in unnecessary_files] + self.config["FOLDERS"] = [d for i, d in enumerate(self.config["FOLDERS"]) if i not in unnecessary_folders] if self.options.exif: self.append_exif() @@ -117,41 +144,75 @@ class Mirva: def create_posts(self): self.posts = [] - for c in self.config: - if c in self.file_list: - post = self.get_post( - c, self.config[c]["title"], self.config[c]["description"] - ) + for c in self.config["IMAGES"]: + if c["path"] in self.file_list: + post = self.get_post(c["path"], c["title"], c["description"]) self.posts.append(post) + def create_folders(self): + self.folders = [] + for c in self.config["FOLDERS"]: + self.folders.append(self.get_folder(c["path"], c["title"], c["thumb"])) + def get_config(self): - self.config = configparser.RawConfigParser() - self.config.read(self.config_file) + if os.path.exists(self.config_file_old): + # Migration from old style config + self.config_old = configparser.RawConfigParser() + self.config_old.read(self.config_file_old) + self.config = {} + self.config["SITE"] = dict(self.config_old.items("SITE")) + self.config["IMAGES"] = [] + + for f in self.config_old.sections(): + if f in ("IMAGES", "SITE"): + continue + self.config["IMAGES"].append( + { + "path": f, + "title": self.config_old[f]["title"], + "description": self.config_old[f]["description"], + } + ) + os.remove(self.config_file_old) + return + if os.path.exists(self.config_file): + with open(self.config_file, "rt") as fp: + self.config = json.load(fp) + return + self.config = {} def write_config(self): - print( - "Modified config: {}".format( - os.path.join(self.options.folder, self.config_file) - ) - ) + print("Modified config: {}".format(os.path.join(self.options.folder, self.config_file))) if os.path.exists(self.config_file): with open(self.config_file, "rt") as reader: with open(self.config_backup, "wt") as writer: writer.write(reader.read()) with open(self.config_file, "wt") as fp: - self.config.write(fp) + json.dump(self.config, fp, indent=2) def get_files(self): files = [] for f in sorted(os.listdir(".")): if f.startswith("."): continue + if not os.path.isfile(f): + continue if not (self.image_match.match(f) or self.video_match.match(f)): continue files.append(f) return files + def get_folders(self): + folders = [] + for f in sorted(os.listdir(".")): + if f.startswith("."): + continue + if not os.path.isdir(f): + continue + folders.append(f) + return folders + def get_options(self): parser = ArgumentParser(prog="mirva", formatter_class=SmartFormatter) parser.add_argument( @@ -165,7 +226,12 @@ class Mirva: default=".", help="Folder for gallery. Default current folder.", ) - + parser.add_argument( + "--add-back", + default=False, + action="store_true", + help="Add 'Back' link to parent folder.", + ) parser.add_argument( "--purge", default=False, @@ -186,9 +252,7 @@ class Mirva: action="append", metavar=("key", "value"), help="smart|Configurable options: \n" - + "\n".join( - ["{}: {}".format(k, v["help"]) for k, v in self.site_defaults.items()] - ), + + "\n".join(["{}: {}".format(k, v["help"]) for k, v in self.site_defaults.items()]), ) parser.add_argument( @@ -214,7 +278,7 @@ class Mirva: "build": self.options.command == "build" or self.options.command == "all", } - def get_index(self, posts): + def get_index(self): return """