mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-30 17:53:31 -04: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()
 |