mirror of https://github.com/pypa/hatch.git
173 lines
5.2 KiB
Python
173 lines
5.2 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
from ..config.model import RootConfig
|
|
from ..utils.fs import Path
|
|
|
|
|
|
class Project:
|
|
def __init__(self, path: Path, *, name: str = None, config=None):
|
|
self._path = path
|
|
|
|
# From app config
|
|
self.chosen_name = name
|
|
|
|
# Location of pyproject.toml
|
|
self._project_file_path: Path | None = None
|
|
|
|
self._root_searched = False
|
|
self._root: Path | None = None
|
|
self._raw_config = config
|
|
self._plugin_manager = None
|
|
self._metadata = None
|
|
self._config = None
|
|
|
|
@property
|
|
def plugin_manager(self):
|
|
if self._plugin_manager is None:
|
|
from ..plugin.manager import PluginManager
|
|
|
|
self._plugin_manager = PluginManager()
|
|
|
|
return self._plugin_manager
|
|
|
|
@property
|
|
def config(self):
|
|
if self._config is None:
|
|
from .config import ProjectConfig
|
|
|
|
self._config = ProjectConfig(self.location, self.metadata.hatch.config, self.plugin_manager)
|
|
|
|
return self._config
|
|
|
|
@property
|
|
def root(self) -> Path | None:
|
|
if not self._root_searched:
|
|
self._root = self.find_project_root()
|
|
self._root_searched = True
|
|
|
|
return self._root
|
|
|
|
@property
|
|
def location(self) -> Path:
|
|
return self.root or self._path
|
|
|
|
@classmethod
|
|
def from_config(cls, config: RootConfig, project: str) -> Project | None:
|
|
# Disallow empty strings
|
|
if not project:
|
|
return None
|
|
|
|
if project in config.projects:
|
|
if location := config.projects[project].location:
|
|
return cls(Path(location).resolve(), name=project)
|
|
else:
|
|
for project_dir in config.dirs.project:
|
|
if not project_dir:
|
|
continue
|
|
|
|
if (location := Path(project_dir, project)).is_dir():
|
|
return cls(Path(location).resolve(), name=project)
|
|
|
|
def find_project_root(self) -> Path | None:
|
|
path = self._path
|
|
|
|
while True:
|
|
possible_file = path.joinpath('pyproject.toml')
|
|
if possible_file.is_file():
|
|
self._project_file_path = possible_file
|
|
return path
|
|
elif path.joinpath('setup.py').is_file():
|
|
return path
|
|
|
|
new_path = path.parent
|
|
if new_path == path:
|
|
return None
|
|
|
|
path = new_path
|
|
|
|
@staticmethod
|
|
def canonicalize_name(name: str, strict=True) -> str:
|
|
if strict:
|
|
return re.sub(r'[-_.]+', '-', name).lower()
|
|
else:
|
|
# Used for creating new projects
|
|
return re.sub(r'[-_. ]+', '-', name).lower()
|
|
|
|
@property
|
|
def metadata(self):
|
|
if self._metadata is None:
|
|
from hatchling.metadata.core import ProjectMetadata
|
|
|
|
self._metadata = ProjectMetadata(self.location, self._plugin_manager, self.raw_config)
|
|
|
|
return self._metadata
|
|
|
|
@property
|
|
def raw_config(self):
|
|
if self._raw_config is None:
|
|
if self.root is None or self._project_file_path is None:
|
|
self._raw_config = {}
|
|
else:
|
|
import tomli
|
|
|
|
with open(str(self._project_file_path), 'r', encoding='utf-8') as f:
|
|
self._raw_config = tomli.loads(f.read())
|
|
|
|
return self._raw_config
|
|
|
|
def save_config(self, config):
|
|
import tomlkit
|
|
|
|
with open(str(self._project_file_path), 'w', encoding='utf-8') as f:
|
|
f.write(tomlkit.dumps(config))
|
|
|
|
@staticmethod
|
|
def initialize(project_file_path, template_config):
|
|
import tomlkit
|
|
|
|
with open(str(project_file_path), 'r', encoding='utf-8') as f:
|
|
raw_config = tomlkit.parse(f.read())
|
|
|
|
# https://github.com/sdispater/tomlkit/issues/49
|
|
build_system_config = raw_config.get('build-system')
|
|
if build_system_config is None:
|
|
raw_config['build-system'] = build_system_config = {}
|
|
|
|
build_system_config.clear()
|
|
build_system_config['requires'] = ['hatchling']
|
|
build_system_config['build-backend'] = 'hatchling.build'
|
|
|
|
project_config = raw_config.get('project')
|
|
if project_config is None:
|
|
raw_config['project'] = project_config = {}
|
|
|
|
project_name = project_config.get('name')
|
|
if not project_name:
|
|
project_config['name'] = template_config['project_name_normalized']
|
|
|
|
project_description = project_config.get('description')
|
|
if not project_description:
|
|
project_config['description'] = template_config['description']
|
|
|
|
project_config['dynamic'] = ['version']
|
|
|
|
tool_config = raw_config.get('tool')
|
|
if tool_config is None:
|
|
raw_config['tool'] = tool_config = {}
|
|
|
|
hatch_config = tool_config.get('hatch')
|
|
if hatch_config is None:
|
|
tool_config['hatch'] = hatch_config = {}
|
|
|
|
version_config = hatch_config.get('version')
|
|
if version_config is None:
|
|
hatch_config['version'] = version_config = {}
|
|
|
|
version_config.clear()
|
|
version_config['path'] = f'{template_config["package_name"]}/__init__.py'
|
|
|
|
with open(str(project_file_path), 'w', encoding='utf-8') as f:
|
|
f.write(tomlkit.dumps(raw_config))
|