1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
|
# Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
import importlib.metadata
import re
import sys
from pathlib import Path
from constants import (
BOOTSTRAP_REQUIREMENTS,
PORTABLE_EXE_REQUIREMENTS,
)
from utils import (
UnmetDependenciesException,
get_install_requires,
parse_requirements,
)
ROOT = Path(__file__).parents[2]
PYPROJECT = ROOT / "pyproject.toml"
BUILD_REQS_RE = re.compile(r"requires = \[([\s\S]+?)\]\s", re.MULTILINE)
EXTRACT_DEPENDENCIES_RE = re.compile(r'"(.+)"')
def validate_env(target_artifact):
requirements = _get_requires_list(target_artifact)
unmet_deps = _get_unmet_dependencies(requirements)
if unmet_deps:
in_venv = sys.prefix != sys.base_prefix
raise UnmetDependenciesException(unmet_deps, in_venv)
def _get_requires_list(target_artifact):
requires_list = _parse_pyproject_requirements()
requires_list += _parse_requirements(BOOTSTRAP_REQUIREMENTS)
requires_list += get_install_requires()
if target_artifact == "portable-exe":
requires_list += _parse_requirements(PORTABLE_EXE_REQUIREMENTS)
return parse_requirements(requires_list)
def _parse_pyproject_requirements():
with open(PYPROJECT) as f:
data = f.read()
raw_dependencies = BUILD_REQS_RE.findall(data)[0]
dependencies = EXTRACT_DEPENDENCIES_RE.findall(raw_dependencies)
return list(dependencies)
def _parse_requirements(requirements_file):
requirements = []
with open(requirements_file) as f:
for line in f.readlines():
if not line.startswith(("-r", "#")):
requirements.append(line.strip())
return requirements
def _get_unmet_dependencies(requirements):
unmet = []
checked = set()
for requirement in requirements:
project_name = requirement.name
if project_name in checked:
continue
checked.add(project_name)
try:
actual_version = importlib.metadata.version(project_name)
except importlib.metadata.PackageNotFoundError:
try:
# Packages built from source may have directory names
# that replace "." with "_".
actual_version = importlib.metadata.version(
project_name.replace(".", "_")
)
except importlib.metadata.PackageNotFoundError:
unmet.append((project_name, None, requirement))
continue
if not requirement.is_in_range(actual_version):
unmet.append((project_name, actual_version, requirement))
return unmet
|