From 6cd93c82f5c0a09bc0a3ccab214d87537c5e60c2 Mon Sep 17 00:00:00 2001 From: John Vandenberg Date: Fri, 22 Jul 2016 09:11:31 +0700 Subject: [PATCH] Monkeypatch pkg_resources to always use _markerlib Prior to setuptools 20.10.0 there is patchy support for environment markers, and setup.py fails while parsing them. html5lib requires at least setuptools 18.5 for its environment markers. However, @gsnedders developed a way to monkey patch pkg_resources so that it always uses _markerlib, which allows all environment markers to be used for any version of setuptools. Some patching of _markerlib is also required so that it works on Python 3 also. On removing the dependency for setuptools>=18.5, pip partially fails on Python 2.6 with an error `Double requirement given: ordereddict` and does not install the requirements.txt. Fixed by removing ordereddict from requirements-test.txt --- requirements-install.sh | 3 --- requirements-test.txt | 1 - requirements.txt | 1 - setup.py | 53 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/requirements-install.sh b/requirements-install.sh index 9b28888a..cd693444 100755 --- a/requirements-install.sh +++ b/requirements-install.sh @@ -5,9 +5,6 @@ if [[ $USE_OPTIONAL != "true" && $USE_OPTIONAL != "false" ]]; then exit 1 fi -# Make sure we're running setuptools >= 18.5 -pip install -U pip setuptools>=18.5 - pip install -U -r requirements-test.txt if [[ $USE_OPTIONAL == "true" ]]; then diff --git a/requirements-test.txt b/requirements-test.txt index e24223ef..e1ad307d 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -4,4 +4,3 @@ flake8 pytest pytest-expect>=1.1,<2.0 mock -ordereddict ; python_version < '2.7' diff --git a/requirements.txt b/requirements.txt index 92c09036..745993b9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ six webencodings ordereddict ; python_version < '2.7' -setuptools>=18.5 diff --git a/setup.py b/setup.py index 7c419e2c..00fee241 100644 --- a/setup.py +++ b/setup.py @@ -8,10 +8,54 @@ from setuptools import setup, find_packages, __version__ as setuptools_version from pkg_resources import parse_version -if parse_version(setuptools_version) < parse_version("18.5"): - print("html5lib requires setuptools version 18.5 or above; " - "please upgrade before installing (you have %s)" % setuptools_version) - sys.exit(1) +import pkg_resources + +try: + import _markerlib.markers +except ImportError: + _markerlib = None + + +# _markerlib.default_environment() obtains its data from _VARS +# and wraps it in another dict, but _markerlib_evaluate writes +# to the dict while it is iterating the keys, causing an error +# on Python 3 only. +# Replace _markerlib.default_environment to return a custom dict +# that has all the necessary markers, and ignores any writes. + +class Python3MarkerDict(dict): + + def __setitem__(self, key, value): + pass + + def pop(self, i=-1): + return self[i] + + +if _markerlib and sys.version_info[0] == 3: + env = _markerlib.markers._VARS + for key in list(env.keys()): + new_key = key.replace('.', '_') + if new_key != key: + env[new_key] = env[key] + + _markerlib.markers._VARS = Python3MarkerDict(env) + + def default_environment(): + return _markerlib.markers._VARS + + _markerlib.default_environment = default_environment + +# Avoid the very buggy pkg_resources.parser, which doesnt consistently +# recognise the markers needed by this setup.py +# Change this to setuptools 20.10.0 to support all markers. +if pkg_resources: + if parse_version(setuptools_version) < parse_version('18.5'): + MarkerEvaluation = pkg_resources.MarkerEvaluation + + del pkg_resources.parser + pkg_resources.evaluate_marker = MarkerEvaluation._markerlib_evaluate + MarkerEvaluation.evaluate_marker = MarkerEvaluation._markerlib_evaluate classifiers = [ 'Development Status :: 5 - Production/Stable', @@ -60,7 +104,6 @@ install_requires=[ 'six', 'webencodings', - 'setuptools>=18.5' ], extras_require={ # A empty extra that only has a conditional marker will be