Parse pip requirements file ourselves, instead of using their internals

that problem just kept getting worse, so i stole this solution partly from:

77879cf341
This commit is contained in:
Lance Edgar 2020-05-14 21:53:41 -05:00
parent f0224144b7
commit 5f2dd31485

View file

@ -33,21 +33,7 @@ import logging
import six
from sqlalchemy import orm
# TODO: pip has declared these to be "not public API" so we should find another way..
try:
# this works for now, with pip 20.0
from pip._internal.network.session import PipSession
from pip._internal.req import parse_requirements
except ImportError:
try:
# this works for now, with pip 10.0.1
from pip._internal.download import PipSession
from pip._internal.req import parse_requirements
except ImportError:
# this should work with pip < 10.0
from pip.download import PipSession
from pip.req import parse_requirements
from rattail.core import Object
from rattail.db import model, Session as RattailSession
from rattail.time import make_utc
from rattail.threads import Thread
@ -345,24 +331,25 @@ class UpgradeView(MasterView):
def parse_requirements(self, upgrade, type_):
packages = {}
path = self.rattail_config.upgrade_filepath(upgrade.uuid, filename='requirements.{}.txt'.format(type_))
session = PipSession()
for req in parse_requirements(path, session=session):
version = self.version_from_requirement(req)
packages[req.name] = version
with open(path, 'rt') as f:
for line in f:
line = line.strip()
if line and not line.startswith('#'):
req = self.parse_requirement(line)
if req:
packages[req.name] = req.version
else:
log.warning("could not parse req from line: %s", line)
return packages
def version_from_requirement(self, req):
if req.specifier:
match = re.match(r'^==(.*)$', six.text_type(req.specifier))
def parse_requirement(self, line):
match = re.match(r'^.*@(.*)#egg=(.*)$', line)
if match:
return match.group(1)
return six.text_type(req.specifier)
elif req.link:
match = re.match(r'^.*@(.*)#egg=.*$', six.text_type(req.link))
return Object(name=match.group(2), version=match.group(1))
match = re.match(r'^(.*)==(.*)$', line)
if match:
return match.group(1)
return six.text_type(req.link)
return ""
return Object(name=match.group(1), version=match.group(2))
def download_path(self, upgrade, filename):
return self.rattail_config.upgrade_filepath(upgrade.uuid, filename=filename)