diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dae77f5b9ee62fe9545b25aa04e20f5df2980e5..9a701a735b3aa983640918a2025a07657db5d765 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Python Buildpack Changelog +# 104 + +unreleased + +- Use `pkg_resources` to check if a distribution is installed instead of + parsing `requirements.txt`. ([#395][395]) + +[395]: https://github.com/heroku/heroku-buildpack-python/pull/395 + ## 103 Bug fixes and improvements. diff --git a/bin/steps/collectstatic b/bin/steps/collectstatic index 6e36c7aabceb3e890e96f3b8839f65479611b5bc..20bbb85f56946d2af1e0af6208a0c3ed977f7051 100755 --- a/bin/steps/collectstatic +++ b/bin/steps/collectstatic @@ -20,7 +20,7 @@ MANAGE_FILE=${MANAGE_FILE:-fakepath} [ -f .heroku/collectstatic_disabled ] && DISABLE_COLLECTSTATIC=1 # Ensure that Django is explicitly specified in requirements.txt -pip-grep -s requirements.txt django Django && DJANGO_INSTALLED=1 +pip-grep -s Django && DJANGO_INSTALLED=1 if [ ! "$DISABLE_COLLECTSTATIC" ] && [ -f "$MANAGE_FILE" ] && [ "$DJANGO_INSTALLED" ]; then diff --git a/bin/steps/cryptography b/bin/steps/cryptography index 8a507999d05256b7dad9a95ea553b7b2ab7fc3c9..dd4ea32f92b61353008645f2434aa5f3b245e684 100755 --- a/bin/steps/cryptography +++ b/bin/steps/cryptography @@ -18,7 +18,7 @@ PKG_CONFIG_PATH="/app/.heroku/vendor/lib/pkgconfig:$PKG_CONFIG_PATH" source $BIN_DIR/utils # If a package using cffi exists within requirements, use vendored libffi. -if (pip-grep -s requirements.txt argon2-cffi bcrypt cffi cryptography django[argon2] Django[argon2] django[bcrypt] Django[bcrypt] PyNaCl pyOpenSSL PyOpenSSL requests[security] misaka &> /dev/null) then +if (pip-grep -s argon2-cffi bcrypt cffi cryptography PyNaCl pyOpenSSL PyOpenSSL misaka &> /dev/null) then if [ ! -d ".heroku/vendor/lib/libffi-3.1" ]; then echo "-----> Noticed cffi. Bootstrapping libffi." diff --git a/bin/steps/gdal b/bin/steps/gdal index 50a09ac331aad10a53e797b49e0d5c01250e2d8f..82892b0072df5be2974c6e3a0790c9061fe3a852 100755 --- a/bin/steps/gdal +++ b/bin/steps/gdal @@ -18,7 +18,7 @@ PKG_CONFIG_PATH="/app/.heroku/vendor/lib/pkgconfig:$PKG_CONFIG_PATH" source $BIN_DIR/utils # If GDAL exists within requirements, use vendored gdal. -if (pip-grep -s requirements.txt GDAL gdal pygdal &> /dev/null) then +if (pip-grep -s GDAL pygdal &> /dev/null) then if [ ! -f ".heroku/vendor/bin/gdalserver" ]; then echo "-----> Noticed GDAL. Bootstrapping gdal." diff --git a/bin/steps/pylibmc b/bin/steps/pylibmc index f574e5350b8adabc4571578767cc3d11924b89f7..d5cc7857142ba40d4d62887502d998eff8ad9a0a 100755 --- a/bin/steps/pylibmc +++ b/bin/steps/pylibmc @@ -17,7 +17,7 @@ source $BIN_DIR/utils # If pylibmc exists within requirements, use vendored libmemcached. -if (pip-grep -s requirements.txt pylibmc &> /dev/null) then +if (pip-grep -s pylibmc &> /dev/null) then if [ ! -d ".heroku/vendor/lib/sasl2" ]; then echo "-----> Noticed pylibmc. Bootstrapping libmemcached." diff --git a/bin/steps/setuptools b/bin/steps/setuptools index 870cfd4a527475f0c0c5456a2eb2dcab435b2045..66a86173880bc775fbe49b27fc7844a043e005d7 100755 --- a/bin/steps/setuptools +++ b/bin/steps/setuptools @@ -3,7 +3,7 @@ # Syntax sugar. source $BIN_DIR/utils -if (pip-grep -s requirements.txt setuptools distribute &> /dev/null) then +if (pip-grep -s setuptools distribute &> /dev/null) then puts-warn 'The package setuptools/distribute is listed in requirements.txt.' puts-warn 'Please remove to ensure expected behavior. ' diff --git a/vendor/pip-pop/pip-grep b/vendor/pip-pop/pip-grep index 9e3371d0ce169c9fddbb14baedec6c5f1eb0b187..8b90a4936666d775ffe95dc2b98862d8d60d8699 100755 --- a/vendor/pip-pop/pip-grep +++ b/vendor/pip-pop/pip-grep @@ -2,58 +2,26 @@ # -*- coding: utf-8 -*- """Usage: - pip-grep [-s] <reqfile> <package>... + pip-grep [-s] <package>... Options: -h --help Show this screen. """ -import os from docopt import docopt -from pip.req import parse_requirements -from pip.index import PackageFinder -from pip._vendor.requests import session +from pkg_resources import DistributionNotFound, get_distribution -requests = session() +def has_any_distribution(names, silent=False): + for name in names: + try: + get_distribution(name) + except DistributionNotFound: + continue -class Requirements(object): - def __init__(self, reqfile=None): - super(Requirements, self).__init__() - self.path = reqfile - self.requirements = [] - - if reqfile: - self.load(reqfile) - - def __repr__(self): - return '<Requirements \'{}\'>'.format(self.path) - - def load(self, reqfile): - if not os.path.exists(reqfile): - raise ValueError('The given requirements file does not exist.') - - finder = PackageFinder([], [], session=requests) - for requirement in parse_requirements(reqfile, finder=finder, session=requests): - if requirement.req: - if not getattr(requirement.req, 'name', None): - # Prior to pip 8.1.2 the attribute `name` did not exist. - requirement.req.name = requirement.req.project_name - self.requirements.append(requirement.req) - - -def grep(reqfile, packages, silent=False): - try: - r = Requirements(reqfile) - except ValueError: if not silent: - print('There was a problem loading the given requirement file.') - exit(os.EX_NOINPUT) + print('Package {name} found!'.format(name=name)) - for req in r.requirements: - if req.name in packages: - if not silent: - print('Package {} found!'.format(req.name)) - exit(0) + exit(0) if not silent: print('Not found.') @@ -63,10 +31,7 @@ def grep(reqfile, packages, silent=False): def main(): args = docopt(__doc__, version='pip-grep') - - kwargs = {'reqfile': args['<reqfile>'], 'packages': args['<package>'], 'silent': args['-s']} - - grep(**kwargs) + has_any_distribution(names=args['<package>'], silent=args['-s']) if __name__ == '__main__':