Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: replace deprecated LegacyVersion with own one #4043

Merged
merged 6 commits into from
Dec 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jmespath = "*"
tqdm = "*"
update-checker = "*"
semantic-version = "*"
packaging = "==21.3"
packaging = "*"
cloudsplaining = ">=0.4.3"
networkx = "<2.7"
dockerfile-parse ="*"
Expand Down
30 changes: 7 additions & 23 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.
141 changes: 141 additions & 0 deletions checkov/common/packaging/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.

# Partial copy of https://github.com/pypa/packaging/blob/21.3/packaging/version.py

from __future__ import annotations

import re
from typing import Iterator, TYPE_CHECKING

from packaging import version as packaging_version

if TYPE_CHECKING:
from typing_extensions import TypeAlias

LegacyCmpKey: TypeAlias = "tuple[int, tuple[str, ...]]"
Version = packaging_version.Version


def parse(version: str) -> packaging_version.Version | LegacyVersion:
"""
Parse the given version string and return either a :class:`Version` object
or a :class:`LegacyVersion` object depending on if the given version is
a valid PEP 440 version or a legacy version.
"""
try:
return packaging_version.parse(version)
except packaging_version.InvalidVersion:
return LegacyVersion(version)


class LegacyVersion(packaging_version._BaseVersion):
def __init__(self, version: str) -> None:
self._version = str(version)
self._key = _legacy_cmpkey(self._version) # type:ignore[assignment]

def __str__(self) -> str:
return self._version

def __repr__(self) -> str:
return f"<LegacyVersion('{self}')>"

@property
def public(self) -> str:
return self._version

@property
def base_version(self) -> str:
return self._version

@property
matansha marked this conversation as resolved.
Show resolved Hide resolved
def epoch(self) -> int:
return -1

@property
def release(self) -> None:
return None

@property
def pre(self) -> None:
return None

@property
def post(self) -> None:
return None

@property
def dev(self) -> None:
return None

@property
def local(self) -> None:
return None

@property
def is_prerelease(self) -> bool:
return False

@property
def is_postrelease(self) -> bool:
return False

@property
def is_devrelease(self) -> bool:
return False


_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE | re.IGNORECASE)

_legacy_version_replacement_map = {
"pre": "c",
"preview": "c",
"-": "final-",
"rc": "c",
"dev": "@",
}


def _parse_version_parts(s: str) -> Iterator[str]:
for part in _legacy_version_component_re.split(s):
part = _legacy_version_replacement_map.get(part, part)

if not part or part == ".":
continue

if part[:1] in "0123456789":
# pad for numeric comparison
yield part.zfill(8)
else:
yield "*" + part

# ensure that alpha/beta/candidate are before final
yield "*final"


def _legacy_cmpkey(version: str) -> LegacyCmpKey:

# We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch
# greater than or equal to 0. This will effectively put the LegacyVersion,
# which uses the defacto standard originally implemented by setuptools,
# as before all PEP 440 versions.
epoch = -1

# This scheme is taken from pkg_resources.parse_version setuptools prior to
# it's adoption of the packaging library.
parts: list[str] = []
for part in _parse_version_parts(version.lower()):
if part.startswith("*"):
# remove "-" before a prerelease tag
if part < "*final":
while parts and parts[-1] == "*final-":
parts.pop()

# remove trailing zeros from each series of numeric parts
while parts and parts[-1] == "00000000":
parts.pop()

parts.append(part)

return epoch, tuple(parts)
3 changes: 1 addition & 2 deletions checkov/common/sca/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
from datetime import datetime, timedelta
from typing import TYPE_CHECKING, Any, Optional, Dict, List

from packaging import version as packaging_version

from checkov.common.bridgecrew.integration_features.features.policy_metadata_integration import (
integration as metadata_integration,
)
Expand All @@ -15,6 +13,7 @@
from checkov.common.models.enums import CheckResult, ScanDataFormat
from checkov.common.output.extra_resource import ExtraResource
from checkov.common.output.record import Record, DEFAULT_SEVERITY, SCA_PACKAGE_SCAN_CHECK_NAME, SCA_LICENSE_CHECK_NAME
from checkov.common.packaging import version as packaging_version
from checkov.common.sca.commons import (
get_file_path_for_record,
get_resource_for_record,
Expand Down
2 changes: 1 addition & 1 deletion checkov/common/util/json_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
from typing import Any

from lark import Tree
from packaging.version import LegacyVersion, Version

from checkov.common.bridgecrew.severities import Severity
from checkov.common.output.common import ImageDetails
from checkov.common.packaging.version import LegacyVersion, Version


class CustomJSONEncoder(json.JSONEncoder):
Expand Down
2 changes: 1 addition & 1 deletion checkov/sca_package/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
from dataclasses import dataclass
from typing import List, Union, Dict, Any

from packaging import version as packaging_version
from prettytable import PrettyTable, SINGLE_BORDER

from checkov.common.bridgecrew.severities import Severities, BcSeverities
from checkov.common.models.enums import CheckResult
from checkov.common.output.record import Record, DEFAULT_SEVERITY, SCA_PACKAGE_SCAN_CHECK_NAME, SCA_LICENSE_CHECK_NAME
from checkov.common.packaging import version as packaging_version
from checkov.common.sca.commons import UNFIXABLE_VERSION
from checkov.common.typing import _LicenseStatus

Expand Down
2 changes: 1 addition & 1 deletion checkov/sca_package_2/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
from dataclasses import dataclass
from typing import List, Union, Dict, Any

from packaging import version as packaging_version
from prettytable import PrettyTable, SINGLE_BORDER

from checkov.common.bridgecrew.severities import Severities, BcSeverities
from checkov.common.models.enums import CheckResult
from checkov.common.output.record import Record, DEFAULT_SEVERITY, SCA_PACKAGE_SCAN_CHECK_NAME, SCA_LICENSE_CHECK_NAME
from checkov.common.packaging import version as packaging_version
from checkov.common.sca.commons import UNFIXABLE_VERSION, get_package_alias
from checkov.common.typing import _LicenseStatus

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re
from typing import List, Dict, Optional

from packaging import version
from checkov.common.packaging import version

VERSION_REGEX = re.compile(r"^(?P<operator>=|!=|>=|>|<=|<|~>)?\s*(?P<version>[\d.]+-?\w*)$")

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"tqdm",
"update-checker",
"semantic-version",
"packaging==21.3",
"packaging",
"cloudsplaining>=0.4.3",
"networkx<2.7",
"dockerfile-parse",
Expand Down