diff --git a/README.md b/README.md index 457c5ce..2c51253 100644 --- a/README.md +++ b/README.md @@ -37,25 +37,25 @@ pip install numpy tqdm Jinja2 The script supports several command-line options to customize its behavior. Below is the list of available options: ```sh -./generate_html.py [-h] -p ROOT -w WEBROOT -t TITLE [-i ICON] [-r] [-n] [--fancyfolders] [-l LICENSE] [-a AUTHOR] [-e EXTENSION] [--theme THEME] [--ignore-other-files] [--exclude EXCLUDE] +./generate_html.py [-h] -p ROOT -w WEBROOT -t TITLE [-i ICON] [-r] [-n] [--use-fancy-folders] [-l LICENSE] [-a AUTHOR] [-e EXTENSION] [--theme-path THEME] [--ignore-other-files] [--exclude-folders EXCLUDE] ``` ### Options - `-h, --help`: Show the help message and exit. -- `-p ROOT, --root ROOT`: Specify the root folder where the images are stored. This option is required. -- `-w WEBROOT, --webroot WEBROOT`: Specify the web root URL where the images will be accessible. This option is required. -- `-t TITLE, --title TITLE`: Specify the title for the root directory HTML file. This option is required. -- `-i ICON, --foldericon ICON`: Specify the URL for the folder icon. Default is `https://www.svgrepo.com/show/400249/folder.svg`. -- `-r, --regenerate`: Regenerate thumbnails even if they already exist. -- `-n, --non-interactive`: Disable interactive mode, which is useful for automated workflows. -- `--fancyfolders`: Use fancy folders instead of the default Apache directory listing. -- `-l LICENSE, --license LICENSE`: Specify a license for the content. Options are `cc-zero`, `cc-by`, `cc-by-sa`, `cc-by-nd`, `cc-by-nc`, `cc-by-nc-sa`, and `cc-by-nc-nd`. -- `-a AUTHOR, --author AUTHOR`: Specify the author of the content. Default is "Author". -- `-e EXTENSION, --extension EXTENSION`: Specify file extensions to include. This option can be used multiple times. -- `--theme THEME`: Specify the path to a custom CSS theme file. Default is `themes/default.css`. +- `-p ROOT, --root-directory ROOT`: Specify the root folder where the images are stored. This option is required. +- `-w WEBROOT, --web-root-url WEBROOT`: Specify the web root URL where the images will be accessible. This option is required. +- `-t TITLE, --site-title TITLE`: Specify the title for the root directory HTML file. This option is required. +- `-i ICON, --folder-icon-url ICON`: Specify the URL for the folder icon. Default is `https://www.svgrepo.com/show/400249/folder.svg`. +- `-r, --regenerate-thumbnails`: Regenerate thumbnails even if they already exist. +- `-n, --non-interactive-mode`: Disable interactive mode, which is useful for automated workflows. +- `--use-fancy-folders`: Use fancy folders instead of the default Apache directory listing. +- `-l LICENSE, --license-type LICENSE`: Specify a license for the content. Options are `cc-zero`, `cc-by`, `cc-by-sa`, `cc-by-nd`, `cc-by-nc`, `cc-by-nc-sa`, and `cc-by-nc-nd`. +- `-a AUTHOR, --author-name AUTHOR`: Specify the author of the content. Default is "Author". +- `-e EXTENSION, --file-extensions EXTENSION`: Specify file extensions to include. This option can be used multiple times. +- `--theme-path THEME`: Specify the path to a custom CSS theme file. Default is `themes/default.css`. - `--ignore-other-files`: Ignore files other than those specified by the included extensions. -- `--exclude EXCLUDE`: Exclude folders from processing. Only provide the basename of the folders you want to exclude. This option can be used multiple times. +- `--exclude-folder EXCLUDE`: Exclude folders from processing. Only provide the basename of the folders you want to exclude. This option can be used multiple times. ### Example @@ -71,7 +71,7 @@ To regenerate thumbnails and run in non-interactive mode: ./generate_html.py -p /data/pictures -w https://pictures.example.com -t "My Photo Gallery" -r -n ``` -To include a license, author, and custom title: +To include a license and author: ```sh ./generate_html.py -p /data/pictures -w https://pictures.example.com -t "My Photo Gallery" -l cc-by -a "John Doe" @@ -80,22 +80,22 @@ To include a license, author, and custom title: To specify a custom CSS theme: ```sh -./generate_html.py -p /data/pictures -w https://pictures.example.com -t "My Photo Gallery" --theme custom_theme.css +./generate_html.py -p /data/pictures -w https://pictures.example.com -t "My Photo Gallery" --theme-path custom_theme.css ``` To exclude specific folders and specify file extensions: ```sh -./generate_html.py -p /data/pictures -w https://pictures.example.com -t "My Photo Gallery" --exclude Archives --exclude Temp -e .jpg -e .jpeg -e .png +./generate_html.py -p /data/pictures -w https://pictures.example.com -t "My Photo Gallery" --exclude-folder Archives --exclude-folders Temp -e .jpg -e .jpeg -e .png ``` ## Notes -- The root and webroot paths must point to the same folder, one on the filesystem and one on the webserver. Use absolute paths. +- The root and web root paths must point to the same folder, one on the filesystem and one on the web server. Use absolute paths. - Ensure that ImageMagick is installed and accessible in your system for thumbnail generation. - The script generates the preview thumbnails in a `.thumbnails` subdirectory within the root folder. - The `.lock` file prevents multiple instances of the script from running simultaneously. Make sure to remove it if the script terminates unexpectedly. ## License -This project is licensed under the AGPL-3.0 License. See the [LICENSE](LICENSE) file for details. \ No newline at end of file +This project is licensed under the AGPL-3.0 License. See the [LICENSE](LICENSE) file for details. diff --git a/cclicense.py b/cclicense.py index aaa453a..ec707d6 100644 --- a/cclicense.py +++ b/cclicense.py @@ -1,3 +1,11 @@ +class License: + project: str + author: str + type: str + url: str + pics: list[str] + + def licenseswitch(cclicense: str) -> str: switch = { "cc-zero": """ diff --git a/generate_html.py b/generate_html.py index 1f20b52..79011fa 100755 --- a/generate_html.py +++ b/generate_html.py @@ -5,248 +5,246 @@ import urllib.parse import shutil from multiprocessing import Pool from pathlib import Path +from typing import Any, Dict, List, Optional, Tuple import numpy as np from jinja2 import Environment, FileSystemLoader from tqdm.auto import tqdm import cclicense -environment = Environment(loader=FileSystemLoader(os.path.join(os.path.abspath(os.path.dirname(__file__)), "templates/"))) - -_FOLDERICON = "https://www.svgrepo.com/show/400249/folder.svg" -_STATICFILES = os.path.join(os.path.abspath(os.path.dirname(__file__)), "files") -_FAVICON = ".static/favicon.ico" -_STYLE = ".static/global.css" -_THEME = os.path.join(os.path.abspath(os.path.dirname(__file__)), "themes", "default.css") -_AUTHOR = "Author" -VERSION = "1.3" # fmt: off -rawext = [".3fr", ".ari", ".arw", ".bay", ".braw", ".crw", ".cr2", ".cr3", ".cap", ".data", ".dcs", ".dcr", ".dng", ".drf", ".eip", ".erf", ".fff", ".gpr", ".iiq", ".k25", ".kdc", ".mdc", ".mef", ".mos", ".mrw", ".nef", ".nrw", ".obm", ".orf", ".pef", ".ptx", ".pxn", ".r3d", ".raf", ".raw", ".rwl", ".rw2", ".rwz", ".sr2", ".srf", ".srw", ".tif", ".tiff", ".x3f"] -imgext = [".jpg", ".jpeg"] -excludes = [".lock", "index.html", ".thumbnails", ".static"] -notlist = ["Galleries", "Archives"] +# Constants +DEFAULT_FOLDER_ICON = "https://www.svgrepo.com/show/400249/folder.svg" +STATIC_FILES_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "files") +FAVICON_PATH = ".static/favicon.ico" +GLOBAL_CSS_PATH = ".static/global.css" +DEFAULT_THEME_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), "themes", "default.css") +DEFAULT_AUTHOR = "Author" +VERSION = "1.4" +RAW_EXTENSIONS = [".3fr", ".ari", ".arw", ".bay", ".braw", ".crw", ".cr2", ".cr3", ".cap", ".data", ".dcs", ".dcr", ".dng", ".drf", ".eip", ".erf", ".fff", ".gpr", ".iiq", ".k25", ".kdc", ".mdc", ".mef", ".mos", ".mrw", ".nef", ".nrw", ".obm", ".orf", ".pef", ".ptx", ".pxn", ".r3d", ".raf", ".raw", ".rwl", ".rw2", ".rwz", ".sr2", ".srf", ".srw", ".tif", ".tiff", ".x3f"] +IMG_EXTENSIONS = [".jpg", ".jpeg"] +EXCLUDES = [".lock", "index.html", ".thumbnails", ".static"] +NOT_LIST = ["Galleries", "Archives"] # fmt: on -thumbnails: list[tuple[str, str]] = [] +# Initialize Jinja2 environment +env = Environment(loader=FileSystemLoader(os.path.join(os.path.abspath(os.path.dirname(__file__)), "templates"))) +thumbnails: List[Tuple[str, str]] = [] + +class Args: + root_directory: str + web_root_url: str + site_title: str + folder_icon_url: str + regenerate_thumbnails: bool + non_interactive_mode: bool + use_fancy_folders: bool + license_type: Optional[str] + author_name: str + file_extensions: List[str] + theme_path: str + ignore_other_files: bool + exclude_folders: List[str] -def thumbnail_convert(arguments: tuple[str, str]): +def parse_arguments() -> Args: + parser = argparse.ArgumentParser(description="Generate HTML files for a static image hosting website.") + parser.add_argument("-p", "--root-directory", help="Root directory containing the images.", required=True, type=str, dest="root_directory") + parser.add_argument("-w", "--web-root-url", help="Base URL of the web root for the image hosting site.", required=True, type=str, dest="web_root_url") + parser.add_argument("-t", "--site-title", help="Title of the image hosting site.", required=True, type=str, dest="site_title") + parser.add_argument("-i", "--folder-icon-url", help="URL of the icon used for folders.", default=DEFAULT_FOLDER_ICON, type=str, metavar="ICON", dest="folder_icon_url") + parser.add_argument("-r", "--regenerate-thumbnails", help="Regenerate thumbnails even if they already exist.", action="store_true", default=False, dest="regenerate_thumbnails") + parser.add_argument("-n", "--non-interactive-mode", help="Run in non-interactive mode, disabling progress bars.", action="store_true", default=False, dest="non_interactive_mode") + parser.add_argument("-l", "--license-type", help="Specify the license type for the images.", choices=["cc-zero", "cc-by", "cc-by-sa", "cc-by-nd", "cc-by-nc", "cc-by-nc-sa", "cc-by-nc-nd"], default=None, dest="license_type") + parser.add_argument("-a", "--author-name", help="Name of the author of the images.", default=DEFAULT_AUTHOR, type=str, dest="author_name") + parser.add_argument("-e", "--file-extensions", help="File extensions to include (can be specified multiple times).", action="append", dest="file_extensions") + parser.add_argument("--theme-path", help="Path to the CSS theme file.", default=DEFAULT_THEME_PATH, type=str, dest="theme_path") + parser.add_argument("--use-fancy-folders", help="Enable fancy folder view instead of the default Apache directory listing.", action="store_true", default=False, dest="use_fancy_folders") + parser.add_argument("--ignore-other-files", help="Ignore files that do not match the specified extensions.", action="store_true", default=False, dest="ignore_other_files") + parser.add_argument("--exclude-folder", help="Folders to exclude from processing (can be specified multiple times).", action="append", dest="exclude_folders") + parser.add_argument("--version", action="version", version=f"%(prog)s {VERSION}") + + parsed_args = parser.parse_args() + args = Args() + args.root_directory = parsed_args.root_directory + args.web_root_url = parsed_args.web_root_url + args.site_title = parsed_args.site_title + args.folder_icon_url = parsed_args.folder_icon_url + args.regenerate_thumbnails = parsed_args.regenerate_thumbnails + args.non_interactive_mode = parsed_args.non_interactive_mode + args.use_fancy_folders = parsed_args.use_fancy_folders + args.license_type = parsed_args.license_type + args.author_name = parsed_args.author_name + args.file_extensions = parsed_args.file_extensions + args.theme_path = parsed_args.theme_path + args.ignore_other_files = parsed_args.ignore_other_files + args.exclude_folders = parsed_args.exclude_folders + return args + + +def init_globals(args: Args) -> None: + global RAW_EXTENSIONS + if not args.file_extensions: + args.file_extensions = IMG_EXTENSIONS + if not args.exclude_folders: + args.exclude_folders = NOT_LIST + args.root_directory = args.root_directory.rstrip("/") + "/" + args.web_root_url = args.web_root_url.rstrip("/") + "/" + if not os.path.exists(os.path.join(args.root_directory, ".thumbnails")): + os.mkdir(os.path.join(args.root_directory, ".thumbnails")) + + RAW_EXTENSIONS = [ext.lower() for ext in RAW_EXTENSIONS] + [ext.upper() for ext in RAW_EXTENSIONS] + + +def copy_static_files(args: Args) -> None: + shutil.copytree(STATIC_FILES_DIR, os.path.join(args.root_directory, ".static"), dirs_exist_ok=True) + shutil.copyfile(args.theme_path, os.path.join(args.root_directory, ".static", "theme.css")) + + +def generate_thumbnail(arguments: Tuple[str, str]) -> None: folder, item = arguments - path = os.path.join(args.root, ".thumbnails", folder.removeprefix(args.root), os.path.splitext(item)[0]) + ".jpg" - if not os.path.exists(path) or args.regenerate: + path = os.path.join(args.root_directory, ".thumbnails", folder.removeprefix(args.root_directory), os.path.splitext(item)[0]) + ".jpg" + if not os.path.exists(path) or args.regenerate_thumbnails: if shutil.which("magick"): - os.system( - f'magick "{os.path.join(folder, item)}" -quality 75% -define jpeg:size=1024x1024 -define jpeg:extent=100kb -thumbnail 512x512 -auto-orient "{path}"' - ) + os.system(f'magick "{os.path.join(folder, item)}" -quality 75% -define jpeg:size=1024x1024 -define jpeg:extent=100kb -thumbnail 512x512 -auto-orient "{path}"') else: - os.system( - f'convert "{os.path.join(folder, item)}" -quality 75% -define jpeg:size=1024x1024 -define jpeg:extent=100kb -thumbnail 512x512 -auto-orient "{path}"' - ) + os.system(f'convert "{os.path.join(folder, item)}" -quality 75% -define jpeg:size=1024x1024 -define jpeg:extent=100kb -thumbnail 512x512 -auto-orient "{path}"') -def listfolder(folder: str, title: str): - if not args.non_interactive: - pbar.desc = f"Generating html files - {folder}" - pbar.update(0) - items: list[str] = os.listdir(folder) +def get_total_folders(folder: str) -> None: + global total + items = os.listdir(folder) items.sort() - images: list[dict] = [] - subfolders: list[dict] = [] + for item in items: + if item not in EXCLUDES: + if os.path.isdir(os.path.join(folder, item)): + total += 1 + if item not in args.exclude_folders: + get_total_folders(os.path.join(folder, item)) - foldername = folder.removeprefix(args.root) - if foldername != "": - foldername += "/" + +def list_folder(folder: str, title: str) -> None: + if not args.non_interactive_mode: + pbar.desc = f"Generating HTML files - {folder}" + pbar.update(0) + items = os.listdir(folder) + items.sort() + images: List[Dict[str, Any]] = [] + subfolders: List[Dict[str, str]] = [] + foldername = folder.removeprefix(args.root_directory) + foldername = f"{foldername}/" if foldername else "" baseurl = urllib.parse.quote(foldername) - - if not os.path.exists(os.path.join(args.root, ".thumbnails", foldername)): - os.mkdir(os.path.join(args.root, ".thumbnails", foldername)) - + if not os.path.exists(os.path.join(args.root_directory, ".thumbnails", foldername)): + os.mkdir(os.path.join(args.root_directory, ".thumbnails", foldername)) contains_files = False for item in items: - if item not in excludes: + if item not in EXCLUDES: if os.path.isdir(os.path.join(folder, item)): - subfolder = {"url": f"{args.webroot}{baseurl}{urllib.parse.quote(item)}", "name": item} - subfolders.extend([subfolder]) - if item not in args.exclude: - listfolder(os.path.join(folder, item), os.path.join(folder, item).removeprefix(args.root)) + subfolder = {"url": f"{args.web_root_url}{baseurl}{urllib.parse.quote(item)}", "name": item} + subfolders.append(subfolder) + if item not in args.exclude_folders: + list_folder(os.path.join(folder, item), os.path.join(folder, item).removeprefix(args.root_directory)) else: extsplit = os.path.splitext(item) - if not args.non_interactive: - pbar.desc = f"Generating html files - {folder}" - pbar.update(0) contains_files = True - if extsplit[1].lower() in args.extensions: + if extsplit[1].lower() in args.file_extensions: image = { - "url": f"{args.webroot}{baseurl}{urllib.parse.quote(item)}", - "thumbnail": f"{args.webroot}.thumbnails/{baseurl}{urllib.parse.quote(extsplit[0])}.jpg", + "url": f"{args.web_root_url}{baseurl}{urllib.parse.quote(item)}", + "thumbnail": f"{args.web_root_url}.thumbnails/{baseurl}{urllib.parse.quote(extsplit[0])}.jpg", "name": item, } - if not os.path.exists(os.path.join(args.root, ".thumbnails", foldername, item)): + if not os.path.exists(os.path.join(args.root_directory, ".thumbnails", foldername, item)): thumbnails.append((folder, item)) - for raw in rawext: + for raw in RAW_EXTENSIONS: if os.path.exists(os.path.join(folder, extsplit[0] + raw)): url = urllib.parse.quote(extsplit[0]) + raw if raw in (".tif", ".tiff"): - image["tiff"] = f"{args.webroot}{baseurl}{url}" + image["tiff"] = f"{args.web_root_url}{baseurl}{url}" else: - image["raw"] = f"{args.webroot}{baseurl}{url}" - images.extend([image]) - if not args.non_interactive: - pbar.desc = f"Generating html files - {folder}" + image["raw"] = f"{args.web_root_url}{baseurl}{url}" + images.append(image) + if not args.non_interactive_mode: + pbar.desc = f"Generating HTML files - {folder}" pbar.update(0) - if len(images) > 0 or (args.fancyfolders and not contains_files) or (args.fancyfolders and args.ignoreotherfiles): - imagechunks = [] - if len(images) > 0: - for chunk in np.array_split(images, 8): - imagechunks.append(chunk) + if images or (args.use_fancy_folders and not contains_files) or (args.use_fancy_folders and args.ignore_other_files): + image_chunks = np.array_split(images, 8) if images else [] with open(os.path.join(folder, "index.html"), "w", encoding="utf-8") as f: - header = os.path.basename(folder) - if header == "": - header = title - if foldername == "": - parent = None - else: - parent = f"{args.webroot}{urllib.parse.quote(foldername.removesuffix(folder.split('/')[-1] + '/'))}" - if args.license: - _license = { - "project": args.title, - "author": args.author, - "type": cclicense.licensenameswitch(args.license), - "url": cclicense.licenseurlswitch(args.license), - "pics": cclicense.licensepicswitch(args.license), + header = os.path.basename(folder) or title + parent = None if not foldername else f"{args.web_root_url}{urllib.parse.quote(foldername.removesuffix(folder.split('/')[-1] + '/'))}" + license_info: cclicense.License = ( + { + "project": args.site_title, + "author": args.author_name, + "type": cclicense.licensenameswitch(args.license_type), + "url": cclicense.licenseurlswitch(args.license_type), + "pics": cclicense.licensepicswitch(args.license_type), } - else: - _license = None - - html = environment.get_template("index.html.j2") + if args.license_type + else None + ) + html = env.get_template("index.html.j2") content = html.render( title=title, - favicon=f"{args.webroot}{_FAVICON}", - stylesheet=f"{args.webroot}{_STYLE}", - theme=f"{args.webroot}.static/theme.css", - root=args.webroot, + favicon=f"{args.web_root_url}{FAVICON_PATH}", + stylesheet=f"{args.web_root_url}{GLOBAL_CSS_PATH}", + theme=f"{args.web_root_url}.static/theme.css", + root=args.web_root_url, parent=parent, header=header, - foldericon=args.foldericon, - license=_license, + foldericon=args.folder_icon_url, + license=license_info, subdirectories=subfolders, - images=imagechunks, + images=image_chunks, ) f.write(content) - f.close() else: if os.path.exists(os.path.join(folder, "index.html")): os.remove(os.path.join(folder, "index.html")) - if not args.non_interactive: + if not args.non_interactive_mode: pbar.update(1) -def gettotal(folder): - global total - - if not args.non_interactive: - pbar.desc = f"Traversing filesystem - {folder}" - pbar.update(0) - - items: list[str] = os.listdir(folder) - items.sort() - - for item in items: - if item not in excludes: - if os.path.isdir(os.path.join(folder, item)): - total += 1 - if not args.non_interactive: - pbar.update(1) - if item not in args.exclude: - gettotal(os.path.join(folder, item)) - - -def main(): - global rawext - global total - global args - global pbar - global _cclicense - +def main() -> None: + global args, total, pbar, thumbnails total = 0 - # fmt: off - # Parse command-line arguments - parser = argparse.ArgumentParser(description="Generate html files for static image host.") - parser.add_argument("-p", "--root", help="Root folder", required=True, type=str, dest="root") - parser.add_argument("-w", "--webroot", help="Webroot url", required=True, type=str, dest="webroot") - parser.add_argument("-t", "--title", help="Title", required=True, type=str, dest="title") - parser.add_argument("-i", "--foldericon", help="Foldericon url", default=_FOLDERICON, required=False, type=str, dest="foldericon", metavar="ICON") - parser.add_argument("-r", "--regenerate", help="Regenerate thumbnails", action="store_true", default=False, required=False, dest="regenerate") - parser.add_argument("-n", "--non-interactive", help="Disable interactive mode", action="store_true", default=False, required=False, dest="non_interactive") - parser.add_argument("-l", "--license", help="License", default=None, required=False, choices=["cc-zero", "cc-by", "cc-by-sa", "cc-by-nd", "cc-by-nc", "cc-by-nc-sa", "cc-by-nc-nd"], dest="license") - parser.add_argument("-a", "--author", help="Author", default=_AUTHOR, required=False, type=str, dest="author") - parser.add_argument("-e", "--extension", help="Extensions to include (multiple --extension are allowed)", required=False, action="append", dest="extensions") - parser.add_argument("--theme", help="Path to CSS theme file", default=_THEME, required=False, type=str, dest="theme") - parser.add_argument("--fancyfolders", help="Use fancy folders instead of default apache ones", action="store_true", default=False, required=False, dest="fancyfolders") - parser.add_argument("--ignore-other-files", help="Ignore other files than the ones specified with the specified extensions -e", action="store_true", default=False, required=False, dest="ignoreotherfiles") - parser.add_argument("--exclude", help="Exclude folders, only provide the basename of the folders you want to exclude (multiple --exclude are allowed)", required=False, action="append", dest="exclude") - parser.add_argument('--version', action='version', version=f'%(prog)s {VERSION}') - args = parser.parse_args() - # fmt: on - if not args.extensions: - args.extensions = imgext - if not args.exclude: - args.exclude = notlist - if not args.root.endswith("/"): - args.root += "/" - if not args.webroot.endswith("/"): - args.webroot += "/" - if not os.path.exists(os.path.join(args.root, ".thumbnails")): - os.mkdir(os.path.join(args.root, ".thumbnails")) - tmprawext = [] - for raw in rawext: - tmprawext.append(raw) - tmprawext.append(raw.upper()) - rawext = tmprawext + args = parse_arguments() + init_globals(args) - if os.path.exists(os.path.join(args.root, ".lock")): + if os.path.exists(os.path.join(args.root_directory, ".lock")): print("Another instance of this program is running.") exit() + try: - Path(os.path.join(args.root, ".lock")).touch() + Path(os.path.join(args.root_directory, ".lock")).touch() print("Copying static files...") - shutil.copytree(_STATICFILES, os.path.join(args.root, ".static"), dirs_exist_ok=True) - shutil.copyfile(args.theme, os.path.join(args.root, ".static", "theme.css")) + copy_static_files(args) - if args.non_interactive: - print("Generating html files...") - listfolder(args.root, args.title) - - with Pool(os.cpu_count()) as p: + if args.non_interactive_mode: + print("Generating HTML files...") + list_folder(args.root_directory, args.site_title) + with Pool(os.cpu_count()) as pool: print("Generating thumbnails...") - p.map(thumbnail_convert, thumbnails) + pool.map(generate_thumbnail, thumbnails) else: - pbar = tqdm(desc="Traversing filesystem", unit=" folders", ascii=True, dynamic_ncols=True) - gettotal(args.root) + pbar = tqdm(desc="Traversing filesystem", unit="folders", ascii=True, dynamic_ncols=True) + get_total_folders(args.root_directory) pbar.desc = "Traversing filesystem" pbar.update(0) pbar.close() - pbar = tqdm(total=total + 1, desc="Generating html files", unit=" files", ascii=True, dynamic_ncols=True) - listfolder(args.root, args.title) + pbar = tqdm(total=total + 1, desc="Generating HTML files", unit="files", ascii=True, dynamic_ncols=True) + list_folder(args.root_directory, args.site_title) pbar.desc = "Generating html files" pbar.update(0) pbar.close() - with Pool(os.cpu_count()) as p: - for r in tqdm( - p.imap_unordered(thumbnail_convert, thumbnails), - total=len(thumbnails), - desc="Generating thumbnails", - unit=" files", - ascii=True, - dynamic_ncols=True, - ): + with Pool(os.cpu_count()) as pool: + for _ in tqdm(pool.imap_unordered(generate_thumbnail, thumbnails), total=len(thumbnails), desc="Generating thumbnails", unit="files", ascii=True, dynamic_ncols=True): pass finally: - os.remove(os.path.join(args.root, ".lock")) + os.remove(os.path.join(args.root_directory, ".lock")) if __name__ == "__main__":