From 9824d97f41bd4cdb7a0951f9390203fd227c8d84 Mon Sep 17 00:00:00 2001 From: Benjamin Lowry Date: Sun, 25 Aug 2024 17:41:08 -0400 Subject: [PATCH] add types for plugin and template --- pyproject.toml | 2 ++ src/hatch/plugin/manager.py | 10 +++++----- src/hatch/plugin/specs.py | 10 +++++----- src/hatch/template/__init__.py | 8 +++++--- src/hatch/template/default.py | 23 +++++++++++++++-------- src/hatch/template/plugin/hooks.py | 9 ++++++++- src/hatch/template/plugin/interface.py | 19 +++++++++++++++---- 7 files changed, 55 insertions(+), 26 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5d8b689e2..c7e678b51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,6 +102,8 @@ warn_unused_ignores = true module = [ "*.hatchling.*", "*.hatch.utils.*", + "hatch.plugin.*", + "hatch.template.*", ] disallow_untyped_defs = true disallow_incomplete_defs = true diff --git a/src/hatch/plugin/manager.py b/src/hatch/plugin/manager.py index aa02983ea..e2b93856c 100644 --- a/src/hatch/plugin/manager.py +++ b/src/hatch/plugin/manager.py @@ -2,29 +2,29 @@ class PluginManager(_PluginManager): - def initialize(self): + def initialize(self) -> None: super().initialize() from hatch.plugin import specs self.manager.add_hookspecs(specs) - def hatch_register_environment(self): + def hatch_register_environment(self) -> None: from hatch.env.plugin import hooks self.manager.register(hooks) - def hatch_register_environment_collector(self): + def hatch_register_environment_collector(self) -> None: from hatch.env.collectors.plugin import hooks self.manager.register(hooks) - def hatch_register_publisher(self): + def hatch_register_publisher(self) -> None: from hatch.publish.plugin import hooks self.manager.register(hooks) - def hatch_register_template(self): + def hatch_register_template(self) -> None: from hatch.template.plugin import hooks self.manager.register(hooks) diff --git a/src/hatch/plugin/specs.py b/src/hatch/plugin/specs.py index 8a5d83b74..87da53283 100644 --- a/src/hatch/plugin/specs.py +++ b/src/hatch/plugin/specs.py @@ -2,25 +2,25 @@ @hookspec -def hatch_register_environment(): +def hatch_register_environment() -> None: """Register new classes that adhere to the environment interface.""" @hookspec -def hatch_register_environment_collector(): +def hatch_register_environment_collector() -> None: """Register new classes that adhere to the environment collector interface.""" @hookspec -def hatch_register_version_scheme(): +def hatch_register_version_scheme() -> None: """Register new classes that adhere to the version scheme interface.""" @hookspec -def hatch_register_publisher(): +def hatch_register_publisher() -> None: """Register new classes that adhere to the publisher interface.""" @hookspec -def hatch_register_template(): +def hatch_register_template() -> None: """Register new classes that adhere to the template interface.""" diff --git a/src/hatch/template/__init__.py b/src/hatch/template/__init__.py index d1008812a..df62bc944 100644 --- a/src/hatch/template/__init__.py +++ b/src/hatch/template/__init__.py @@ -1,9 +1,11 @@ from __future__ import annotations from contextlib import suppress -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Generator if TYPE_CHECKING: + from types import ModuleType + from hatch.utils.fs import Path @@ -13,7 +15,7 @@ def __init__(self, path: Path | None, contents: str = ''): self.contents = contents self.feature = None - def write(self, root): + def write(self, root: Path) -> None: if self.path is None: # no cov return @@ -22,7 +24,7 @@ def write(self, root): path.write_text(self.contents, encoding='utf-8') -def find_template_files(module): +def find_template_files(module: ModuleType) -> Generator[File, None, None]: for name in dir(module): obj = getattr(module, name) if obj is File: diff --git a/src/hatch/template/default.py b/src/hatch/template/default.py index 71acb3e97..a06ef0043 100644 --- a/src/hatch/template/default.py +++ b/src/hatch/template/default.py @@ -1,25 +1,32 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + from hatch.template import File, files_default, find_template_files from hatch.template.plugin.interface import TemplateInterface from hatch.utils.fs import Path from hatch.utils.network import download_file +if TYPE_CHECKING: + from datetime import datetime + class DefaultTemplate(TemplateInterface): PLUGIN_NAME = 'default' - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.plugin_config.setdefault('ci', False) self.plugin_config.setdefault('src-layout', True) self.plugin_config.setdefault('tests', True) - def initialize_config(self, config): + def initialize_config(self, config: dict) -> None: # Default values config['readme_file_path'] = 'README.md' config['package_metadata_file_path'] = f'src/{config["package_name"]}/__about__.py' - license_data = {} + license_data: dict[str, str] = {} # Licenses license_ids = config['licenses']['default'] @@ -73,7 +80,7 @@ def initialize_config(self, config): if not self.plugin_config['src-layout']: config['package_metadata_file_path'] = f'{config["package_metadata_file_path"][4:]}' - def get_files(self, config): + def get_files(self, config: dict) -> list[File]: files = list(find_template_files(files_default)) # Add any licenses @@ -106,19 +113,19 @@ def get_files(self, config): return files - def finalize_files(self, config, files): + def finalize_files(self, config: dict, files: list[File]) -> None: if config['licenses']['headers'] and config['license_data']: for template_file in files: - if template_file.path.name.endswith('.py'): + if template_file.path and template_file.path.name.endswith('.py'): template_file.contents = config['license_header'] + template_file.contents if self.plugin_config['src-layout']: for template_file in files: - if template_file.path.parts[0] == config['package_name']: + if template_file.path and template_file.path.parts[0] == config['package_name']: template_file.path = Path('src', template_file.path) -def get_license_text(config, license_id, license_text, creation_time): +def get_license_text(config: dict, license_id: str, license_text: str, creation_time: datetime) -> str: if license_id == 'MIT': license_text = license_text.replace('', f'{creation_time.year}-present', 1) license_text = license_text.replace('', f'{config["name"]} <{config["email"]}>', 1) diff --git a/src/hatch/template/plugin/hooks.py b/src/hatch/template/plugin/hooks.py index 08953b50d..8336cab3d 100644 --- a/src/hatch/template/plugin/hooks.py +++ b/src/hatch/template/plugin/hooks.py @@ -1,7 +1,14 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + from hatch.template.default import DefaultTemplate from hatchling.plugin import hookimpl +if TYPE_CHECKING: + from hatch.template.plugin.interface import TemplateInterface + @hookimpl -def hatch_register_template(): +def hatch_register_template() -> type[TemplateInterface]: return DefaultTemplate diff --git a/src/hatch/template/plugin/interface.py b/src/hatch/template/plugin/interface.py index 2a361c666..edd686e00 100644 --- a/src/hatch/template/plugin/interface.py +++ b/src/hatch/template/plugin/interface.py @@ -1,21 +1,32 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from datetime import datetime + + from hatch.template import File + from hatch.utils.fs import Path + + class TemplateInterface: PLUGIN_NAME = '' PRIORITY = 100 - def __init__(self, plugin_config: dict, cache_dir, creation_time): + def __init__(self, plugin_config: dict, cache_dir: Path, creation_time: datetime) -> None: self.plugin_config = plugin_config self.cache_dir = cache_dir self.creation_time = creation_time - def initialize_config(self, config): + def initialize_config(self, config: dict) -> None: """ Allow modification of the configuration passed to every file for new projects before the list of files are determined. """ - def get_files(self, config): # noqa: ARG002, PLR6301 + def get_files(self, config: dict) -> list[File]: # noqa: ARG002, PLR6301 """Add to the list of files for new projects that are written to the file system.""" return [] - def finalize_files(self, config, files): + def finalize_files(self, config: dict, files: list[File]) -> None: """Allow modification of files for new projects before they are written to the file system."""