Example #1
0
File: config.py Project: sbg/dante
def config_command(_):
    """Print current configuration
    :param _: Command arguments
    :return: None
    """
    printer = Printer()
    message = Config.to_json()
    printer.print_message(message=message)
Example #2
0
File: cyclic.py Project: sbg/dante
def cyclic_command(args, packages=None, exit_on_failure=True):
    """Runs detection of cyclical dependencies
    :param args: Command arguments
    :param packages: Collection of packages
    :param exit_on_failure: Enable/disable exiting application on failure
    :return: None
    """
    ignore_list = (
        args.ignore or Config.ignore_list or []
    )

    printer = Printer()
    packages = (
        packages or dependency_list(ignore_list=ignore_list)
    )

    cyclic_paths = cyclic_dependencies(packages=packages)

    if cyclic_paths:
        printer.error(messages.CYCLIC_FOUND)
        for path in cyclic_paths:
            if path:
                path.append(path[0])
                path_message = ' -> '.join(map(lambda p: p.key, path))
                printer.info(message=path_message)
        if exit_on_failure:
            sys.exit(1)
        return False

    printer.success(messages.CYCLIC_OK)
    return True
Example #3
0
def graph_command(args, packages=None, exit_on_failure=True):
    """Return or render a dependency graph
    :param args: Command arguments
    :param packages: Collection of packages
    :param exit_on_failure: Enable/disable exiting application on failure
    :return: None
    """
    ignore_list = (args.ignore or Config.ignore_list or [])

    name = args.name or Config.graph_name
    filename = args.filename or Config.graph_filename
    file_format = args.format or Config.graph_format
    engine = args.engine or Config.graph_engine
    strict = args.strict or Config.graph_strict
    graph_attr = args.graph_attr or Config.graph_attributes
    node_attr = args.node_attr or Config.graph_node_attributes
    edge_attr = args.edge_attr or Config.graph_edge_attributes
    view = args.view or False
    render = args.render or False

    printer = Printer()
    packages = (packages or dependency_list(ignore_list=ignore_list))

    graph = get_graph(
        packages=packages,
        name=name,
        filename=filename,
        file_format=file_format,
        engine=engine,
        strict=strict,
        graph_attr=graph_attr,
        node_attr=node_attr,
        edge_attr=edge_attr,
    )

    if render:
        try:
            filepath = render_graph(graph=graph, view=view)
            printer.success(
                messages.GRAPH_EXPORTED.format(file_path=filepath,
                                               format=file_format))
        except Exception as e:
            printer.error(messages.GRAPH_FAILED_TO_RENDER.format(error=e))
            return sys.exit(1) if exit_on_failure else ''

    else:
        printer.print_message(message=graph)
Example #4
0
def conflicts_command(args, packages=None, exit_on_failure=True):
    """Runs detection of dependency conflicts
    :param args: Command arguments
    :param packages: Collection of packages
    :param exit_on_failure: Enable/disable exiting application on failure
    :return: None
    """
    ignore_list = (args.ignore or Config.ignore_list or [])

    printer = Printer()
    packages = (packages or dependency_list(ignore_list=ignore_list))

    conflicting = [
        (package, required_by)
        for package, required_by in conflicting_dependencies(packages=packages)
    ]

    headers = [
        messages.PACKAGE,
        messages.INSTALLED,
        messages.REQUIRED,
        messages.REQUIRED_BY,
    ]

    tabular_data = [[
        printer.colored_message(message=package.key,
                                message_color=printer.color_package),
        package.version_id,
        required_version,
        required_by.key,
    ] for package, requirement in conflicting
                    for required_by, required_version in requirement]

    if tabular_data:
        printer.error(messages.CONFLICTS_FOUND)
        printer.table(headers=headers, tabular_data=tabular_data)
        if exit_on_failure:
            sys.exit(1)
        return False

    printer.success(messages.CONFLICTS_OK)
    return True
