def test_required_installed_analyzer(): pkgs_reqs = RequirementsTxt(packages=[ PackageRequirement(name='coverage', operator='<', version='3.6'), PackageRequirement(name='parsimonious', operator='<=', version='0.5'), ], ) pkgs_installed = InstalledPackages( packages=[ InstalledPackage(name='coverage', version='3.5'), # ok InstalledPackage(name='parsimonious', version='0.5'), # ok ], ) analyzer = RequiredInstalledAnalyzer( requirements_txt=pkgs_reqs, installed_packages=pkgs_installed, ) advice_list = analyzer.analyze() expected_advice_list = AdviceList(advice_list=[ Advice( analyzer=analyzer, severity='debug', message=("Required dependency 'coverage<3.6' " "is satisfied by installed 'coverage-3.5'"), ), Advice( analyzer=analyzer, severity='debug', message=("Required dependency 'parsimonious<=0.5' " "is satisfied by installed 'parsimonious-0.5'"), ), ], ) assert expected_advice_list == advice_list
def test_requirements_txt_equality(): reqs1 = RequirementsTxt(packages=[ PackageRequirement(name='coverage', operator='<', version='3.6'), PackageRequirement(name='parsimonious', operator='<=', version='0.5'), ], ) # missing one package reqs2 = RequirementsTxt(packages=[ PackageRequirement(name='coverage', operator='<', version='3.6'), ], ) # operator differs reqs3 = RequirementsTxt(packages=[ PackageRequirement(name='coverage', operator='<', version='3.6'), PackageRequirement(name='parsimonious', operator='==', version='0.5'), ], ) assert not reqs1 == None # noqa assert reqs1 == reqs1 assert not reqs1 != reqs1 assert reqs1 != reqs2 assert not reqs1 == reqs2 assert reqs1 != reqs3 assert not reqs1 == reqs3 # Test repr assert repr(reqs1) == '<RequirementsTxt num_packages=2>'
def parse(self): pkgs = [] for line in self.fileobj: line = self.strip_comment(line) line = self.strip_flag(line) line = line.strip() # If the line was all comment or whitespace then skip it if not line: continue match = self.rx_name_op_version.match(line) if not match: match = self.rx_name.match(line) # Was unable to parse the line if not match or not len(match.groups()) in [1, 3]: _logger.warn('Unable to parse requirements line: %s', line) continue pkg = PackageRequirement( name=match.groupdict()['name'], operator=match.groupdict().get('operator'), version=match.groupdict().get('version'), ) pkgs.append(pkg) reqs = RequirementsTxt(packages=pkgs) return reqs
def test_is_unused_analyzer(): pkgs_reqs = RequirementsTxt(packages=[ PackageRequirement(name='click', operator='==', version='1.8'), PackageRequirement(name='six', operator='==', version='3.5'), ], ) pkgs_installed = InstalledPackages(packages=[ InstalledPackage(name='click', version='1.8'), InstalledPackage(name='six', version='3.5'), ], ) # mock: the top level of the package is the name of the package site_packages = SitePackages( python_path=None, installed_package_names=[], ) site_packages.get_package_top_levels = lambda pkg_name: [pkg_name] # mock: grep says six is used, nothing else is git_grep = GitGrep(basedir=None) git_grep.package_is_imported = lambda pkg_name: (True if pkg_name == 'six' else False) analyzer = IsUnusedAnalyzer( requirements_txt=pkgs_reqs, installed_packages=pkgs_installed, site_packages=site_packages, grep=git_grep, ) advice_list = analyzer.analyze() expected_advice_list = AdviceList(advice_list=[ Advice( analyzer=analyzer, severity='info', message=("Required dependency 'click==1.8' " "is never imported (click)"), ), ], ) assert expected_advice_list == advice_list
def test_requirements_txt_parser(): reqs_expected = RequirementsTxt(packages=[ PackageRequirement(name='coverage', operator='<', version='3.6'), PackageRequirement(name='parsimonious', operator='<=', version='0.5'), PackageRequirement(name='pytest', operator='==', version='2.3.5'), PackageRequirement(name='six', operator='>=', version='1.6.0'), PackageRequirement(name='tox', operator='>', version='1.6.1'), PackageRequirement(name='mock', operator='!=', version='5.1.1'), PackageRequirement(name='ply', operator='~=', version='3.10'), PackageRequirement(name='jsonpath', operator='===', version='2.0.x'), PackageRequirement(name='simplejson', operator=None, version=None), ], ) parser = RequirementsTxtParser(fileobj=StringIO(REQS_EXAMPLE)) reqs = parser.parse() assert reqs_expected == reqs
def test_required_not_installed_analyzer(): pkgs_reqs = RequirementsTxt(packages=[ PackageRequirement(name='coverage', operator='<', version='3.6'), PackageRequirement(name='parsimonious', operator='<=', version='0.5'), PackageRequirement(name='six', operator='>=', version='0.5'), ], ) pkgs_installed = InstalledPackages( packages=[ InstalledPackage(name='coverage', version='3.5'), # ok # parsimonious missing InstalledPackage(name='six', version='0.4.9'), # version too low ], ) analyzer = RequiredNotInstalledAnalyzer( requirements_txt=pkgs_reqs, installed_packages=pkgs_installed, ) advice_list = analyzer.analyze() expected_advice_list = AdviceList(advice_list=[ Advice( analyzer=analyzer, severity='error', message=( "Required dependency 'parsimonious<=0.5' is not installed"), ), Advice( analyzer=analyzer, severity='error', message=("Required dependency 'six>=0.5' " "is not satisfied by installed 'six-0.4.9'"), ), ], ) assert expected_advice_list == advice_list
def test_requirements_txt_get_by_name(): coverage = PackageRequirement(name='coverage', operator='<', version='3.6') reqs = RequirementsTxt(packages=[ coverage, ], ) # exact name matches assert reqs.get_by_name('coverage') is coverage assert reqs.get_by_name('Coverage') is None # ignore case assert reqs.get_by_name('coverage', ignore_case=True) is coverage assert reqs.get_by_name('Coverage', ignore_case=True) is coverage # nothing else matches assert reqs.get_by_name('coverage==1.0') is None assert reqs.get_by_name('cov') is None
def test_can_be_upgraded_analyzer(): pkgs_available = AvailablePackages( packages=[ PackageReleases(name='abc', versions=('8.5', '8.6')), PackageReleases(name='click', versions=('1.8', '1.9')), PackageReleases(name='coverage', versions=('3.5', '3.6', '4.0', '4.1')), PackageReleases(name='ply', versions=('0.5', '0.5.1')), PackageReleases(name='six', versions=('0.8', '0.9')), ], ) pkgs_reqs = RequirementsTxt( packages=[ PackageRequirement(name='abc', operator='<=', version='9.0'), PackageRequirement(name='click', operator=None, version=None), PackageRequirement(name='coverage', operator='<', version='4.0'), # -> 4.1 PackageRequirement(name='ply', operator='==', version='0.5'), # -> 0.5.1 PackageRequirement(name='six', operator='==', version='0.9'), ], ) pkgs_installed = InstalledPackages( packages=[ InstalledPackage(name='abc', version='8.5'), # -> 8.6 InstalledPackage(name='click', version='1.8'), # -> 1.9 InstalledPackage(name='coverage', version='3.5'), # -> 3.6 ], ) analyzer = CanBeUpgradedAnalyzer( requirements_txt=pkgs_reqs, installed_packages=pkgs_installed, available_packages=pkgs_available, ) advice_list = analyzer.analyze() expected_advice_list = AdviceList( advice_list=[ Advice( analyzer=analyzer, severity='info', message=( "Installed dependency 'abc-8.5' " "can be updated to 'abc-8.6'" ), ), Advice( analyzer=analyzer, severity='info', message=( "Installed dependency 'click-1.8' " "can be updated to 'click-1.9'" ), ), Advice( analyzer=analyzer, severity='info', message=( "Required dependency 'coverage<4.0' " "can be upgraded to 'coverage-4.1'" ), ), Advice( analyzer=analyzer, severity='info', message=( "Installed dependency 'coverage-3.5' " "can be updated to 'coverage-3.6'" ), ), Advice( analyzer=analyzer, severity='info', message=( "Required dependency 'ply==0.5' " "can be upgraded to 'ply-0.5.1'" ), ), ], ) assert expected_advice_list == advice_list
def test_can_be_upgraded_analyzer(): pkgs_reqs = RequirementsTxt( packages=[ PackageRequirement(name='locustio', operator='==', version='0.8a2'), # top level PackageRequirement(name='Flask', operator='==', version='0.12.2'), # one level down PackageRequirement(name='Jinja2', operator='==', version='2.9.6'), # two levels down ], ) pkgs_installed = InstalledPackages( packages=[ # locustio dependency closure InstalledPackage(name='Flask', version='0.12.2'), InstalledPackage(name='Jinja2', version='2.9.6'), InstalledPackage(name='MarkupSafe', version='1.0'), InstalledPackage(name='Werkzeug', version='0.12.2'), InstalledPackage(name='certifi', version='2017.7.27.1'), InstalledPackage(name='chardet', version='3.0.4'), InstalledPackage(name='click', version='6.7'), InstalledPackage(name='gevent', version='1.2.2'), InstalledPackage(name='greenlet', version='0.4.12'), InstalledPackage(name='idna', version='2.6'), InstalledPackage(name='itsdangerous', version='0.24'), InstalledPackage(name='locustio', version='0.8a2'), InstalledPackage(name='msgpack-python', version='0.4.8'), InstalledPackage(name='pyzmq', version='15.2.0'), InstalledPackage(name='requests', version='2.18.4'), InstalledPackage(name='six', version='1.11.0'), InstalledPackage(name='urllib3', version='1.22'), # top level dependencies, but not reported as they are known # "virtual" dependencies InstalledPackage(name='pkg-resources', version='0.0.0'), InstalledPackage(name='setuptools', version='36.5.0'), # top level dependency that is not required - should be reported InstalledPackage(name='ipdb', version='0.10.3'), ], ) installed_names = [pkg.name for pkg in pkgs_installed.packages] site_packages = SitePackages( python_path=None, installed_package_names=installed_names, ) site_packages._query_cache = EXAMPLE_RESULTS_DICT analyzer = IsTransitiveDepAnalyzer( requirements_txt=pkgs_reqs, installed_packages=pkgs_installed, site_packages=site_packages, ) advice_list = analyzer.analyze() expected_advice_list = AdviceList(advice_list=[ Advice( analyzer=analyzer, severity='info', message=("Required dependency 'Flask==0.12.2' " "is a transitive dependency of 'locustio==0.8a2'"), ), Advice( analyzer=analyzer, severity='info', message=("Required dependency 'Jinja2==2.9.6' " "is a transitive dependency of 'locustio==0.8a2'"), ), Advice( analyzer=analyzer, severity='warn', message=("Installed non-transitive dependency 'ipdb-0.10.3' " "is not required"), ), ], ) assert expected_advice_list == advice_list