404

[ Avaa Bypassed ]




Upload:

Command:

botdev@3.137.143.141: ~ $
"""
Tools for converting old- to new-style metadata.
"""

import email.parser
import os.path
import re
import textwrap
from collections import namedtuple, OrderedDict

import pkg_resources

from . import __version__ as wheel_version
from .pkginfo import read_pkg_info
from .util import OrderedDefaultDict

METADATA_VERSION = "2.0"

PLURAL_FIELDS = {"classifier": "classifiers",
                 "provides_dist": "provides",
                 "provides_extra": "extras"}

SKIP_FIELDS = set()

CONTACT_FIELDS = (({"email": "author_email", "name": "author"},
                   "author"),
                  ({"email": "maintainer_email", "name": "maintainer"},
                   "maintainer"))

# commonly filled out as "UNKNOWN" by distutils:
UNKNOWN_FIELDS = {"author", "author_email", "platform", "home_page", "license"}

# Wheel itself is probably the only program that uses non-extras markers
# in METADATA/PKG-INFO. Support its syntax with the extra at the end only.
EXTRA_RE = re.compile("""^(?P<package>.*?)(;\s*(?P<condition>.*?)(extra == '(?P<extra>.*?)')?)$""")
KEYWORDS_RE = re.compile("[\0-,]+")

MayRequiresKey = namedtuple('MayRequiresKey', ('condition', 'extra'))


def unique(iterable):
    """
    Yield unique values in iterable, preserving order.
    """
    seen = set()
    for value in iterable:
        if value not in seen:
            seen.add(value)
            yield value


def handle_requires(metadata, pkg_info, key):
    """
    Place the runtime requirements from pkg_info into metadata.
    """
    may_requires = OrderedDefaultDict(list)
    for value in sorted(pkg_info.get_all(key)):
        extra_match = EXTRA_RE.search(value)
        if extra_match:
            groupdict = extra_match.groupdict()
            condition = groupdict['condition']
            extra = groupdict['extra']
            package = groupdict['package']
            if condition.endswith(' and '):
                condition = condition[:-5]
        else:
            condition, extra = None, None
            package = value
        key = MayRequiresKey(condition, extra)
        may_requires[key].append(package)

    if may_requires:
        metadata['run_requires'] = []

        def sort_key(item):
            # Both condition and extra could be None, which can't be compared
            # against strings in Python 3.
            key, value = item
            if key.condition is None:
                return ''
            return key.condition

        for key, value in sorted(may_requires.items(), key=sort_key):
            may_requirement = OrderedDict((('requires', value),))
            if key.extra:
                may_requirement['extra'] = key.extra
            if key.condition:
                may_requirement['environment'] = key.condition
            metadata['run_requires'].append(may_requirement)

        if 'extras' not in metadata:
            metadata['extras'] = []
        metadata['extras'].extend([key.extra for key in may_requires.keys() if key.extra])


def pkginfo_to_dict(path, distribution=None):
    """
    Convert PKG-INFO to a prototype Metadata 2.0 (PEP 426) dict.

    The description is included under the key ['description'] rather than
    being written to a separate file.

    path: path to PKG-INFO file
    distribution: optional distutils Distribution()
    """

    metadata = OrderedDefaultDict(
        lambda: OrderedDefaultDict(lambda: OrderedDefaultDict(OrderedDict)))
    metadata["generator"] = "bdist_wheel (" + wheel_version + ")"
    try:
        unicode
        pkg_info = read_pkg_info(path)
    except NameError:
        with open(path, 'rb') as pkg_info_file:
            pkg_info = email.parser.Parser().parsestr(pkg_info_file.read().decode('utf-8'))
    description = None

    if pkg_info['Summary']:
        metadata['summary'] = pkginfo_unicode(pkg_info, 'Summary')
        del pkg_info['Summary']

    if pkg_info['Description']:
        description = dedent_description(pkg_info)
        del pkg_info['Description']
    else:
        payload = pkg_info.get_payload()
        if isinstance(payload, bytes):
            # Avoid a Python 2 Unicode error.
            # We still suffer ? glyphs on Python 3.
            payload = payload.decode('utf-8')
        if payload:
            description = payload

    if description:
        pkg_info['description'] = description

    for key in sorted(unique(k.lower() for k in pkg_info.keys())):
        low_key = key.replace('-', '_')

        if low_key in SKIP_FIELDS:
            continue

        if low_key in UNKNOWN_FIELDS and pkg_info.get(key) == 'UNKNOWN':
            continue

        if low_key in sorted(PLURAL_FIELDS):
            metadata[PLURAL_FIELDS[low_key]] = pkg_info.get_all(key)

        elif low_key == "requires_dist":
            handle_requires(metadata, pkg_info, key)

        elif low_key == 'provides_extra':
            if 'extras' not in metadata:
                metadata['extras'] = []
            metadata['extras'].extend(pkg_info.get_all(key))

        elif low_key == 'home_page':
            metadata['extensions']['python.details']['project_urls'] = {'Home': pkg_info[key]}

        elif low_key == 'keywords':
            metadata['keywords'] = KEYWORDS_RE.split(pkg_info[key])

        else:
            metadata[low_key] = pkg_info[key]

    metadata['metadata_version'] = METADATA_VERSION

    if 'extras' in metadata:
        metadata['extras'] = sorted(set(metadata['extras']))

    # include more information if distribution is available
    if distribution:
        for requires, attr in (('test_requires', 'tests_require'),):
            try:
                requirements = getattr(distribution, attr)
                if isinstance(requirements, list):
                    new_requirements = sorted(convert_requirements(requirements))
                    metadata[requires] = [{'requires': new_requirements}]
            except AttributeError:
                pass

    # handle contacts
    contacts = []
    for contact_type, role in CONTACT_FIELDS:
        contact = OrderedDict()
        for key in sorted(contact_type):
            if contact_type[key] in metadata:
                contact[key] = metadata.pop(contact_type[key])
        if contact:
            contact['role'] = role
            contacts.append(contact)
    if contacts:
        metadata['extensions']['python.details']['contacts'] = contacts

    # convert entry points to exports
    try:
        with open(os.path.join(os.path.dirname(path), "entry_points.txt"), "r") as ep_file:
            ep_map = pkg_resources.EntryPoint.parse_map(ep_file.read())
        exports = OrderedDict()
        for group, items in sorted(ep_map.items()):
            exports[group] = OrderedDict()
            for item in sorted(map(str, items.values())):
                name, export = item.split(' = ', 1)
                exports[group][name] = export
        if exports:
            metadata['extensions']['python.exports'] = exports
    except IOError:
        pass

    # copy console_scripts entry points to commands
    if 'python.exports' in metadata['extensions']:
        for (ep_script, wrap_script) in (('console_scripts', 'wrap_console'),
                                         ('gui_scripts', 'wrap_gui')):
            if ep_script in metadata['extensions']['python.exports']:
                metadata['extensions']['python.commands'][wrap_script] = \
                    metadata['extensions']['python.exports'][ep_script]

    return metadata