Example #5
0
def validate_files(files, printer=None, exit_on_failure=True):
    """Validate all provided files exist
    :param files: List of files
    :param printer: Printer object
    :param exit_on_failure: Enable/disable exiting application on failure
    :return: Whether the files are valid
    """
    invalid_files = []
    printer = printer or Printer()
    for file_ in files:
        if not os.path.exists(file_):
            if exit_on_failure:
                printer.error('File "{}" not found'.format(file_))
            invalid_files.append(file_)
    return (True if not invalid_files else
            sys.exit(1) if exit_on_failure else False)
Example #6
0
def check_requirement_version_mismatch(requirements, locked, printer=None):
    """Run validation that checks if there are version mismatches between
        requirements and locked requirements
    :param requirements: Collection of requirements
    :param locked: Collection of locked requirements
    :param printer: Printer object
    :return: Whether the validation was successful
    """
    printer = printer or Printer()
    locked_versions = required_version_mismatch(
        requirements=requirements,
        locked=locked
    )

    headers = [
        messages.PACKAGE,
        messages.REQUIRED,
        messages.LOCKED,
    ]

    tabular_data = [
        [
            printer.colored_message(
                message=requirement.key,
                message_color=printer.color_package
            ),
            requirement.specified_version,
            required,
        ]
        for requirement, required in locked_versions
    ]

    if tabular_data:
        printer.error(messages.REQUIREMENT_VERSION_MISMATCH_FOUND)
        printer.table(
            headers=headers,
            tabular_data=tabular_data
        )
        return False

    printer.success(messages.REQUIREMENT_VERSION_MISMATCH_OK)
    return True
Example #7
0
def check_unnecessary_packages(
        packages, requirements, locked, printer=None):
    """Run validation that checks if there are unnecessary installed packages
        in the environment that are not required by anything
    :param packages: Collection of packages
    :param requirements: Collection of requirements
    :param locked: Collection of locked requirements
    :param printer: Printer object
    :return: Whether the validation was successful
    """
    printer = printer or Printer()
    lock_not_required = unnecessary_packages(
        packages=packages, requirements=requirements, locked=locked
    )

    headers = [
        messages.PACKAGE,
        messages.INSTALLED,
    ]

    tabular_data = [
        [
            printer.colored_message(
                message=package.key,
                message_color=printer.color_package
            ),
            package.version_id,
        ]
        for package in lock_not_required
    ]

    if tabular_data:
        printer.warning(messages.PACKAGE_NOT_REQUIRED_FOUND)
        printer.table(
            headers=headers,
            tabular_data=tabular_data
        )
        return False

    printer.success(messages.PACKAGE_NOT_REQUIRED_OK)
    return True
Example #8
0
def check_unnecessary_locks(requirements, locked, ignore_list, printer=None):
    """Run validation that checks if there are unnecessary locked requirements
        that are not required by anything
    :param requirements: Collection of requirements
    :param locked: Collection of locked requirements
    :param printer: Printer object
    :return: Whether the validation was successful
    """
    printer = printer or Printer()
    lock_not_required = unnecessary_locks(
        requirements=requirements,
        locked=locked,
        ignore_list=ignore_list,
    )

    headers = [
        messages.PACKAGE,
        messages.LOCKED,
    ]

    tabular_data = [
        [
            printer.colored_message(
                message=requirement.key,
                message_color=printer.color_package
            ),
            requirement.specified_version,
        ]
        for requirement in lock_not_required
    ]

    if tabular_data:
        printer.warning(messages.LOCK_NOT_REQUIRED_FOUND)
        printer.table(
            headers=headers,
            tabular_data=tabular_data
        )
        return False

    printer.success(messages.LOCK_NOT_REQUIRED_OK)
    return True
