comparison lib/python3.8/site-packages/wheel/metadata.py @ 1:64071f2a4cf0 draft default tip

Deleted selected files
author guerler
date Mon, 27 Jul 2020 03:55:49 -0400
parents 9e54283cc701
children
comparison
equal deleted inserted replaced
0:9e54283cc701 1:64071f2a4cf0
1 """
2 Tools for converting old- to new-style metadata.
3 """
4
5 import os.path
6 import re
7 import textwrap
8
9 import pkg_resources
10
11 from .pkginfo import read_pkg_info
12
13 # Support markers syntax with the extra at the end only
14 EXTRA_RE = re.compile(
15 r"""^(?P<package>.*?)(;\s*(?P<condition>.*?)(extra == '(?P<extra>.*?)')?)$""")
16
17
18 def requires_to_requires_dist(requirement):
19 """Return the version specifier for a requirement in PEP 345/566 fashion."""
20 if getattr(requirement, 'url', None):
21 return " @ " + requirement.url
22
23 requires_dist = []
24 for op, ver in requirement.specs:
25 requires_dist.append(op + ver)
26 if not requires_dist:
27 return ''
28 return " (%s)" % ','.join(sorted(requires_dist))
29
30
31 def convert_requirements(requirements):
32 """Yield Requires-Dist: strings for parsed requirements strings."""
33 for req in requirements:
34 parsed_requirement = pkg_resources.Requirement.parse(req)
35 spec = requires_to_requires_dist(parsed_requirement)
36 extras = ",".join(sorted(parsed_requirement.extras))
37 if extras:
38 extras = "[%s]" % extras
39 yield (parsed_requirement.project_name + extras + spec)
40
41
42 def generate_requirements(extras_require):
43 """
44 Convert requirements from a setup()-style dictionary to ('Requires-Dist', 'requirement')
45 and ('Provides-Extra', 'extra') tuples.
46
47 extras_require is a dictionary of {extra: [requirements]} as passed to setup(),
48 using the empty extra {'': [requirements]} to hold install_requires.
49 """
50 for extra, depends in extras_require.items():
51 condition = ''
52 extra = extra or ''
53 if ':' in extra: # setuptools extra:condition syntax
54 extra, condition = extra.split(':', 1)
55
56 extra = pkg_resources.safe_extra(extra)
57 if extra:
58 yield 'Provides-Extra', extra
59 if condition:
60 condition = "(" + condition + ") and "
61 condition += "extra == '%s'" % extra
62
63 if condition:
64 condition = ' ; ' + condition
65
66 for new_req in convert_requirements(depends):
67 yield 'Requires-Dist', new_req + condition
68
69
70 def pkginfo_to_metadata(egg_info_path, pkginfo_path):
71 """
72 Convert .egg-info directory with PKG-INFO to the Metadata 2.1 format
73 """
74 pkg_info = read_pkg_info(pkginfo_path)
75 pkg_info.replace_header('Metadata-Version', '2.1')
76 # Those will be regenerated from `requires.txt`.
77 del pkg_info['Provides-Extra']
78 del pkg_info['Requires-Dist']
79 requires_path = os.path.join(egg_info_path, 'requires.txt')
80 if os.path.exists(requires_path):
81 with open(requires_path) as requires_file:
82 requires = requires_file.read()
83
84 parsed_requirements = sorted(pkg_resources.split_sections(requires),
85 key=lambda x: x[0] or '')
86 for extra, reqs in parsed_requirements:
87 for key, value in generate_requirements({extra: reqs}):
88 if (key, value) not in pkg_info.items():
89 pkg_info[key] = value
90
91 description = pkg_info['Description']
92 if description:
93 pkg_info.set_payload(dedent_description(pkg_info))
94 del pkg_info['Description']
95
96 return pkg_info
97
98
99 def pkginfo_unicode(pkg_info, field):
100 """Hack to coax Unicode out of an email Message() - Python 3.3+"""
101 text = pkg_info[field]
102 field = field.lower()
103 if not isinstance(text, str):
104 for item in pkg_info.raw_items():
105 if item[0].lower() == field:
106 text = item[1].encode('ascii', 'surrogateescape') \
107 .decode('utf-8')
108 break
109
110 return text
111
112
113 def dedent_description(pkg_info):
114 """
115 Dedent and convert pkg_info['Description'] to Unicode.
116 """
117 description = pkg_info['Description']
118
119 # Python 3 Unicode handling, sorta.
120 surrogates = False
121 if not isinstance(description, str):
122 surrogates = True
123 description = pkginfo_unicode(pkg_info, 'Description')
124
125 description_lines = description.splitlines()
126 description_dedent = '\n'.join(
127 # if the first line of long_description is blank,
128 # the first line here will be indented.
129 (description_lines[0].lstrip(),
130 textwrap.dedent('\n'.join(description_lines[1:])),
131 '\n'))
132
133 if surrogates:
134 description_dedent = description_dedent \
135 .encode("utf8") \
136 .decode("ascii", "surrogateescape")
137
138 return description_dedent