Source code for pip_rating.packages

from functools import cached_property
from typing import TYPE_CHECKING, Iterator, Set, Optional, TypedDict, List

from anytree import Node

from pip_rating.rating import PackageRating, PackageRatingJson
from pip_rating.sources.audit import Audit, Vulnerability
from pip_rating.sources.pypi import Pypi
from pip_rating.sources.sourcecode_page import SourcecodePage
from pip_rating.sources.sourcerank import SourceRank

if TYPE_CHECKING:
    from pip_rating.dependencies import Dependencies
    from pip_rating.sources.sourcerank import SourceRankBreakdown
    from pip_rating.sources.pypi import PypiPackage


[docs]class PackageJson(TypedDict): name: str version: str sourcerank_breakdown: "SourceRankBreakdown" pypi_package: "PypiPackage" audit_vulnerabilities: List[Vulnerability] rating: PackageRatingJson dependencies: List["PackageJson"]
[docs]class Package: nodes: Set[Node] def __init__(self, dependencies: "Dependencies", name: str): self.dependencies = dependencies self.name = name self.nodes = set() @cached_property def real_name(self) -> str: return self.pypi.package["info"]["name"] @cached_property def first_node(self) -> Node: return next(iter(sorted(self.nodes, key=lambda n: n.depth))) @property def first_node_with_version(self) -> str: return f"{self.first_node.name}=={self.first_node.version}" @cached_property def sourcerank(self) -> SourceRank: return SourceRank(self) @cached_property def pypi(self) -> "Pypi": return Pypi(self.name) @cached_property def sourcecode_page(self) -> "SourcecodePage": return SourcecodePage(self)
[docs] def get_audit(self, node: Node) -> "Audit": return Audit(self.name, node.version)
@cached_property def rating(self) -> "PackageRating": return PackageRating(self)
[docs] def get_node_from_parent( self, from_package: Optional["Package"] = None ) -> Optional["Node"]: """Given this package and a parent package, return the node in the package that is a descendant of the parent package """ if from_package is None: return self.first_node for node in self.nodes: for parent_node in from_package.nodes: if node in parent_node.descendants: return node
[docs] def get_descendant_packages(self) -> Iterator["Package"]: for descendant in self.first_node.descendants: package = self.dependencies.add_node_package(descendant) if package: yield package
[docs] def get_child_packages(self) -> Iterator["Package"]: for child in self.first_node.children: package = self.dependencies.add_node_package(child) if package: yield package
[docs] def add_node(self, node: Node): self.nodes.add(node)
[docs] def as_json(self, from_package: Optional["Package"] = None) -> PackageJson: node = self.get_node_from_parent(from_package) return { "name": self.name, "version": node.version, "sourcerank_breakdown": self.sourcerank.breakdown, "pypi_package": self.pypi.package, "audit_vulnerabilities": self.get_audit(node).vulnerabilities, "rating": self.rating.as_json(from_package), "dependencies": [ self.dependencies.packages[subnode.name].as_json(self) for subnode in node.children ], }
def __repr__(self) -> str: return f"<Package {self.name}>"