Example #9
0
def check_package_version_mismatch(packages, locked, printer=None):
    """Run validation that checks if there are mismatches between installed
        packages and locked requirements
    :param packages: Collection of packages
    :param locked: Collection of locked requirements
    :param printer: Printer object
    :return: Whether the validation was successful
    """
    printer = printer or Printer()
    locked_versions = lock_version_mismatch(
        packages=packages, locked=locked
    )

    headers = [
        messages.PACKAGE,
        messages.INSTALLED,
        messages.REQUIRED,
    ]

    tabular_data = [
        [
            printer.colored_message(
                message=package.key,
                message_color=printer.color_package
            ),
            package.version_id,
            required,
        ]
        for package, required in locked_versions
    ]

    if tabular_data:
        printer.error(messages.PACKAGE_VERSION_MISMATCH_FOUND)
        printer.table(
            headers=headers,
            tabular_data=tabular_data
        )
        return False

    printer.success(messages.PACKAGE_VERSION_MISMATCH_OK)
    return True
Example #10
0
def lock_command(args, packages=None, exit_on_failure=True):
    """Display or save locked requirements for current environment
    :param args: Command arguments
    :param packages: Collection of packages
    :param exit_on_failure: Enable/disable exiting application on failure
    :return: None
    """
    requirements_files = (args.requirements or Config.requirements_files or [])
    ignore_list = (args.ignore or Config.ignore_list or [])
    save_lock = args.save or False
    lock_filepath = args.file or Config.lock_file_path

    printer = Printer()
    if not validate_files(files=requirements_files,
                          printer=printer,
                          exit_on_failure=exit_on_failure):
        return False

    requirements = RequirementCollection()
    for requirements_file in requirements_files:
        requirements.extend(
            RequirementCollection.from_file(filepath=requirements_file))

    lock_ignore_list = [
        key for key in ignore_list if key not in requirements.keys()
    ]

    packages = (packages or dependency_list(ignore_list=lock_ignore_list))

    locked = locked_requirements(packages=packages, requirements=requirements)

    if save_lock:
        locked.save_lock_file(filepath=lock_filepath)
        printer.success(message=messages.LOCK_EXPORTED.format(
            file_path=lock_filepath))
    else:
        for item in locked:
            printer.info("{}=={}".format(
                printer.colored_message(item.key, color.DEFAULT_PACKAGE),
                item.version_id))

    return True
Example #11
0
def check_unset_locks(requirements, locked, printer=None):
    """Run validation that checks if there are requirements missing in
        locked requirements
    :param requirements: Collection of requirements
    :param locked: Collection of locked requirements
    :param printer: Printer object
    :return: Whether the validation was successful
    """
    printer = printer or Printer()
    locks_unset = unset_locks(requirements=requirements, locked=locked)

    headers = [
        messages.PACKAGE,
        messages.INSTALLED,
    ]

    tabular_data = [
        [
            printer.colored_message(
                message=package.key,
                message_color=printer.color_package
            ),
            package.version_id,
        ]
        for package in locks_unset
    ]

    if tabular_data:
        printer.error(messages.UNSET_LOCKS_FOUND)
        printer.table(
            headers=headers,
            tabular_data=tabular_data
        )
        return False

    printer.success(messages.UNSET_LOCKS_OK)
    return True
Example #12
0
def check_unlocked_requirements(requirements, printer=None):
    """Run validation that checks if there are requirements that are not locked
        to a version
    :param requirements: Collection of requirements
    :param printer: Printer object
    :return: Whether the validation was successful
    """
    printer = printer or Printer()
    requirements_unlocked = unlocked_requirements(requirements=requirements)

    headers = [
        messages.PACKAGE,
        messages.INSTALLED,
    ]

    tabular_data = [
        [
            printer.colored_message(
                message=package.key,
                message_color=printer.color_package
            ),
            package.version_id,
        ]
        for package in requirements_unlocked
    ]

    if tabular_data:
        printer.error(messages.UNLOCKED_REQUIREMENTS_FOUND)
        printer.table(
            headers=headers,
            tabular_data=tabular_data
        )
        return False

    printer.success(messages.UNLOCKED_REQUIREMENTS_OK)
    return True
