updates
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
import abc
|
||||
from dataclasses import field
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
|
||||
from .specification import PythonSpecification
|
||||
|
||||
NOT_IMPLEMENTED_ERROR_MSG = (
|
||||
"Needs implementation for the specific " "specification type."
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Dependency:
|
||||
name: str
|
||||
version: Optional[str]
|
||||
specifications: List[PythonSpecification]
|
||||
found: Optional[Path] = None
|
||||
absolute_path: Optional[Path] = None
|
||||
insecure_versions: List[str] = field(default_factory=lambda: [])
|
||||
secure_versions: List[str] = field(default_factory=lambda: [])
|
||||
latest_version_without_known_vulnerabilities: Optional[str] = None
|
||||
latest_version: Optional[str] = None
|
||||
more_info_url: Optional[str] = None
|
||||
|
||||
def has_unpinned_specification(self):
|
||||
for specification in self.specifications:
|
||||
if not specification.is_pinned():
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_unpinned_specificaitons(self):
|
||||
return filter(
|
||||
lambda specification: not specification.is_pinned(), self.specifications
|
||||
)
|
||||
|
||||
@abc.abstractmethod
|
||||
def filter_by_supported_versions(self, versions: List[str]) -> List[str]:
|
||||
raise NotImplementedError()
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_versions(self, db_full):
|
||||
raise NotImplementedError()
|
||||
|
||||
@abc.abstractmethod
|
||||
def refresh_from(self, db_full):
|
||||
raise NotImplementedError()
|
||||
|
||||
def to_dict(self, **kwargs):
|
||||
if kwargs.get("short_version", False):
|
||||
return {
|
||||
"name": self.name,
|
||||
"version": self.version,
|
||||
"requirements": self.specifications,
|
||||
}
|
||||
|
||||
return {
|
||||
"name": self.name,
|
||||
"version": self.version,
|
||||
"requirements": self.specifications,
|
||||
"found": None,
|
||||
"insecure_versions": self.insecure_versions,
|
||||
"secure_versions": self.secure_versions,
|
||||
"latest_version_without_known_vulnerabilities": self.latest_version_without_known_vulnerabilities, # noqa: E501
|
||||
"latest_version": self.latest_version,
|
||||
"more_info_url": self.more_info_url,
|
||||
}
|
||||
|
||||
def update(self, new):
|
||||
for key, value in new.items():
|
||||
if hasattr(self, key):
|
||||
setattr(self, key, value)
|
||||
|
||||
|
||||
@dataclass
|
||||
class PythonDependency(Dependency):
|
||||
def filter_by_supported_versions(self, versions: List[str]) -> List[str]:
|
||||
from packaging.version import parse as parse_version
|
||||
|
||||
allowed = []
|
||||
|
||||
for version in versions:
|
||||
try:
|
||||
parse_version(version)
|
||||
allowed.append(version)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return allowed
|
||||
|
||||
def get_versions(self, db_full):
|
||||
pkg_meta = db_full.get("meta", {}).get("packages", {}).get(self.name, {})
|
||||
versions = self.filter_by_supported_versions(
|
||||
pkg_meta.get("insecure_versions", []) + pkg_meta.get("secure_versions", [])
|
||||
)
|
||||
return set(versions)
|
||||
|
||||
def refresh_from(self, db_full):
|
||||
from packaging.utils import canonicalize_name
|
||||
|
||||
base_domain = db_full.get("meta", {}).get("base_domain")
|
||||
pkg_meta = (
|
||||
db_full.get("meta", {})
|
||||
.get("packages", {})
|
||||
.get(canonicalize_name(self.name), {})
|
||||
)
|
||||
|
||||
kwargs = {
|
||||
"insecure_versions": self.filter_by_supported_versions(
|
||||
pkg_meta.get("insecure_versions", [])
|
||||
),
|
||||
"secure_versions": self.filter_by_supported_versions(
|
||||
pkg_meta.get("secure_versions", [])
|
||||
),
|
||||
"latest_version_without_known_vulnerabilities": pkg_meta.get(
|
||||
"latest_secure_version", None
|
||||
),
|
||||
"latest_version": pkg_meta.get("latest_version", None),
|
||||
"more_info_url": f"{base_domain}{pkg_meta.get('more_info_path', '')}",
|
||||
}
|
||||
|
||||
self.update(kwargs)
|
||||
|
||||
@staticmethod
|
||||
def find_version(specifications: List[PythonSpecification]) -> Optional[str]:
|
||||
ver = None
|
||||
|
||||
if len(specifications) != 1:
|
||||
return ver
|
||||
|
||||
specification = specifications[0]
|
||||
if specification.is_pinned():
|
||||
ver = next(iter(specification.specifier)).version
|
||||
|
||||
return ver
|
||||
Reference in New Issue
Block a user