move to json config. allow subfolders

This commit is contained in:
Q
2023-10-13 23:52:46 +03:00
parent 7f0412a9e4
commit 076279c261
3 changed files with 165 additions and 57 deletions

View File

@@ -1,4 +1,4 @@
__version__ = "20230929.0"
__version__ = "20231013.0"
def get_version():

View File

@@ -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 """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Design by TEMPLATED
@@ -252,6 +316,11 @@ Released : 20110306
<div id="page-bgtop">
<div id="page-bgbtm">
<div id="content">
<div id="post_folders">
<div class="entry folders">
{folders}
</div>
</div>
<div class="post" id="post_intro">
<div class="entry intro">
{intro}
@@ -273,7 +342,8 @@ Released : 20110306
sub_title=self.config["SITE"]["sub_title"],
intro=self.config["SITE"]["intro"],
scroll=self.config["SITE"]["scroll"],
posts="\n".join(posts),
folders="\n".join(self.folders),
posts="\n".join(self.posts),
resource=self.resource_dir,
)
@@ -307,6 +377,32 @@ Released : 20110306
</div>"""
).format(image=image, title=title, content=content, med_dir=self.medium_dir)
def get_folder(self, path, title, thumb):
if thumb == '[guess]':
try:
img = (
"style=\"background-image: url('"
+ urllib.parse.quote(
os.path.join(
path,
self.resource_dir,
"med",
sorted(
[f for f in os.listdir(os.path.join(path, self.resource_dir, "med")) if f.endswith(".jpg")]
)[0],
)
)
+ "')\""
)
except Exception:
img = ""
else:
img = "style=\"background-image: url('{}')\"".format(thumb)
return '<div class=folder_wrapper><a href="{path}" title="{title}"><span class="folder_thumb" {img}></span>{title}</a></div>'.format(
path=urllib.parse.quote(path), title=title, img=img
)
def is_created_with_mirva(self):
with open("index.html", "rt") as fp:
for line in fp.readlines():
@@ -317,13 +413,11 @@ Released : 20110306
def write_index(self):
if os.path.exists("index.html"):
if not self.is_created_with_mirva():
print(
"index.html exists, and it's not written with Mirva. Not overwriting."
)
print("index.html exists, and it's not written with Mirva. Not overwriting.")
sys.exit(1)
with open("index.html", "wt") as fp:
fp.write(self.get_index(self.posts))
fp.write(self.get_index())
def write_resources(self):
try:
@@ -427,22 +521,21 @@ Released : 20110306
</ul>
"""
for f in self.config:
if f in self.file_list:
for f in self.config["IMAGES"]:
if f["path"] in self.file_list:
sys.stdout.write(".")
sys.stdout.flush()
file_size = human_size(f)
file_size = human_size(f["path"])
p = subprocess.run(
[
"identify",
"-format",
exif_format.format(size=file_size),
"{}[0]".format(f),
"{}[0]".format(f["path"]),
],
capture_output=True,
)
self.config[f]["description"] += p.stdout.decode("utf-8")
f["description"] += p.stdout.decode("utf-8")
sys.stdout.write("\n")

View File

@@ -175,6 +175,21 @@ a:hover {}
.post-bgbtm {}
.folder_wrapper {
margin-top: 3px;
font-size: 15px;
}
.folders .folder_thumb {
width: 150px;
height: 40px;
background-size: cover;
vertical-align: middle;
margin-right: 2em;
display: inline-block;
background-position: center;
}
.post .title {
height: 38px;
margin-bottom: 10px;