Example #13
0
File: list.py Project: sbg/dante
def list_command(args, packages=None, exit_on_failure=True):
    """List installed dependencies with configurable filters
    :param args: Command arguments
    :param packages: Collection of packages
    :param exit_on_failure: Enable/disable exiting application on failure
    :return: None
    """
    requirements_files = (args.requirements or Config.requirements_files or [])
    ignore_list = (args.ignore or Config.ignore_list or [])

    printer = Printer()
    if not validate_files(files=requirements_files,
                          printer=printer,
                          exit_on_failure=exit_on_failure):
        return False

    requirements = RequirementCollection()
    for requirements_file in requirements_files:
        requirements.extend(
            RequirementCollection.from_file(filepath=requirements_file))

    requirements = requirements if requirements else None
    packages = (packages or dependency_list(ignore_list=ignore_list,
                                            requirements=requirements))

    headers = [messages.PACKAGE, messages.INSTALLED]
    tabular_data = [[
        printer.colored_message(message=package.key,
                                message_color=printer.color_package),
        package.version_id
    ] for package in packages]

    if tabular_data:
        printer.table(headers=headers, tabular_data=tabular_data)
    else:
        printer.info(messages.PACKAGES_NOT_FOUND)

    return True
Example #14
0
import os
import io
import json
import tempfile
import contextlib

import pip
import pip.req
import pipdeptree

from dante.core.printer import Printer
from dante.core.utils import filter_tree


VERSION_ANY = 'Any'
printer = Printer()


def get_package_tree(ignore_list=None, include_only=None):
    """Returns dependency package tree
    :param ignore_list: list of dependencies to exclude from tree
    :param include_only: list of dependencies to include if
    :return: dictionary of top level packages with their dependencies
    """
    ignore_list = [i.lower() for i in ignore_list] if ignore_list else []
    include_only = [i.lower() for i in include_only] if include_only else []
    packages = [
        package for package in
        pip.get_installed_distributions()
        if package.key not in ignore_list
    ]
Example #15
0
 def exists(self, **printer_info):
     info = self._default()
     info.update(printer_info)
     printer = Printer(**info)
     return printer
Example #16
0
def missing_requirements_command(args, packages=None, exit_on_failure=True):
    """Runs detection of required packages that are not installed
    :param args: Command arguments
    :param packages: Collection of packages
    :param exit_on_failure: Enable/disable exiting application on failure
    :return: None
    """
    requirements_files = (
        args.requirements or Config.requirements_files or []
    )
    ignore_list = (
        args.ignore or Config.ignore_list or []
    )

    printer = Printer()
    if not validate_files(
            files=requirements_files,
            printer=printer,
            exit_on_failure=exit_on_failure):
        return False

    requirements = RequirementCollection()
    for requirements_file in requirements_files:
        requirements.extend(
            RequirementCollection.from_file(filepath=requirements_file)
        )

    packages = (
        packages or dependency_list(ignore_list=ignore_list)
    )

    missing = [
        (package, required_by)
        for package, required_by
        in missing_requirements(
            packages=packages,
            requirements=requirements,
            ignore_list=ignore_list
        )
    ]

    headers = [
        messages.PACKAGE,
        messages.REQUIRED,
        messages.REQUIRED_BY,
    ]

    tabular_data = []
    for package, requirers in missing:
        if requirers:
            for required_by, required_version in requirers:
                tabular_data.append([
                    printer.colored_message(
                        message=package.key,
                        message_color=printer.color_package
                    ),
                    required_version,
                    required_by.key,
                ])
        else:
            tabular_data.append([
                printer.colored_message(
                    message=package.key,
                    message_color=printer.color_package
                ),
                package.version.specifier,
                "Requirements",
            ])

    if tabular_data:
        printer.error(messages.MISSING_FOUND)
        printer.table(headers=headers, tabular_data=tabular_data)
        if exit_on_failure:
            sys.exit(1)
        return False

    printer.success(messages.MISSING_OK)
    return True
