def test_check_version_mismatch(capsys, test_data): # preconditions package_list, locked_list = test_data packages = PackageCollection([ Package(key=key, name=key, obj=None, version=InstalledVersion(version)) for key, version in package_list ]) locked = RequirementCollection([ Requirement(key=key, name=key, obj=None, version=RequiredVersion(version)) for key, version in locked_list ]) # action success = validate.check_package_version_mismatch(packages=packages, locked=locked) # verification captured = capsys.readouterr() assert success is False if package_list != locked_list else success if success: assert messages.PACKAGE_VERSION_MISMATCH_OK in captured.out else: assert messages.PACKAGE_VERSION_MISMATCH_FOUND in captured.out for package in package_list: for lock in locked_list: if package[0] == lock[0] and package[1] != lock[1]: assert package[0] in captured.out
def test_check_unnecessary_requirements(capsys, test_data): # preconditions package_list, requirements_list, locked_list = test_data packages = PackageCollection([ Package(key=key, name=key, obj=None, version=None) for key in package_list ]) requirements = RequirementCollection([ Requirement.from_requirement_string(key) for key in requirements_list ]) locked = RequirementCollection( [Requirement.from_requirement_string(key) for key in locked_list]) # action success = validate.check_unnecessary_packages( packages=packages, requirements=requirements, locked=locked, ) # verification captured = capsys.readouterr() required = set(requirements_list + locked_list) assert success is False if len(package_list) > len(required) else success if success: assert messages.PACKAGE_NOT_REQUIRED_OK in captured.out else: assert messages.PACKAGE_NOT_REQUIRED_FOUND in captured.out for package in package_list: if package not in required: assert package in captured.out
def locked_requirements(packages=None, requirements=None, ignore_list=None): """Returns all requirements locked to the required versions :param packages: Collection of packages :param requirements: Collection of requirements :param ignore_list: List of package keys to ignore :return: All requirements locked to their installed versions """ packages = packages or PackageCollection() requirements = requirements or RequirementCollection() ignore_list = ignore_list or [] if not requirements: return RequirementCollection( sorted([ Requirement.from_package(package=package) for package in packages ])) locked = [] for package in packages: specified_in_requirements = package.key in requirements.keys() required_by_requirements = required_by(requirement=package, packages=requirements.flatten()) if specified_in_requirements or required_by_requirements: locked.append(package) return RequirementCollection( sorted([requirement for requirement in locked]))
def cyclic_dependencies(packages=None): """Returns all cyclic dependencies :param packages: Collection of packages :return: List of found cyclic paths """ packages = packages or PackageCollection() return packages.cyclic_dependencies
def get_graph(packages=None, name=None, filename=None, file_format=None, engine=None, strict=True, graph_attr=None, node_attr=None, edge_attr=None): """Creates a dependency graph :param packages: Installed packages :param name: Graph name :param filename: Export filename :param file_format: Export format :param engine: Rendering engine :param strict: Rendering should merge multi-edges :param graph_attr: Graph attributes :param node_attr: Node attributes :param edge_attr: Edge attributes :return: Graph object """ packages = packages or PackageCollection() return create_dependency_graph( packages=packages, name=name, filename=filename, file_format=file_format, engine=engine, strict=strict, edge_attr=edge_attr, graph_attr=graph_attr, node_attr=node_attr, )
def render_graph(packages=None, graph=None, view=False): """Renders a dependency graph :param packages: Installed packages :param graph: Graph to render :param view: Display created graph :return: Saved render filepath """ packages = packages or PackageCollection() graph = graph or create_dependency_graph(packages=packages) return render_dependency_graph(graph=graph, view=view)
def unnecessary_packages(packages=None, requirements=None, locked=None): """Return locked packages that are not required by specified requirements or locked requirements :param packages: Collection of packages :param requirements: Collection of requirements :param locked: Collection of locked requirements :return: All packages that are not required """ packages = packages or PackageCollection() requirements = requirements or RequirementCollection() locked = locked or RequirementCollection() unset = unset_locks(requirements=requirements, locked=locked) return PackageCollection( sorted([ package for package in packages if package.key not in locked.keys() and package.key not in unset.keys() ]))
def dependency_list(ignore_list=None, requirements=None): """Returns all installed packages :param ignore_list: List of package keys to ignore :param requirements: Collection of requirements :return: List of packages """ ignore_list = ignore_list or Config.ignore_list installed_packages = PackageCollection.installed_packages( ignore_list=ignore_list) # If requirements files are specified filter out other packages if requirements: return PackageCollection([ package for package in installed_packages if package.key in requirements.flatten().keys() ]) # Otherwise just return all installed packages return installed_packages
def unset_requirements(packages=None, requirements=None): """Returns all package requirements that are not in provided requirements :param packages: Collection of packages :param requirements: Collection of requirements :return: All requirements that are not in requirements """ packages = packages or PackageCollection() requirements = requirements or RequirementCollection() return RequirementCollection((package for package in packages.independent_packages if package.key not in requirements.keys()))
def required_by(requirement, packages=None): """Returns all packages that require the provided requirement :param requirement: Requirement object :param packages: Collection of packages :return: Packages that require the requirement """ packages = packages or PackageCollection() return [(package, package_requirement.specified_version) for package in packages for package_requirement in package.requirements if requirement.key == package_requirement.key]
def missing_requirements(packages=None, requirements=None, ignore_list=None): """Returns all requirements that are not installed :param packages: Collection of packages :param requirements: Collection of requirements :param ignore_list: List of package keys to ignore :return: All requirements that are not found in packages """ packages = packages or PackageCollection() requirements = requirements or RequirementCollection() ignore_list = ignore_list or [] return [(requirement, required_by(requirement, packages)) for requirement in requirements.flatten() if requirement.key not in ignore_list + packages.keys()]
def lock_version_mismatch(packages=None, locked=None): """Return detected version mismatches between packages and locked requirements :param packages: Collection of packages :param locked: Collection of locked requirements :return: All detected mismatches between installed packages and locked requirements """ packages = packages or PackageCollection() locked = locked or RequirementCollection() return [(package, str(lock.specified_version)) for package in packages for lock in locked if package.key == lock.key and package.specified_version != lock.specified_version]
def conflicting_dependencies(packages=None, allow_named_versions=False, named_version_patterns=None): """Returns all dependencies with conflicting versions :param packages: Collection of packages :param allow_named_versions: Allow named versions to circumvent conflicts :param named_version_patterns: List of patterns that determine named versions :return: List of requirements and packages that require them with the required version """ packages = packages or PackageCollection() return [(requirement, required_by(requirement, packages)) for requirement in packages.requirements if requirement.conflicting( allow_named_versions=allow_named_versions, named_version_patterns=named_version_patterns)]
def dependency_tree(packages=None, requirements=None): """Returns a dependency tree for all packages :param packages: Collection of packages :param requirements: Collection of requirements :return: Dependency tree for all packages """ packages = packages or PackageCollection() tree = OrderedDict( sorted({ package: package_dependency_tree(dependency=package) for package in packages if package.key in packages.independent_packages.keys() and ( # Include only the branches from provided requirements # if they were provided requirements is None or (requirements is not None and package.key in requirements.keys())) }.items())) return tree
def prepare_packages(venv, mocker, packages): working_set = prepare_working_set(venv, packages) mocker.patch('dante.vendor.pkg_resources.working_set', working_set) return PackageCollection.from_distributions( packages=[package for package in working_set], ignore_list=Config.ignore_list)