diff --git a/docs/license.md b/docs/license.md new file mode 100644 index 0000000000..f409d45232 --- /dev/null +++ b/docs/license.md @@ -0,0 +1 @@ +--8<-- "LICENSE" diff --git a/mkdocs.yml b/mkdocs.yml index ededa9ae5c..8e4c2663bc 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,4 +1,5 @@ site_name: ayon-core +repo_url: https://github.com/ynput/ayon-core nav: - Home: index.md @@ -45,15 +46,18 @@ plugins: - docs/**/* - tests/**/* - tools/**/* + - stubs/**/* # mocha fix + - ./**/pythonrc.py # houdini fix - .*/**/* - ./*.py - mkdocstrings: handlers: python: paths: - - . - - client - - server + - ./ + - client/* + - server/* + - services/* - minify: minify_html: true minify_js: true diff --git a/mkdocs_hooks.py b/mkdocs_hooks.py index fb424b236a..1faa1954f9 100644 --- a/mkdocs_hooks.py +++ b/mkdocs_hooks.py @@ -1,10 +1,71 @@ import os -import sys from pathlib import Path from shutil import rmtree import json +import glob +import logging TMP_FILE = "./missing_init_files.json" +NFILES = [] + +# ----------------------------------------------------------------------------- + + +class ColorFormatter(logging.Formatter): + grey = "\x1b[38;20m" + green = "\x1b[32;20m" + yellow = "\x1b[33;20m" + red = "\x1b[31;20m" + bold_red = "\x1b[31;1m" + reset = "\x1b[0m" + fmt = ( + "%(asctime)s - %(name)s - %(levelname)s - %(message)s " # noqa + "(%(filename)s:%(lineno)d)" + ) + + FORMATS = { + logging.DEBUG: grey + fmt + reset, + logging.INFO: green + fmt + reset, + logging.WARNING: yellow + fmt + reset, + logging.ERROR: red + fmt + reset, + logging.CRITICAL: bold_red + fmt + reset, + } + + def format(self, record): + log_fmt = self.FORMATS.get(record.levelno) + formatter = logging.Formatter(log_fmt) + return formatter.format(record) + + +ch = logging.StreamHandler() +ch.setFormatter(ColorFormatter()) + +logging.basicConfig( + level=logging.INFO, + handlers=[ch], +) + + +# ----------------------------------------------------------------------------- + + +def create_init_file(dirpath, msg): + global NFILES + ini_file = f"{dirpath}/__init__.py" + Path(ini_file).touch() + NFILES.append(ini_file) + logging.info(f"{msg}: created '{ini_file}'") + + +def create_parent_init_files(dirpath: str, rootpath: str, msg: str): + parent_path = dirpath + while parent_path != rootpath: + parent_path = os.path.dirname(parent_path) + parent_init = os.path.join(parent_path, "__init__.py") + if not os.path.exists(parent_init): + create_init_file(parent_path, msg) + else: + break def add_missing_init_files(*roots, msg=""): @@ -19,28 +80,26 @@ def add_missing_init_files(*roots, msg=""): Returns: None """ - nfiles = [] for root in roots: if not os.path.exists(root): continue - for dirpath, dirs, files in os.walk(root): + rootpath = os.path.abspath(root) + for dirpath, dirs, files in os.walk(rootpath): if "__init__.py" in files: continue - else: - Path(f"{dirpath}/__init__.py").touch() - nfiles.append(f"{dirpath}/__init__.py") - sys.stdout.write( - "\r\x1b[K" + f"{msg}: created {len(nfiles)} " - "temp '__init__.py' files" - ) - sys.stdout.flush() + + if "." in dirpath: + continue + + if not glob.glob(os.path.join(dirpath, "*.py")): + continue + + create_init_file(dirpath, msg) + create_parent_init_files(dirpath, rootpath, msg) with open(TMP_FILE, "w") as f: - json.dump(nfiles, f) - - sys.stdout.write("\n") - sys.stdout.flush() + json.dump(NFILES, f) def remove_missing_init_files(msg=""): @@ -55,26 +114,26 @@ def remove_missing_init_files(msg=""): Returns: None """ - with open(TMP_FILE, "r") as f: - nfiles = json.load(f) + global NFILES + nfiles = [] + if os.path.exists(TMP_FILE): + with open(TMP_FILE, "r") as f: + nfiles = json.load(f) + else: + nfiles = NFILES for file in nfiles: Path(file).unlink() - sys.stdout.write( - "\r\x1b[K" + f"{msg}: removed {len(nfiles)} temp '__init__.py' files" - ) - sys.stdout.flush() + logging.info(f"{msg}: removed {file}") os.remove(TMP_FILE) - - sys.stdout.write("\n") - sys.stdout.flush() + NFILES = [] def remove_pychache_dirs(msg=""): """ - This function walks the current directory and removes all existing '__pycache__' - directories. + This function walks the current directory and removes all existing + '__pycache__' directories. Args: msg: An optional message to display during the removal process. @@ -89,19 +148,13 @@ def remove_pychache_dirs(msg=""): pydir = Path(f"{dirpath}/__pycache__") rmtree(pydir) nremoved += 1 - sys.stdout.write( - "\r\x1b[K" + f"{msg}: removed {nremoved} '__pycache__' directories" - ) - sys.stdout.flush() + logging.info(f"{msg}: removed '{pydir}'") if not nremoved: - sys.stdout.write(f"{msg}: no __pycache__ dirs found") - - sys.stdout.write("\n") - sys.stdout.flush() + logging.info(f"{msg}: no __pycache__ dirs found") -# mkdocs hooks ----------------------------------------------------------------- +# mkdocs hooks ---------------------------------------------------------------- def on_startup(command, dirty): @@ -114,13 +167,19 @@ def on_pre_build(config): temporary `__init__.py` files to directories that do not contain one, to make sure mkdocs doesn't ignore them. """ - add_missing_init_files( - "client", - "server", - "services", - "tests", - msg="HOOK - on_pre_build", - ) + try: + add_missing_init_files( + "client", + "server", + "services", + msg="HOOK - on_pre_build", + ) + except BaseException as e: + logging.error(e) + remove_missing_init_files( + msg="HOOK - on_post_build: cleaning up on error !" + ) + raise def on_post_build(config): diff --git a/poetry.lock b/poetry.lock index 40a6887567..96e1dc0f4c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -842,6 +842,22 @@ mkdocs-autorefs = ">=1.4" mkdocstrings = ">=0.28.3" typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} +[[package]] +name = "mkdocstrings-shell" +version = "1.0.3" +description = "A shell scripts/libraries handler for mkdocstrings." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "mkdocstrings_shell-1.0.3-py3-none-any.whl", hash = "sha256:b23ebe43d06c9c19a541548f34d42ee4e4324ae06423eba8a9136e295c67f345"}, + {file = "mkdocstrings_shell-1.0.3.tar.gz", hash = "sha256:3bdea6a1e794a5d0e15d461f33b92e0b9f3b9a1e2c33671d9a2b7d83c761096a"}, +] + +[package.dependencies] +mkdocstrings = ">=0.28.3" +shellman = ">=1.0.2" + [[package]] name = "mock" version = "5.1.0" @@ -1269,6 +1285,23 @@ files = [ {file = "semver-3.0.4.tar.gz", hash = "sha256:afc7d8c584a5ed0a11033af086e8af226a9c0b206f313e0301f8dd7b6b589602"}, ] +[[package]] +name = "shellman" +version = "1.0.2" +description = "Write documentation in comments and render it with templates." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "shellman-1.0.2-py3-none-any.whl", hash = "sha256:f8c960fd2d3785e195f86fcd8f110a8d51a950e759d82c14a5af0bd71b918b3c"}, + {file = "shellman-1.0.2.tar.gz", hash = "sha256:48cba79d6415c0d013ad4dfd2205ed81b0e468795d1886dcda943ac78eaffd38"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} +jinja2 = ">=3" +typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} + [[package]] name = "six" version = "1.17.0" @@ -1479,4 +1512,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.9.1,<3.10" -content-hash = "58c2656b970622b91e31e92602f4a80d65ac07c8a11d61b6a06c3cac298616bd" +content-hash = "24b6215b9c20a4f64f844d3deb121618aef510b1c5ee54242e50305db6c0c4f4" diff --git a/pyproject.toml b/pyproject.toml index 45b91782c3..8c7ea9aec2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,7 @@ markdown-checklist = "^0.4.4" mdx-gh-links = "^0.4" pymdown-extensions = "^10.14.3" mike = "^2.1.3" +mkdocstrings-shell = "^1.0.2" [tool.ruff]