Example #17
0
File: tree.py Project: sbg/dante
def tree_command(args, packages=None, exit_on_failure=True):
    """Display dependency tree for a single package or the entire environment
    :param args: Command arguments
    :param packages: Collection of packages
    :param exit_on_failure: Enable/disable exiting application on failure
    :return: None
    """
    package_key = args.package
    requirements_files = (args.requirements or Config.requirements_files or [])
    ignore_list = (args.ignore or Config.ignore_list or [])

    printer = Printer()

    if not validate_files(files=requirements_files,
                          printer=printer,
                          exit_on_failure=exit_on_failure):
        return False

    requirements = RequirementCollection()
    for requirements_file in requirements_files:
        requirements.extend(
            RequirementCollection.from_file(filepath=requirements_file))

    package_string = '{package} [{installed}: {version}]'
    requirement_string = (
        '{spacing}{package} [{installed}: {version} | {required}: {spec}]')

    packages = (packages or dependency_list(ignore_list=ignore_list))

    if package_key:
        package = packages.get(key=package_key)
        if not package:
            printer.error(
                messages.PACKAGE_NOT_FOUND.format(package=package_key))
            sys.exit(1)

        tree = {package: package_dependency_tree(dependency=package)}
    else:
        tree = dependency_tree(
            packages=packages,
            requirements=requirements if requirements else None)

    if not tree:
        printer.info(messages.PACKAGES_NOT_FOUND)

    def print_dependency_tree(requirements_list, indent=0):
        spacing = ' ' * indent
        for requirement in requirements_list:
            printer.info(
                requirement_string.format(
                    spacing=spacing,
                    package=printer.colored_message(
                        message=requirement.key,
                        message_color=printer.color_package),
                    installed=messages.INSTALLED,
                    version=requirement.version_id,
                    required=messages.REQUIRED,
                    spec=requirement.specified_version), )
            print_dependency_tree(requirements_list[requirement], indent + 2)

    for dependency in tree:
        printer.info(
            package_string.format(package=printer.colored_message(
                message=dependency.key, message_color=printer.color_package),
                                  installed=messages.INSTALLED,
                                  version=dependency.version))
        print_dependency_tree(tree[dependency], indent=2)

    return True
Example #18
0
def validate_command(args, packages=None, exit_on_failure=True):
    """Runs requirement file validation
    :param args: Command arguments
    :param packages: Collection of packages
    :param exit_on_failure: Enable/disable exiting application on failure
    :return: None
    """
    strict = args.strict or False
    ignore_list = (
        args.ignore or Config.ignore_list or []
    )
    requirements_files = (
        args.requirements or Config.requirements_files or []
    )
    lock_files = (
        args.lock or Config.lock_files or []
    )

    printer = Printer()
    if not validate_files(
            files=requirements_files,
            printer=printer,
            exit_on_failure=exit_on_failure
        ) or not validate_files(
            files=lock_files,
            printer=printer,
            exit_on_failure=exit_on_failure):
        return False

    try:
        requirements = RequirementCollection.from_files(
            filepaths=requirements_files
        )
        locked = RequirementCollection.from_files(filepaths=lock_files)
    except Exception as e:
        # Always exit on invalid requirements
        printer.error('{}: {}'.format(messages.REQUIREMENTS_PARSING_ERROR, e))
        sys.exit(1)

    checks_ok = []
    packages = (
        packages or dependency_list(ignore_list=ignore_list)
    )

    checks_ok.append(check_unlocked_requirements(
        requirements=requirements,
        printer=printer,
    ))
    checks_ok.append(check_unset_locks(
        requirements=requirements,
        locked=locked,
        printer=printer,
    ))
    checks_ok.append(check_package_version_mismatch(
        packages=packages,
        locked=locked,
        printer=printer,
    ))
    checks_ok.append(check_requirement_version_mismatch(
        requirements=requirements,
        locked=locked,
        printer=printer,
    ))

    if strict:
        checks_ok.append(check_unnecessary_packages(
            packages=packages,
            requirements=requirements,
            locked=locked,
            printer=printer,
        ))
        checks_ok.append(check_unnecessary_locks(
            requirements=requirements,
            locked=locked,
            ignore_list=ignore_list,
            printer=printer,
        ))

    return (
        sys.exit(1) if exit_on_failure else False
        if not all(checks_ok)
        else True
    )