from __future__ import annotations import re from typing import TYPE_CHECKING, Any if TYPE_CHECKING: from packaging.requirements import Requirement from hatchling.metadata.core import ProjectMetadata # NOTE: this module should rarely be changed because it is likely to be used by other packages like Hatch def is_valid_project_name(project_name: str) -> bool: # https://peps.python.org/pep-0508/#names return re.search('^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$', project_name, re.IGNORECASE) is not None def normalize_project_name(project_name: str) -> str: # https://peps.python.org/pep-0503/#normalized-names return re.sub(r'[-_.]+', '-', project_name).lower() def get_normalized_dependency(requirement: Requirement) -> str: # Changes to this function affect reproducibility between versions from packaging.specifiers import SpecifierSet requirement.name = normalize_project_name(requirement.name) if requirement.specifier: requirement.specifier = SpecifierSet(str(requirement.specifier).lower()) if requirement.extras: requirement.extras = {normalize_project_name(extra) for extra in requirement.extras} # All TOML writers use double quotes, so allow direct writing or copy/pasting to avoid escaping return str(requirement).replace('"', "'") def resolve_metadata_fields(metadata: ProjectMetadata) -> dict[str, Any]: # https://packaging.python.org/en/latest/specifications/declaring-project-metadata/ return { 'name': metadata.core.name, 'version': metadata.version, 'description': metadata.core.description, 'readme': {'content-type': metadata.core.readme_content_type, 'text': metadata.core.readme}, 'requires-python': metadata.core.requires_python, 'license': metadata.core.license_expression or metadata.core.license, 'authors': metadata.core.authors, 'maintainers': metadata.core.maintainers, 'keywords': metadata.core.keywords, 'classifiers': metadata.core.classifiers, 'urls': metadata.core.urls, 'scripts': metadata.core.scripts, 'gui-scripts': metadata.core.gui_scripts, 'entry-points': metadata.core.entry_points, 'dependencies': metadata.core.dependencies, 'optional-dependencies': metadata.core.optional_dependencies, }