Skip to content

update_deps

update_deps task.

Update dependencies in a pyproject.toml file.

ignore_version(current, latest, version_rules, semver_rules)

Determine whether the latest version can be ignored.

Parameters:

Name Type Description Default
current list[str]

The current version as a list of version parts. It's expected, but not required, the version is a semantic version.

required
latest list[str]

The latest version as a list of version parts. It's expected, but not required, the version is a semantic version.

required
version_rules "list[dict[Literal['operator', 'version'], str]]"

Version ignore rules.

required
semver_rules "dict[Literal['version-update'], list[Literal['major', 'minor', 'patch']]]"

Semantic version ignore rules.

required

Returns:

Type Description
bool

Whether or not the latest version can be ignored based on the version and semantic version ignore rules.

Source code in ci_cd/tasks/update_deps.py
def ignore_version(
    current: list[str],
    latest: list[str],
    version_rules: "list[dict[Literal['operator', 'version'], str]]",
    semver_rules: "dict[Literal['version-update'], list[Literal['major', 'minor', 'patch']]]",  # pylint: disable=line-too-long
) -> bool:
    """Determine whether the latest version can be ignored.

    Parameters:
        current: The current version as a list of version parts. It's expected, but not
            required, the version is a semantic version.
        latest: The latest version as a list of version parts. It's expected, but not
            required, the version is a semantic version.
        version_rules: Version ignore rules.
        semver_rules: Semantic version ignore rules.

    Returns:
        Whether or not the latest version can be ignored based on the version and
        semantic version ignore rules.

    """
    # ignore all updates
    if not version_rules and not semver_rules:
        # A package name has been specified without specific rules, ignore all updates
        # for package.
        return True

    # version rules
    if _ignore_version_rules(latest, version_rules):
        return True

    # semver rules
    if "version-update" in semver_rules and _ignore_semver_rules(
        current, latest, semver_rules
    ):
        return True

    return False

parse_ignore_entries(entries, separator)

Parser for the --ignore option.

The --ignore option values are given as key/value-pairs in the form: key=value...key=value. Here ... is the separator value supplied by --ignore-separator.

Parameters:

Name Type Description Default
entries list[str]

The list of supplied --ignore options.

required
separator str

The supplied --ignore-separator value.

required

Returns:

Type Description
'dict[str, dict[Literal["versions", "update-types"], list[str]]]'

A parsed mapping of dependencies to ignore rules.

Source code in ci_cd/tasks/update_deps.py
def parse_ignore_entries(
    entries: list[str], separator: str
) -> 'dict[str, dict[Literal["versions", "update-types"], list[str]]]':
    """Parser for the `--ignore` option.

    The `--ignore` option values are given as key/value-pairs in the form:
    `key=value...key=value`. Here `...` is the separator value supplied by
    `--ignore-separator`.

    Parameters:
        entries: The list of supplied `--ignore` options.
        separator: The supplied `--ignore-separator` value.

    Returns:
        A parsed mapping of dependencies to ignore rules.

    """
    ignore_entries: 'dict[str, dict[Literal["versions", "update-types"], list[str]]]' = (
        {}
    )

    for entry in entries:
        pairs = entry.split(separator, maxsplit=2)
        for pair in pairs:
            if separator in pair:
                raise InputParserError(
                    "More than three key/value-pairs were given for an `--ignore` "
                    "option, while there are only three allowed key names. Input "
                    f"value: --ignore={entry}"
                )

        ignore_entry: 'dict[Literal["dependency-name", "versions", "update-types"], str]' = (  # pylint: disable=line-too-long
            {}
        )
        for pair in pairs:
            match = re.match(
                r"^(?P<key>dependency-name|versions|update-types)=(?P<value>.*)$",
                pair,
            )
            if match is None:
                raise InputParserError(
                    f"Could not parse ignore configuration: {pair!r} (part of the "
                    f"ignore option: {entry!r}"
                )
            if match.group("key") in ignore_entry:
                raise InputParserError(
                    "An ignore configuration can only be given once per option. The "
                    f"configuration key {match.group('key')!r} was found multiple "
                    f"times in the option {entry!r}"
                )

            ignore_entry[match.group("key")] = match.group("value").strip()  # type: ignore[index]  # pylint: disable=line-too-long

        if "dependency-name" not in ignore_entry:
            raise InputError(
                "Ignore option entry missing required 'dependency-name' "
                f"configuration. Ignore option entry: {entry}"
            )

        dependency_name: str = ignore_entry.pop("dependency-name", "")
        if dependency_name not in ignore_entries:
            ignore_entries[dependency_name] = {
                key: [value] for key, value in ignore_entry.items()  # type: ignore[misc]
            }
        else:
            for key, value in ignore_entry.items():
                ignore_entries[dependency_name][key].append(value)  # type: ignore[index]

    return ignore_entries

parse_ignore_rules(rules)

Parser for a specific set of ignore rules.

Parameters:

Name Type Description Default
rules "dict[Literal['versions', 'update-types'], list[str]]"

A set of ignore rules for one or more packages.

required

Returns:

Type Description
"tuple[list[dict[Literal['operator', 'version'], str]], dict[Literal['version-update'], list[Literal['major', 'minor', 'patch']]]]"

A tuple of the parsed 'versions' and 'update-types' entries as dictionaries.

Source code in ci_cd/tasks/update_deps.py
def parse_ignore_rules(
    rules: "dict[Literal['versions', 'update-types'], list[str]]",
) -> "tuple[list[dict[Literal['operator', 'version'], str]], dict[Literal['version-update'], list[Literal['major', 'minor', 'patch']]]]":  # pylint: disable=line-too-long
    """Parser for a specific set of ignore rules.

    Parameters:
        rules: A set of ignore rules for one or more packages.

    Returns:
        A tuple of the parsed 'versions' and 'update-types' entries as dictionaries.

    """
    if not rules:
        # Ignore package altogether
        return [{"operator": ">=", "version": "0"}], {}

    versions: 'list[dict[Literal["operator", "version"], str]]' = []
    update_types: "dict[Literal['version-update'], list[Literal['major', 'minor', 'patch']]]" = (  # pylint: disable=line-too-long
        {}
    )

    if "versions" in rules:
        for versions_entry in rules["versions"]:
            match = re.match(
                r"^(?P<operator>>|<|<=|>=|==|!=|~=)\s*"
                r"(?P<version>[0-9]+(?:\.[0-9]+){0,2})$",
                versions_entry,
            )
            if match is None:
                raise InputParserError(
                    "Ignore option's 'versions' value cannot be parsed. It "
                    "must be a single operator followed by a version number.\n"
                    f"Unparseable 'versions' value: {versions_entry!r}"
                )
            versions.append(match.groupdict())  # type: ignore[arg-type]

    if "update-types" in rules:
        update_types["version-update"] = []
        for update_type_entry in rules["update-types"]:
            match = re.match(
                r"^version-update:semver-(?P<semver_part>major|minor|patch)$",
                update_type_entry,
            )
            if match is None:
                raise InputParserError(
                    "Ignore option's 'update-types' value cannot be parsed."
                    " It must be either: 'version-update:semver-major', "
                    "'version-update:semver-minor' or "
                    "'version-update:semver-patch'.\nUnparseable 'update-types' "
                    f"value: {update_type_entry!r}"
                )
            update_types["version-update"].append(match.group("semver_part"))  # type: ignore[arg-type]  # pylint: disable=line-too-long

    return versions, update_types