# -*- coding: utf-8 -*-"""Comprehensive Automation Namespace for Python Project OperationsThis module provides a unified interface for managing various aspects of a Python projectlifecycle, including virtual environment, dependencies, testing, documentation,build, and publishing processes.The PyWf (Python Workflow) class consolidates multiple operational concerns into asingle, cohesive management system, enabling streamlined project automation.The class uses a composition-based approach, inheriting from multiple specializednamespace classes to provide a comprehensive project management toolkit."""importtypingasTtry:importtomllibexceptImportError:# pragma: no coverimporttomlastomllibimportdataclassesfrompathlibimportPathfromfunctoolsimportcached_propertyfrom.vendor.home_secretimporthsfrom.define_01_pathsimportPyWfPathsfrom.define_02_venvimportPyWfVenvfrom.define_03_depsimportPyWfDepsfrom.define_04_testsimportPyWfTestsfrom.define_05_docsimportPyWfDocsfrom.define_06_buildimportPyWfBuildfrom.define_07_publishimportPyWfPublishfrom.define_08_saasimportPyWfSaas
[docs]@dataclasses.dataclassclassPyWf(PyWfPaths,PyWfVenv,PyWfDeps,PyWfTests,PyWfDocs,PyWfBuild,PyWfPublish,PyWfSaas,):""" Unified Automation Interface for Python Project Management :param dir_project_root: Root directory of the project, typically the git repository root. It has to have a ``pyproject.toml`` file in it. :param toml_data: Parsed configuration data from ``pyproject.toml`` """dir_project_root:Path=dataclasses.field()toml_data:T.Dict[str,T.Any]=dataclasses.field()# --------------------------------------------------------------------------# [project] Configuration Properties# --------------------------------------------------------------------------@propertydefpackage_name(self)->str:"""Retrieve the package name from pyproject.toml."""returnself.toml_data["project"]["name"]@propertydefpackage_version(self)->str:"""Retrieve the package version from pyproject.toml."""returnself.toml_data["project"]["version"]@propertydefpackage_license(self)->str:"""Retrieve the package license from pyproject.toml."""returnself.toml_data["project"]["license"]@propertydefpackage_description(self)->str:"""Retrieve the package description from pyproject.toml."""returnself.toml_data["project"]["description"]@propertydefpackage_author_name(self)->str:"""Retrieve the primary author's name from pyproject.toml."""returnself.toml_data["project"]["authors"][0]["name"]@propertydefpackage_author_email(self)->str:"""Retrieve the primary author's email from pyproject.toml."""returnself.toml_data["project"]["authors"][0]["email"]@propertydefpackage_maintainer_name(self)->str:"""Retrieve the primary maintainer's name from pyproject.toml."""returnself.toml_data["project"]["maintainers"][0]["name"]@propertydefpackage_maintainer_email(self)->str:"""Retrieve the primary maintainer's email from pyproject.toml."""returnself.toml_data["project"]["maintainers"][0]["email"]# --------------------------------------------------------------------------# [tool.pywf] Configuration Properties# --------------------------------------------------------------------------@propertydefpy_ver_major(self)->int:"""Extract major version number from development Python version."""returnint(self.toml_data["tool"]["pywf"]["dev_python"].split(".")[0])@propertydefpy_ver_minor(self)->int:"""Extract minor version number from development Python version."""returnint(self.toml_data["tool"]["pywf"]["dev_python"].split(".")[1])@propertydefpy_ver_micro(self)->int:"""Extract micro version number from development Python version."""returnint(self.toml_data["tool"]["pywf"]["dev_python"].split(".")[2])# --- GitHub.com@propertydefgithub_account(self)->str:returnself.toml_data["tool"]["pywf"]["github_account"]@propertydefgithub_token_field(self)->str:returnself.toml_data["tool"]["pywf"]["github_token_field"]@cached_propertydefgithub_token(self:"PyWf")->str:# pragma: no coverreturnhs.v(self.github_token_field)@propertydefgit_repo_name(self)->str:""" Git repo name. """returnself.dir_project_root.name@propertydefgithub_repo_fullname(self)->str:returnf"{self.github_account}/{self.git_repo_name}"@propertydefgithub_repo_url(self)->str:returnf"https://github.com/{self.github_repo_fullname}"@propertydefgithub_actions_secrets_settings_url(self)->str:returnf"{self.github_repo_url}/settings/secrets/actions"@propertydefgithub_versioned_release_url(self)->str:returnf"{self.github_repo_url}/releases/tag/{self.package_version}"# --- codecov.io@propertydefcodecov_account(self)->str:returnself.toml_data["tool"]["pywf"]["codecov_account"]@propertydefcodecov_token_field(self)->str:returnself.toml_data["tool"]["pywf"]["codecov_token_field"]@cached_propertydefcodecov_token(self)->str:# pragma: no coverreturnhs.v(self.codecov_token_field)# --- readthedocs.org@propertydefreadthedocs_token_field(self)->str:returnself.toml_data["tool"]["pywf"]["readthedocs_token_field"]@cached_propertydefreadthedocs_token(self)->str:# pragma: no coverreturnhs.v(self.readthedocs_token_field)@propertydefreadthedocs_project_name(self)->str:returnself.toml_data["tool"]["pywf"]["readthedocs_project_name"]@propertydefreadthedocs_project_name_slug(self)->str:returnself.readthedocs_project_name.replace("_","-")def_validate_paths(self):""" Validate project root directory and package structure. Checks: - Verify presence of ``pyproject.toml`` - Confirm ``package/__init__.py`` exists """ifisinstance(self.dir_project_root,Path)isFalse:# pragma: no coverself.dir_project_root=Path(self.dir_project_root)if(self.dir_project_root.joinpath("pyproject.toml").exists()isFalse):# pragma: no coverraiseValueError(f"{self.dir_project_root} does not have a pyproject.toml file! "f"it might not be a valid project root directory.")dir_python_lib=self.dir_project_root.joinpath(self.package_name)ifdir_python_lib.joinpath("__init__.py").exists()isFalse:# pragma: no coverraiseValueError(f"{dir_python_lib} does not have a __init__.py file, "f"the package name {self.package_name} might be invalid.")def_validate_python_version(self):""" Validate the Python version used in the project. """ifself.py_ver_major!=3:# pragma: no coverraiseValueError(f"Python major version has to be 3, but got {self.py_ver_major}.")ifself.py_ver_minor<11:# pragma: no coverraiseValueError(f"PyWf tool only support Python3.11+, but got {self.py_ver_major}.{self.py_ver_minor}")def_update_version_file(self):""" Update the version file with current project metadata in ``pyproject.toml``. """dir_here=Path(__file__).absolute().parentpath_version_tpl=dir_here/"_version.tpl"content=path_version_tpl.read_text(encoding="utf-8").format(version=self.package_version,description=self.package_description,license=self.package_license,author=self.package_author_name,author_email=self.package_author_email,maintainer=self.package_maintainer_name,maintainer_email=self.package_maintainer_email,)self.path_version_py.write_text(content,encoding="utf-8")def__post_init__(self):self._validate_paths()self._validate_python_version()self._update_version_file()
[docs]@classmethoddeffrom_pyproject_toml(cls,path_pyproject_toml:Path,):""" Create a :class:`PyWf` instance from a pyproject.toml file. """path_pyproject_toml=Path(path_pyproject_toml)toml_data=tomllib.loads(path_pyproject_toml.read_text(encoding="utf-8"))returncls(dir_project_root=path_pyproject_toml.parent,toml_data=toml_data,)