from __future__ import annotations from typing import Any from hatchling.builders.hooks.plugin.interface import BuildHookInterface from hatchling.version.core import VersionFile class VersionBuildHook(BuildHookInterface): PLUGIN_NAME = 'version' def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.__config_path: str | None = None self.__config_template: str | None = None self.__config_pattern: str | bool | None = None @property def config_path(self) -> str: if self.__config_path is None: path = self.config.get('path', '') if not isinstance(path, str): message = f'Option `path` for build hook `{self.PLUGIN_NAME}` must be a string' raise TypeError(message) if not path: message = f'Option `path` for build hook `{self.PLUGIN_NAME}` is required' raise ValueError(message) self.__config_path = path return self.__config_path @property def config_template(self) -> str: if self.__config_template is None: template = self.config.get('template', '') if not isinstance(template, str): message = f'Option `template` for build hook `{self.PLUGIN_NAME}` must be a string' raise TypeError(message) self.__config_template = template return self.__config_template @property def config_pattern(self) -> str | bool: if self.__config_pattern is None: pattern = self.config.get('pattern', '') if not isinstance(pattern, (str, bool)): message = f'Option `pattern` for build hook `{self.PLUGIN_NAME}` must be a string or a boolean' raise TypeError(message) self.__config_pattern = pattern return self.__config_pattern def initialize( self, version: str, # noqa: ARG002 build_data: dict[str, Any], ) -> None: version_file = VersionFile(self.root, self.config_path) if self.config_pattern: version_file.read(pattern=self.config_pattern) version_file.set_version(self.metadata.version) else: version_file.write(self.metadata.version, self.config_template) build_data['artifacts'].append(f'/{self.config_path}')