mirror of
https://github.com/kristoferssolo/School.git
synced 2025-10-21 20:10:38 +00:00
213 lines
6.6 KiB
Python
213 lines
6.6 KiB
Python
""" configuration """
|
|
import os
|
|
import re
|
|
import warnings
|
|
|
|
from ._version_cls import NonNormalizedVersion
|
|
from ._version_cls import Version
|
|
from .utils import trace
|
|
|
|
DEFAULT_TAG_REGEX = r"^(?:[\w-]+-)?(?P<version>[vV]?\d+(?:\.\d+){0,2}[^\+]*)(?:\+.*)?$"
|
|
DEFAULT_VERSION_SCHEME = "guess-next-dev"
|
|
DEFAULT_LOCAL_SCHEME = "node-and-date"
|
|
|
|
|
|
def _check_tag_regex(value):
|
|
if not value:
|
|
value = DEFAULT_TAG_REGEX
|
|
regex = re.compile(value)
|
|
|
|
group_names = regex.groupindex.keys()
|
|
if regex.groups == 0 or (regex.groups > 1 and "version" not in group_names):
|
|
warnings.warn(
|
|
"Expected tag_regex to contain a single match group or a group named"
|
|
" 'version' to identify the version part of any tag."
|
|
)
|
|
|
|
return regex
|
|
|
|
|
|
def _check_absolute_root(root, relative_to):
|
|
trace("l", repr(locals()))
|
|
if relative_to:
|
|
if os.path.isabs(root) and not root.startswith(relative_to):
|
|
warnings.warn(
|
|
"absolute root path '%s' overrides relative_to '%s'"
|
|
% (root, relative_to)
|
|
)
|
|
if os.path.isdir(relative_to):
|
|
warnings.warn(
|
|
"relative_to is expected to be a file,"
|
|
" its the directory %r\n"
|
|
"assuming the parent directory was passed" % (relative_to,)
|
|
)
|
|
trace("dir", relative_to)
|
|
root = os.path.join(relative_to, root)
|
|
else:
|
|
trace("file", relative_to)
|
|
root = os.path.join(os.path.dirname(relative_to), root)
|
|
return os.path.abspath(root)
|
|
|
|
|
|
def _lazy_tomli_load(data):
|
|
from tomli import loads
|
|
|
|
return loads(data)
|
|
|
|
|
|
class Configuration:
|
|
"""Global configuration model"""
|
|
|
|
def __init__(
|
|
self,
|
|
relative_to=None,
|
|
root=".",
|
|
version_scheme=DEFAULT_VERSION_SCHEME,
|
|
local_scheme=DEFAULT_LOCAL_SCHEME,
|
|
write_to=None,
|
|
write_to_template=None,
|
|
tag_regex=DEFAULT_TAG_REGEX,
|
|
parentdir_prefix_version=None,
|
|
fallback_version=None,
|
|
fallback_root=".",
|
|
parse=None,
|
|
git_describe_command=None,
|
|
dist_name=None,
|
|
version_cls=None,
|
|
normalize=True,
|
|
search_parent_directories=False,
|
|
):
|
|
# TODO:
|
|
self._relative_to = relative_to
|
|
self._root = "."
|
|
|
|
self.root = root
|
|
self.version_scheme = version_scheme
|
|
self.local_scheme = local_scheme
|
|
self.write_to = write_to
|
|
self.write_to_template = write_to_template
|
|
self.parentdir_prefix_version = parentdir_prefix_version
|
|
self.fallback_version = fallback_version
|
|
self.fallback_root = fallback_root
|
|
self.parse = parse
|
|
self.tag_regex = tag_regex
|
|
self.git_describe_command = git_describe_command
|
|
self.dist_name = dist_name
|
|
self.search_parent_directories = search_parent_directories
|
|
self.parent = None
|
|
|
|
if not normalize:
|
|
# `normalize = False` means `version_cls = NonNormalizedVersion`
|
|
if version_cls is not None:
|
|
raise ValueError(
|
|
"Providing a custom `version_cls` is not permitted when "
|
|
"`normalize=False`"
|
|
)
|
|
self.version_cls = NonNormalizedVersion
|
|
else:
|
|
# Use `version_cls` if provided, default to packaging or pkg_resources
|
|
if version_cls is None:
|
|
version_cls = Version
|
|
elif isinstance(version_cls, str):
|
|
try:
|
|
# Not sure this will work in old python
|
|
import importlib
|
|
|
|
pkg, cls_name = version_cls.rsplit(".", 1)
|
|
version_cls_host = importlib.import_module(pkg)
|
|
version_cls = getattr(version_cls_host, cls_name)
|
|
except: # noqa
|
|
raise ValueError(f"Unable to import version_cls='{version_cls}'")
|
|
self.version_cls = version_cls
|
|
|
|
@property
|
|
def fallback_root(self):
|
|
return self._fallback_root
|
|
|
|
@fallback_root.setter
|
|
def fallback_root(self, value):
|
|
self._fallback_root = os.path.abspath(value)
|
|
|
|
@property
|
|
def absolute_root(self):
|
|
return self._absolute_root
|
|
|
|
@property
|
|
def relative_to(self):
|
|
return self._relative_to
|
|
|
|
@relative_to.setter
|
|
def relative_to(self, value):
|
|
self._absolute_root = _check_absolute_root(self._root, value)
|
|
self._relative_to = value
|
|
trace("root", repr(self._absolute_root))
|
|
trace("relative_to", repr(value))
|
|
|
|
@property
|
|
def root(self):
|
|
return self._root
|
|
|
|
@root.setter
|
|
def root(self, value):
|
|
self._absolute_root = _check_absolute_root(value, self._relative_to)
|
|
self._root = value
|
|
trace("root", repr(self._absolute_root))
|
|
trace("relative_to", repr(self._relative_to))
|
|
|
|
@property
|
|
def tag_regex(self):
|
|
return self._tag_regex
|
|
|
|
@tag_regex.setter
|
|
def tag_regex(self, value):
|
|
self._tag_regex = _check_tag_regex(value)
|
|
|
|
@classmethod
|
|
def from_file(
|
|
cls,
|
|
name: str = "pyproject.toml",
|
|
dist_name=None, # type: str | None
|
|
_load_toml=_lazy_tomli_load,
|
|
):
|
|
"""
|
|
Read Configuration from pyproject.toml (or similar).
|
|
Raises exceptions when file is not found or toml is
|
|
not installed or the file has invalid format or does
|
|
not contain the [tool.setuptools_scm] section.
|
|
"""
|
|
|
|
with open(name, encoding="UTF-8") as strm:
|
|
data = strm.read()
|
|
defn = _load_toml(data)
|
|
try:
|
|
section = defn.get("tool", {})["setuptools_scm"]
|
|
except LookupError as e:
|
|
raise LookupError(
|
|
f"{name} does not contain a tool.setuptools_scm section"
|
|
) from e
|
|
if "dist_name" in section:
|
|
if dist_name is None:
|
|
dist_name = section.pop("dist_name")
|
|
else:
|
|
assert dist_name == section["dist_name"]
|
|
del section["dist_name"]
|
|
if dist_name is None:
|
|
if "project" in defn:
|
|
# minimal pep 621 support for figuring the pretend keys
|
|
dist_name = defn["project"].get("name")
|
|
if dist_name is None:
|
|
dist_name = _read_dist_name_from_setup_cfg()
|
|
|
|
return cls(dist_name=dist_name, **section)
|
|
|
|
|
|
def _read_dist_name_from_setup_cfg():
|
|
|
|
# minimal effort to read dist_name off setup.cfg metadata
|
|
import configparser
|
|
|
|
parser = configparser.ConfigParser()
|
|
parser.read(["setup.cfg"])
|
|
dist_name = parser.get("metadata", "name", fallback=None)
|
|
return dist_name
|