Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
pkg_resources.py299 linesDownload Raw Back to metadata
1from __future__ import annotations2 3import email.message4import email.parser5import logging6import os7import zipfile8from collections.abc import Collection, Iterable, Iterator, Mapping9from typing import (10    NamedTuple,11)12 13from pip._vendor import pkg_resources14from pip._vendor.packaging.requirements import Requirement15from pip._vendor.packaging.utils import NormalizedName, canonicalize_name16from pip._vendor.packaging.version import Version17from pip._vendor.packaging.version import parse as parse_version18 19from pip._internal.exceptions import InvalidWheel, NoneMetadataError, UnsupportedWheel20from pip._internal.utils.egg_link import egg_link_path_from_location21from pip._internal.utils.misc import display_path, normalize_path22from pip._internal.utils.wheel import parse_wheel, read_wheel_metadata_file23 24from .base import (25    BaseDistribution,26    BaseEntryPoint,27    BaseEnvironment,28    InfoPath,29    Wheel,30)31 32__all__ = ["NAME", "Distribution", "Environment"]33 34logger = logging.getLogger(__name__)35 36NAME = "pkg_resources"37 38 39class EntryPoint(NamedTuple):40    name: str41    value: str42    group: str43 44 45class InMemoryMetadata:46    """IMetadataProvider that reads metadata files from a dictionary.47 48    This also maps metadata decoding exceptions to our internal exception type.49    """50 51    def __init__(self, metadata: Mapping[str, bytes], wheel_name: str) -> None:52        self._metadata = metadata53        self._wheel_name = wheel_name54 55    def has_metadata(self, name: str) -> bool:56        return name in self._metadata57 58    def get_metadata(self, name: str) -> str:59        try:60            return self._metadata[name].decode()61        except UnicodeDecodeError as e:62            # Augment the default error with the origin of the file.63            raise UnsupportedWheel(64                f"Error decoding metadata for {self._wheel_name}: {e} in {name} file"65            )66 67    def get_metadata_lines(self, name: str) -> Iterable[str]:68        return pkg_resources.yield_lines(self.get_metadata(name))69 70    def metadata_isdir(self, name: str) -> bool:71        return False72 73    def metadata_listdir(self, name: str) -> list[str]:74        return []75 76    def run_script(self, script_name: str, namespace: str) -> None:77        pass78 79 80class Distribution(BaseDistribution):81    def __init__(self, dist: pkg_resources.Distribution) -> None:82        self._dist = dist83        # This is populated lazily, to avoid loading metadata for all possible84        # distributions eagerly.85        self.__extra_mapping: Mapping[NormalizedName, str] | None = None86 87    @property88    def _extra_mapping(self) -> Mapping[NormalizedName, str]:89        if self.__extra_mapping is None:90            self.__extra_mapping = {91                canonicalize_name(extra): extra for extra in self._dist.extras92            }93 94        return self.__extra_mapping95 96    @classmethod97    def from_directory(cls, directory: str) -> BaseDistribution:98        dist_dir = directory.rstrip(os.sep)99 100        # Build a PathMetadata object, from path to metadata. :wink:101        base_dir, dist_dir_name = os.path.split(dist_dir)102        metadata = pkg_resources.PathMetadata(base_dir, dist_dir)103 104        # Determine the correct Distribution object type.105        if dist_dir.endswith(".egg-info"):106            dist_cls = pkg_resources.Distribution107            dist_name = os.path.splitext(dist_dir_name)[0]108        else:109            assert dist_dir.endswith(".dist-info")110            dist_cls = pkg_resources.DistInfoDistribution111            dist_name = os.path.splitext(dist_dir_name)[0].split("-")[0]112 113        dist = dist_cls(base_dir, project_name=dist_name, metadata=metadata)114        return cls(dist)115 116    @classmethod117    def from_metadata_file_contents(118        cls,119        metadata_contents: bytes,120        filename: str,121        project_name: str,122    ) -> BaseDistribution:123        metadata_dict = {124            "METADATA": metadata_contents,125        }126        dist = pkg_resources.DistInfoDistribution(127            location=filename,128            metadata=InMemoryMetadata(metadata_dict, filename),129            project_name=project_name,130        )131        return cls(dist)132 133    @classmethod134    def from_wheel(cls, wheel: Wheel, name: str) -> BaseDistribution:135        try:136            with wheel.as_zipfile() as zf:137                info_dir, _ = parse_wheel(zf, name)138                metadata_dict = {139                    path.split("/", 1)[-1]: read_wheel_metadata_file(zf, path)140                    for path in zf.namelist()141                    if path.startswith(f"{info_dir}/")142                }143        except zipfile.BadZipFile as e:144            raise InvalidWheel(wheel.location, name) from e145        except UnsupportedWheel as e:146            raise UnsupportedWheel(f"{name} has an invalid wheel, {e}")147        dist = pkg_resources.DistInfoDistribution(148            location=wheel.location,149            metadata=InMemoryMetadata(metadata_dict, wheel.location),150            project_name=name,151        )152        return cls(dist)153 154    @property155    def location(self) -> str | None:156        return self._dist.location157 158    @property159    def installed_location(self) -> str | None:160        egg_link = egg_link_path_from_location(self.raw_name)161        if egg_link:162            location = egg_link163        elif self.location:164            location = self.location165        else:166            return None167        return normalize_path(location)168 169    @property170    def info_location(self) -> str | None:171        return self._dist.egg_info172 173    @property174    def installed_by_distutils(self) -> bool:175        # A distutils-installed distribution is provided by FileMetadata. This176        # provider has a "path" attribute not present anywhere else. Not the177        # best introspection logic, but pip has been doing this for a long time.178        try:179            return bool(self._dist._provider.path)180        except AttributeError:181            return False182 183    @property184    def canonical_name(self) -> NormalizedName:185        return canonicalize_name(self._dist.project_name)186 187    @property188    def version(self) -> Version:189        return parse_version(self._dist.version)190 191    @property192    def raw_version(self) -> str:193        return self._dist.version194 195    def is_file(self, path: InfoPath) -> bool:196        return self._dist.has_metadata(str(path))197 198    def iter_distutils_script_names(self) -> Iterator[str]:199        yield from self._dist.metadata_listdir("scripts")200 201    def read_text(self, path: InfoPath) -> str:202        name = str(path)203        if not self._dist.has_metadata(name):204            raise FileNotFoundError(name)205        content = self._dist.get_metadata(name)206        if content is None:207            raise NoneMetadataError(self, name)208        return content209 210    def iter_entry_points(self) -> Iterable[BaseEntryPoint]:211        for group, entries in self._dist.get_entry_map().items():212            for name, entry_point in entries.items():213                name, _, value = str(entry_point).partition("=")214                yield EntryPoint(name=name.strip(), value=value.strip(), group=group)215 216    def _metadata_impl(self) -> email.message.Message:217        """218        :raises NoneMetadataError: if the distribution reports `has_metadata()`219            True but `get_metadata()` returns None.220        """221        if isinstance(self._dist, pkg_resources.DistInfoDistribution):222            metadata_name = "METADATA"223        else:224            metadata_name = "PKG-INFO"225        try:226            metadata = self.read_text(metadata_name)227        except FileNotFoundError:228            if self.location:229                displaying_path = display_path(self.location)230            else:231                displaying_path = repr(self.location)232            logger.warning("No metadata found in %s", displaying_path)233            metadata = ""234        feed_parser = email.parser.FeedParser()235        feed_parser.feed(metadata)236        return feed_parser.close()237 238    def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]:239        if extras:240            relevant_extras = set(self._extra_mapping) & set(241                map(canonicalize_name, extras)242            )243            extras = [self._extra_mapping[extra] for extra in relevant_extras]244        return self._dist.requires(extras)245 246    def iter_provided_extras(self) -> Iterable[NormalizedName]:247        return self._extra_mapping.keys()248 249 250class Environment(BaseEnvironment):251    def __init__(self, ws: pkg_resources.WorkingSet) -> None:252        self._ws = ws253 254    @classmethod255    def default(cls) -> BaseEnvironment:256        return cls(pkg_resources.working_set)257 258    @classmethod259    def from_paths(cls, paths: list[str] | None) -> BaseEnvironment:260        return cls(pkg_resources.WorkingSet(paths))261 262    def _iter_distributions(self) -> Iterator[BaseDistribution]:263        for dist in self._ws:264            yield Distribution(dist)265 266    def _search_distribution(self, name: str) -> BaseDistribution | None:267        """Find a distribution matching the ``name`` in the environment.268 269        This searches from *all* distributions available in the environment, to270        match the behavior of ``pkg_resources.get_distribution()``.271        """272        canonical_name = canonicalize_name(name)273        for dist in self.iter_all_distributions():274            if dist.canonical_name == canonical_name:275                return dist276        return None277 278    def get_distribution(self, name: str) -> BaseDistribution | None:279        # Search the distribution by looking through the working set.280        dist = self._search_distribution(name)281        if dist:282            return dist283 284        # If distribution could not be found, call working_set.require to285        # update the working set, and try to find the distribution again.286        # This might happen for e.g. when you install a package twice, once287        # using setup.py develop and again using setup.py install. Now when288        # running pip uninstall twice, the package gets removed from the289        # working set in the first uninstall, so we have to populate the290        # working set again so that pip knows about it and the packages gets291        # picked up and is successfully uninstalled the second time too.292        try:293            # We didn't pass in any version specifiers, so this can never294            # raise pkg_resources.VersionConflict.295            self._ws.require(name)296        except pkg_resources.DistributionNotFound:297            return None298        return self._search_distribution(name)299 
codekingpro/portable-devtools · Team Ai