mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-11-04 03:03:18 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			109 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import pathlib
 | 
						|
import re
 | 
						|
import subprocess
 | 
						|
from dataclasses import dataclass, field
 | 
						|
 | 
						|
from utils import PROJECT_DIR, log, render_python_template
 | 
						|
 | 
						|
template = """# This file is auto-generated by gen_schema_exports.py
 | 
						|
{% for file in data.module.files %}{{ file.import_str() }}
 | 
						|
{% endfor %}
 | 
						|
 | 
						|
__all__ = [
 | 
						|
    {% for file in data.module.files %}
 | 
						|
    {%- for class in file.classes -%}
 | 
						|
    "{{ class }}",
 | 
						|
    {%- endfor -%}
 | 
						|
    {%- endfor %}
 | 
						|
]
 | 
						|
 | 
						|
"""
 | 
						|
 | 
						|
SCHEMA_PATH = PROJECT_DIR / "mealie" / "schema"
 | 
						|
 | 
						|
SKIP = {"static", "__pycache__"}
 | 
						|
 | 
						|
 | 
						|
class PyFile:
 | 
						|
    import_path: str
 | 
						|
    """The import path of the file"""
 | 
						|
 | 
						|
    classes: list[str]
 | 
						|
    """A list of classes in the file"""
 | 
						|
 | 
						|
    def __init__(self, path: pathlib.Path):
 | 
						|
        self.import_path = path.stem
 | 
						|
        self.classes = []
 | 
						|
 | 
						|
        self.classes = PyFile.extract_classes(path)
 | 
						|
        self.classes.sort()
 | 
						|
 | 
						|
    def import_str(self) -> str:
 | 
						|
        """Returns a string that can be used to import the file"""
 | 
						|
        return f"from .{self.import_path} import {', '.join(self.classes)}"
 | 
						|
 | 
						|
    @staticmethod
 | 
						|
    def extract_classes(file_path: pathlib.Path) -> list[str]:
 | 
						|
        name = file_path.stem
 | 
						|
 | 
						|
        if name == "__init__" or name.startswith("_"):
 | 
						|
            return []
 | 
						|
 | 
						|
        classes = re.findall(r"(?m)^class\s(\w+)", file_path.read_text())
 | 
						|
        return classes
 | 
						|
 | 
						|
 | 
						|
@dataclass
 | 
						|
class Modules:
 | 
						|
    directory: pathlib.Path
 | 
						|
    """The directory to search for modules"""
 | 
						|
 | 
						|
    files: list[PyFile] = field(default_factory=list)
 | 
						|
    """A list of files in the directory"""
 | 
						|
 | 
						|
    def __post_init__(self):
 | 
						|
        for file in self.directory.glob("*.py"):
 | 
						|
            if file.name.startswith("_"):
 | 
						|
                continue
 | 
						|
 | 
						|
            pfile = PyFile(file)
 | 
						|
 | 
						|
            if len(pfile.classes) > 0:
 | 
						|
                self.files.append(pfile)
 | 
						|
 | 
						|
            else:
 | 
						|
                log.debug(f"Skipping {file.name} as it has no classes")
 | 
						|
 | 
						|
 | 
						|
def find_modules(root: pathlib.Path) -> list[Modules]:
 | 
						|
    """Finds all the top level modules in the provided folder"""
 | 
						|
    modules: list[Modules] = []
 | 
						|
    for file in root.iterdir():
 | 
						|
        if file.is_dir() and file.name not in SKIP:
 | 
						|
            modules.append(Modules(directory=file))
 | 
						|
 | 
						|
    return modules
 | 
						|
 | 
						|
 | 
						|
def main() -> None:
 | 
						|
    modules = find_modules(SCHEMA_PATH)
 | 
						|
 | 
						|
    template_paths: list[pathlib.Path] = []
 | 
						|
    for module in modules:
 | 
						|
        log.debug(f"Module: {module.directory.name}")
 | 
						|
        for file in module.files:
 | 
						|
            log.debug(f"  File: {file.import_path}")
 | 
						|
            log.debug(f"    Classes: [{', '.join(file.classes)}]")
 | 
						|
 | 
						|
        template_path = module.directory / "__init__.py"
 | 
						|
        template_paths.append(template_path)
 | 
						|
        render_python_template(template, template_path, {"module": module})
 | 
						|
 | 
						|
    path_args = (str(p) for p in template_paths)
 | 
						|
    subprocess.run(["poetry", "run", "ruff", "check", *path_args, "--fix"])
 | 
						|
    subprocess.run(["poetry", "run", "ruff", "format", *path_args])
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    main()
 |