|
@@ -16,7 +16,12 @@
|
|
|
|
|
|
import logging
|
|
|
|
|
|
-from pkg_resources import DistributionNotFound, VersionConflict, get_distribution
|
|
|
+from pkg_resources import (
|
|
|
+ DistributionNotFound,
|
|
|
+ Requirement,
|
|
|
+ VersionConflict,
|
|
|
+ get_provider,
|
|
|
+)
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
@@ -91,7 +96,13 @@ CONDITIONAL_REQUIREMENTS = {
|
|
|
|
|
|
# ACME support is required to provision TLS certificates from authorities
|
|
|
# that use the protocol, such as Let's Encrypt.
|
|
|
- "acme": ["txacme>=0.9.2"],
|
|
|
+ "acme": [
|
|
|
+ "txacme>=0.9.2",
|
|
|
+
|
|
|
+ # txacme depends on eliot. Eliot 1.8.0 is incompatible with
|
|
|
+ # python 3.5.2, as per https://github.com/itamarst/eliot/issues/418
|
|
|
+ 'eliot<1.8.0;python_version<"3.5.3"',
|
|
|
+ ],
|
|
|
|
|
|
"saml2": ["pysaml2>=4.5.0"],
|
|
|
"systemd": ["systemd-python>=231"],
|
|
@@ -125,10 +136,10 @@ class DependencyException(Exception):
|
|
|
@property
|
|
|
def dependencies(self):
|
|
|
for i in self.args[0]:
|
|
|
- yield '"' + i + '"'
|
|
|
+ yield "'" + i + "'"
|
|
|
|
|
|
|
|
|
-def check_requirements(for_feature=None, _get_distribution=get_distribution):
|
|
|
+def check_requirements(for_feature=None):
|
|
|
deps_needed = []
|
|
|
errors = []
|
|
|
|
|
@@ -139,7 +150,7 @@ def check_requirements(for_feature=None, _get_distribution=get_distribution):
|
|
|
|
|
|
for dependency in reqs:
|
|
|
try:
|
|
|
- _get_distribution(dependency)
|
|
|
+ _check_requirement(dependency)
|
|
|
except VersionConflict as e:
|
|
|
deps_needed.append(dependency)
|
|
|
errors.append(
|
|
@@ -157,7 +168,7 @@ def check_requirements(for_feature=None, _get_distribution=get_distribution):
|
|
|
|
|
|
for dependency in OPTS:
|
|
|
try:
|
|
|
- _get_distribution(dependency)
|
|
|
+ _check_requirement(dependency)
|
|
|
except VersionConflict as e:
|
|
|
deps_needed.append(dependency)
|
|
|
errors.append(
|
|
@@ -175,6 +186,23 @@ def check_requirements(for_feature=None, _get_distribution=get_distribution):
|
|
|
raise DependencyException(deps_needed)
|
|
|
|
|
|
|
|
|
+def _check_requirement(dependency_string):
|
|
|
+ """Parses a dependency string, and checks if the specified requirement is installed
|
|
|
+
|
|
|
+ Raises:
|
|
|
+ VersionConflict if the requirement is installed, but with the the wrong version
|
|
|
+ DistributionNotFound if nothing is found to provide the requirement
|
|
|
+ """
|
|
|
+ req = Requirement.parse(dependency_string)
|
|
|
+
|
|
|
+ # first check if the markers specify that this requirement needs installing
|
|
|
+ if req.marker is not None and not req.marker.evaluate():
|
|
|
+ # not required for this environment
|
|
|
+ return
|
|
|
+
|
|
|
+ get_provider(req)
|
|
|
+
|
|
|
+
|
|
|
if __name__ == "__main__":
|
|
|
import sys
|
|
|
|