parse_requirements => Requirement.parse

Since we only ever handle one requirement here, the parse_requirements
generator (which btw needs a next m() is not the best choice.

Also extracted install command cleanup into class method and added tests
for that.

cc @markwal
This commit is contained in:
Gina Häußge 2017-11-28 12:02:43 +01:00
parent d174d7ab80
commit 14bd0632c0
3 changed files with 115 additions and 23 deletions

View file

@ -24,9 +24,38 @@ class UnknownPip(Exception):
pass
class PipCaller(CommandlineCaller):
process_dependency_links = pkg_resources.parse_requirements("pip>=1.5")
no_use_wheel = pkg_resources.parse_requirements("pip==1.5.0")
broken = pkg_resources.parse_requirements("pip>=6.0.1,<=6.0.3")
process_dependency_links = pkg_resources.Requirement.parse("pip>=1.5")
no_use_wheel = pkg_resources.Requirement.parse("pip==1.5.0")
broken = pkg_resources.Requirement.parse("pip>=6.0.1,<=6.0.3")
@classmethod
def clean_install_command(cls, args, pip_version, virtual_env, use_user, force_user):
logger = logging.getLogger(__name__)
args = list(args)
# strip --process-dependency-links for versions that don't support it
if not pip_version in cls.process_dependency_links and "--process-dependency-links" in args:
logger.debug(
"Found --process-dependency-links flag, version {} doesn't need that yet though, removing.".format(
pip_version))
args.remove("--process-dependency-links")
# add --no-use-wheel for versions that otherwise break
if pip_version in cls.no_use_wheel and not "--no-use-wheel" in args:
logger.debug("Version {} needs --no-use-wheel to properly work.".format(pip_version))
args.append("--no-use-wheel")
# remove --user if it's present and a virtual env is detected
if "--user" in args:
if virtual_env or not site.ENABLE_USER_SITE:
logger.debug("Virtual environment detected, removing --user flag.")
args.remove("--user")
# otherwise add it if necessary
elif not virtual_env and site.ENABLE_USER_SITE and (use_user or force_user):
logger.debug("pip needs --user flag for installations.")
args.append("--user")
return args
def __init__(self, configured=None, ignore_cache=False, force_sudo=False,
force_user=False):
@ -126,25 +155,8 @@ class PipCaller(CommandlineCaller):
arg_list = list(args)
if "install" in arg_list:
# strip --process-dependency-links for versions that don't support it
if not self.version in self.__class__.process_dependency_links and "--process-dependency-links" in arg_list:
self._logger.debug("Found --process-dependency-links flag, version {} doesn't need that yet though, removing.".format(self.version))
arg_list.remove("--process-dependency-links")
# add --no-use-wheel for versions that otherwise break
if self.version in self.__class__.no_use_wheel and not "--no-use-wheel" in arg_list:
self._logger.debug("Version {} needs --no-use-wheel to properly work.".format(self.version))
arg_list.append("--no-use-wheel")
# remove --user if it's present and a virtual env is detected
if "--user" in arg_list:
if self._virtual_env or not site.ENABLE_USER_SITE:
self._logger.debug("Virtual environment detected, removing --user flag.")
arg_list.remove("--user")
# otherwise add it if necessary
elif not self._virtual_env and site.ENABLE_USER_SITE and (self.use_user or self.force_user):
self._logger.debug("pip needs --user flag for installations.")
arg_list.append("--user")
arg_list = self.clean_install_command(arg_list, self.version, self._virtual_env, self.use_user,
self.force_user)
# add args to command
if isinstance(self._command, list):

View file

@ -74,7 +74,7 @@ def is_octoprint_compatible(*compatibility_entries, **kwargs):
if not any(octo_compat.startswith(c) for c in ("<", "<=", "!=", "==", ">=", ">", "~=", "===")):
octo_compat = ">={}".format(octo_compat)
s = next(pkg_resources.parse_requirements("OctoPrint" + octo_compat))
s = pkg_resources.Requirement.parse("OctoPrint" + octo_compat)
if octoprint_version in s:
break
except:

80
tests/util/test_pip.py Normal file
View file

@ -0,0 +1,80 @@
# coding=utf-8
from __future__ import absolute_import
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
__copyright__ = "Copyright (C) 2017 The OctoPrint Project - Released under terms of the AGPLv3 License"
import unittest
import ddt
import mock
import octoprint.util.pip
import site
import pkg_resources
@ddt.ddt
class PipCallerTest(unittest.TestCase):
@ddt.data(
# remove --process-dependency-links for versions < 1.5
(["install", "--process-dependency-links", "http://example.com/foo.zip"], "1.1", True, False, False,
True,
["install", "http://example.com/foo.zip"]),
# keep --process-dependency-links for versions >= 1.5, --no-use-wheel for ==1.5.0
(["install", "--process-dependency-links", "http://example.com/foo.zip"], "1.5", True, False, False,
True,
["install", "--process-dependency-links", "http://example.com/foo.zip", "--no-use-wheel"]),
# keep --process-dependency-links for versions >= 1.5
(["install", "--process-dependency-links", "http://example.com/foo.zip"], "9.0.1", True, False, False,
True,
["install", "--process-dependency-links", "http://example.com/foo.zip"]),
# remove --user in virtual env
(["install", "--user", "http://example.com/foo.zip"], "9.0.1", True, False, False,
True,
["install", "http://example.com/foo.zip"]),
# ignore use_user in virtual env
(["install", "http://example.com/foo.zip"], "9.0.1", True, True, False,
True,
["install", "http://example.com/foo.zip"]),
# ignore force_user in virtual env
(["install", "http://example.com/foo.zip"], "9.0.1", True, False, True,
True,
["install", "http://example.com/foo.zip"]),
# remove --user with disabled user_site
(["install", "--user", "http://example.com/foo.zip"], "9.0.1", False, False, False,
False,
["install", "http://example.com/foo.zip"]),
# add --user when not in virtual env and use_user is True
(["install", "http://example.com/foo.zip"], "9.0.1", False, True, False,
True,
["install", "http://example.com/foo.zip", "--user"]),
# ignore use_user with disabled user_site
(["install", "http://example.com/foo.zip"], "9.0.1", False, True, False,
False,
["install", "http://example.com/foo.zip"]),
# add --user when not in virtual env and force_user is True
(["install", "http://example.com/foo.zip"], "9.0.1", False, False, True,
True,
["install", "http://example.com/foo.zip", "--user"]),
# ignore force_user with disabled user_site
(["install", "http://example.com/foo.zip"], "9.0.1", False, False, True,
False,
["install", "http://example.com/foo.zip"]),
)
@ddt.unpack
def test_clean_install_command(self, args, version, virtual_env, use_user, force_user, user_site, expected):
with mock.patch.object(site, "ENABLE_USER_SITE", user_site):
parsed = pkg_resources.parse_version(version)
actual = octoprint.util.pip.PipCaller.clean_install_command(args, parsed, virtual_env, use_user, force_user)
self.assertEquals(expected, actual)