Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dynamic version from environment variable #3885

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add dynamic version retrieve from an environment variable
  • Loading branch information
IlyaMichlin committed Apr 6, 2023
commit 34f78b7c1ae936c4f9dc7b85fa1c5a2f19654674
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,11 @@ def validate_https___setuptools_pypa_io_en_latest_references_keywords_html(data,
validate_https___setuptools_pypa_io_en_latest_references_keywords_html__definitions_file_directive(data__dynamic__version, custom_formats, (name_prefix or "data") + ".dynamic.version")
data__dynamic__version_one_of_count5 += 1
except JsonSchemaValueException: pass
if data__dynamic__version_one_of_count5 < 2:
try:
validate_https___setuptools_pypa_io_en_latest_references_keywords_html__definitions_env_directive(data__dynamic__version, custom_formats, (name_prefix or "data") + ".dynamic.version")
data__dynamic__version_one_of_count5 += 1
except JsonSchemaValueException: pass
if data__dynamic__version_one_of_count5 != 1:
raise JsonSchemaValueException("" + (name_prefix or "data") + ".dynamic.version must be valid exactly by one definition" + (" (" + str(data__dynamic__version_one_of_count5) + " matches found)"), value=data__dynamic__version, name="" + (name_prefix or "data") + ".dynamic.version", definition={'$$description': ['A version dynamically loaded via either the ``attr:`` or ``file:``', 'directives. Please make sure the given file or attribute respects :pep:`440`.'], 'oneOf': [{'title': "'attr:' directive", '$id': '#/definitions/attr-directive', '$$description': ['Value is read from a module attribute. Supports callables and iterables;', 'unsupported types are cast via ``str()``'], 'type': 'object', 'additionalProperties': False, 'properties': {'attr': {'type': 'string'}}, 'required': ['attr']}, {'$id': '#/definitions/file-directive', 'title': "'file:' directive", 'description': 'Value is read from a file (or list of files and then concatenated)', 'type': 'object', 'additionalProperties': False, 'properties': {'file': {'oneOf': [{'type': 'string'}, {'type': 'array', 'items': {'type': 'string'}}]}}, 'required': ['file']}]}, rule='oneOf')
if "classifiers" in data__dynamic_keys:
Expand Down Expand Up @@ -565,6 +570,24 @@ def validate_https___setuptools_pypa_io_en_latest_references_keywords_html__defi
raise JsonSchemaValueException("" + (name_prefix or "data") + " must not contain "+str(data_keys)+" properties", value=data, name="" + (name_prefix or "data") + "", definition={'title': "'attr:' directive", '$id': '#/definitions/attr-directive', '$$description': ['Value is read from a module attribute. Supports callables and iterables;', 'unsupported types are cast via ``str()``'], 'type': 'object', 'additionalProperties': False, 'properties': {'attr': {'type': 'string'}}, 'required': ['attr']}, rule='additionalProperties')
return data

def validate_https___setuptools_pypa_io_en_latest_references_keywords_html__definitions_env_directive(data, custom_formats={}, name_prefix=None):
if not isinstance(data, (dict)):
raise JsonSchemaValueException("" + (name_prefix or "data") + " must be object", value=data, name="" + (name_prefix or "data") + "", definition={'title': "'env:' directive", '$id': '#/definitions/env-directive', 'description': 'Value is read from an environment variable', 'type': 'object', 'additionalProperties': False, 'properties': {'env': 'string'}, 'required': ['env']}, rule='type')
data_is_dict = isinstance(data, dict)
if data_is_dict:
data_len = len(data)
if not all(prop in data for prop in ['env']):
raise JsonSchemaValueException("" + (name_prefix or "data") + " must contain ['env'] properties", value=data, name="" + (name_prefix or "data") + "", definition={'title': "'env:' directive", '$id': '#/definitions/env-directive', 'description': 'Value is read from an environment variable', 'type': 'object', 'additionalProperties': False, 'properties': {'env': 'string'}, 'required': ['env']}, rule='required')
data_keys = set(data.keys())
if "env" in data_keys:
data_keys.remove("env")
data__env = data["env"]
if not isinstance(data__env, (str)):
raise JsonSchemaValueException("" + (name_prefix or "data") + ".attr must be string", value=data__env, name="" + (name_prefix or "data") + ".env", definition={'type': 'string'}, rule='type')
if data_keys:
raise JsonSchemaValueException("" + (name_prefix or "data") + " must not contain "+str(data_keys)+" properties", value=data, name="" + (name_prefix or "data") + "", definition={'title': "'env:' directive", '$id': '#/definitions/env-directive', '$$description': ['Value is read from a module attribute. Supports callables and iterables;', 'unsupported types are cast via ``str()``'], 'type': 'object', 'additionalProperties': False, 'properties': {'attr': {'type': 'string'}}, 'required': ['attr']}, rule='additionalProperties')
return data

def validate_https___setuptools_pypa_io_en_latest_references_keywords_html__definitions_find_directive(data, custom_formats={}, name_prefix=None):
if not isinstance(data, (dict)):
raise JsonSchemaValueException("" + (name_prefix or "data") + " must be object", value=data, name="" + (name_prefix or "data") + "", definition={'$id': '#/definitions/find-directive', 'title': "'find:' directive", 'type': 'object', 'additionalProperties': False, 'properties': {'find': {'type': 'object', '$$description': ['Dynamic `package discovery', '<https://setuptools.pypa.io/en/latest/userguide/package_discovery.html>`_.'], 'additionalProperties': False, 'properties': {'where': {'description': 'Directories to be searched for packages (Unix-style relative path)', 'type': 'array', 'items': {'type': 'string'}}, 'exclude': {'type': 'array', '$$description': ['Exclude packages that match the values listed in this field.', "Can container shell-style wildcards (e.g. ``'pkg.*'``)"], 'items': {'type': 'string'}}, 'include': {'type': 'array', '$$description': ['Restrict the found packages to just the ones listed in this field.', "Can container shell-style wildcards (e.g. ``'pkg.*'``)"], 'items': {'type': 'string'}}, 'namespaces': {'type': 'boolean', '$$description': ['When ``True``, directories without a ``__init__.py`` file will also', 'be scanned for :pep:`420`-style implicit namespaces']}}}}}, rule='type')
Expand Down Expand Up @@ -1049,4 +1072,4 @@ def validate_https___packaging_python_org_en_latest_specifications_declaring_pro
raise JsonSchemaValueException("" + (name_prefix or "data") + ".email must be idn-email", value=data__email, name="" + (name_prefix or "data") + ".email", definition={'type': 'string', 'format': 'idn-email', 'description': 'MUST be a valid email address'}, rule='format')
if data_keys:
raise JsonSchemaValueException("" + (name_prefix or "data") + " must not contain "+str(data_keys)+" properties", value=data, name="" + (name_prefix or "data") + "", definition={'$id': '#/definitions/author', 'title': 'Author or Maintainer', '$comment': 'https://peps.python.org/pep-0621/#authors-maintainers', 'type': 'object', 'additionalProperties': False, 'properties': {'name': {'type': 'string', '$$description': ['MUST be a valid email name, i.e. whatever can be put as a name, before an', 'email, in :rfc:`822`.']}, 'email': {'type': 'string', 'format': 'idn-email', 'description': 'MUST be a valid email address'}}}, rule='additionalProperties')
return data
return data
12 changes: 12 additions & 0 deletions setuptools/config/expand.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,18 @@ def _find_module(
return parent_path, module_path, module_name


def read_env(env_name: str):
"""Reads the value of an environment variable.

:param str env_name: Name of the environment variable
:rtype: str
"""
if env_name not in os.environ:
raise KeyError(f"Environment variable {env_name!r} not found")

return os.environ[env_name]


def resolve_class(
qualified_class_name: str,
package_dir: Optional[Mapping[str, str]] = None,
Expand Down
2 changes: 2 additions & 0 deletions setuptools/config/pyprojecttoml.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,8 @@ def _expand_directive(
return _expand.read_files(directive["file"], root_dir)
if "attr" in directive:
return _expand.read_attr(directive["attr"], package_dir, root_dir)
if "env" in directive:
return _expand.read_env(directive["env"])
raise ValueError(f"invalid `{specifier}`: {directive!r}")
return None

Expand Down