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 import six
from sqlalchemy import orm from sqlalchemy import orm
# TODO: pip has declared these to be "not public API" so we should find another way.. from rattail.core import Object
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.db import model, Session as RattailSession from rattail.db import model, Session as RattailSession
from rattail.time import make_utc from rattail.time import make_utc
from rattail.threads import Thread from rattail.threads import Thread
@ -345,24 +331,25 @@ class UpgradeView(MasterView):
def parse_requirements(self, upgrade, type_): def parse_requirements(self, upgrade, type_):
packages = {} packages = {}
path = self.rattail_config.upgrade_filepath(upgrade.uuid, filename='requirements.{}.txt'.format(type_)) path = self.rattail_config.upgrade_filepath(upgrade.uuid, filename='requirements.{}.txt'.format(type_))
session = PipSession() with open(path, 'rt') as f:
for req in parse_requirements(path, session=session): for line in f:
version = self.version_from_requirement(req) line = line.strip()
packages[req.name] = version 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 return packages
def version_from_requirement(self, req): def parse_requirement(self, line):
if req.specifier: match = re.match(r'^.*@(.*)#egg=(.*)$', line)
match = re.match(r'^==(.*)$', six.text_type(req.specifier))
if match: if match:
return match.group(1) return Object(name=match.group(2), version=match.group(1))
return six.text_type(req.specifier)
elif req.link: match = re.match(r'^(.*)==(.*)$', line)
match = re.match(r'^.*@(.*)#egg=.*$', six.text_type(req.link))
if match: if match:
return match.group(1) return Object(name=match.group(1), version=match.group(2))
return six.text_type(req.link)
return ""
def download_path(self, upgrade, filename): def download_path(self, upgrade, filename):
return self.rattail_config.upgrade_filepath(upgrade.uuid, filename=filename) return self.rattail_config.upgrade_filepath(upgrade.uuid, filename=filename)