def requires_to_requires_dist(requirement):
    """Compose the version predicates for requirement in PEP 345 fashion."""
    requires_dist = []
    for op, ver in requirement.specs:
        requires_dist.append(op + ver)
    if not requires_dist:
        return ''
    return " (%s)" % ','.join(sorted(requires_dist))


def convert_requirements(requirements):
    """Yield Requires-Dist: strings for parsed requirements strings."""
    for req in requirements:
        parsed_requirement = pkg_resources.Requirement.parse(req)
        spec = requires_to_requires_dist(parsed_requirement)
        extras = ",".join(parsed_requirement.extras)
        if extras:
            extras = "[%s]" % extras
        yield (parsed_requirement.project_name + extras + spec)


def generate_requirements(extras_require):
    """
    Convert requirements from a setup()-style dictionary to ('Requires-Dist', 'requirement')
    and ('Provides-Extra', 'extra') tuples.

    extras_require is a dictionary of {extra: [requirements]} as passed to setup(),
    using the empty extra {'': [requirements]} to hold install_requires.
    """
    for extra, depends in extras_require.items():
        condition = ''
        if extra and ':' in extra:  # setuptools extra:condition syntax
            extra, condition = extra.split(':', 1)
            extra = pkg_resources.safe_extra(extra)
        if extra:
            yield ('Provides-Extra', extra)
            if condition:
                condition += " and "
            condition += "extra == '%s'" % extra
        if condition:
            condition = '; ' + condition
        for new_req in convert_requirements(depends):
            yield ('Requires-Dist', new_req + condition)


def pkginfo_to_metadata(egg_info_path, pkginfo_path):
    """
    Convert .egg-info directory with PKG-INFO to the Metadata 1.3 aka
    old-draft Metadata 2.0 format.
    """
    pkg_info = read_pkg_info(pkginfo_path)
    pkg_info.replace_header('Metadata-Version', '2.0')
    requires_path = os.path.join(egg_info_path, 'requires.txt')
    if os.path.exists(requires_path):
        with open(requires_path) as requires_file:
            requires = requires_file.read()
        for extra, reqs in sorted(pkg_resources.split_sections(requires),
                                  key=lambda x: x[0] or ''):
            for item in generate_requirements({extra: reqs}):
                pkg_info[item[0]] = item[1]

    description = pkg_info['Description']
    if description:
        pkg_info.set_payload(dedent_description(pkg_info))
        del pkg_info['Description']

    return pkg_info


def pkginfo_unicode(pkg_info, field):
    """Hack to coax Unicode out of an email Message() - Python 3.3+"""
    text = pkg_info[field]
    field = field.lower()
    if not isinstance(text, str):
        if not hasattr(pkg_info, 'raw_items'):  # Python 3.2
            return str(text)
        for item in pkg_info.raw_items():
            if item[0].lower() == field:
                text = item[1].encode('ascii', 'surrogateescape') \
                    .decode('utf-8')
                break

    return text


def dedent_description(pkg_info):
    """
    Dedent and convert pkg_info['Description'] to Unicode.
    """
    description = pkg_info['Description']

    # Python 3 Unicode handling, sorta.
    surrogates = False
    if not isinstance(description, str):
        surrogates = True
        description = pkginfo_unicode(pkg_info, 'Description')

    description_lines = description.splitlines()
    description_dedent = '\n'.join(
        # if the first line of long_description is blank,
        # the first line here will be indented.
        (description_lines[0].lstrip(),
         textwrap.dedent('\n'.join(description_lines[1:])),
         '\n'))

    if surrogates:
        description_dedent = description_dedent \
            .encode("utf8") \
            .decode("ascii", "surrogateescape")

    return description_dedent


if __name__ == "__main__":
    import sys
    import pprint

    pprint.pprint(pkginfo_to_dict(sys.argv[1]))

Filemanager

Name Type Size Permission Actions
__pycache__ Folder 0755
signatures Folder 0755
tool Folder 0755
__init__.py File 96 B 0644
__main__.py File 419 B 0644
archive.py File 2.32 KB 0644
bdist_wheel.py File 18.41 KB 0644
decorator.py File 541 B 0644
egg2wheel.py File 2.97 KB 0644
install.py File 18 KB 0644
metadata.py File 11.29 KB 0644
paths.py File 1.1 KB 0644
pep425tags.py File 5.63 KB 0644
pkginfo.py File 1.23 KB 0644
util.py File 4.62 KB 0644
wininst2wheel.py File 7.59 KB 0644