11import pkginfo
2+ import re
23import shutil
34import tempfile
45import json
5152 ".zip" : "sdist" ,
5253}
5354
55+ DIST_REGEXES = {
56+ # regex from https://github.com/pypa/pip/blob/18.0/src/pip/_internal/wheel.py#L569
57+ ".whl" : re .compile (
58+ r"""^(?P<name>.+?)-(?P<version>.*?)
59+ ((-(?P<build>\d[^-]*?))?-(?P<pyver>.+?)-(?P<abi>.+?)-(?P<plat>.+?)
60+ \.whl|\.dist-info)$""" ,
61+ re .VERBOSE
62+ ),
63+ # regex based on https://setuptools.pypa.io/en/latest/deprecated/python_eggs.html#filename-embedded-metadata # noqa: E501
64+ ".egg" : re .compile (r"^(?P<name>.+?)-(?P<version>.*?)(-(?P<pyver>.+?(-(?P<plat>.+?))?))?\.egg|\.egg-info$" ), # noqa: E501
65+ # regex based on https://github.com/python/cpython/blob/v3.7.0/Lib/distutils/command/bdist_wininst.py#L292 # noqa: E501
66+ ".exe" : re .compile (r"^(?P<name>.+?)-(?P<version>.*?)\.(?P<plat>.+?)(-(?P<pyver>.+?))?\.exe$" ),
67+ }
68+
5469DIST_TYPES = {
5570 "bdist_wheel" : pkginfo .Wheel ,
5671 "bdist_wininst" : pkginfo .Distribution ,
@@ -72,6 +87,8 @@ def parse_project_metadata(project):
7287 """
7388 package = {}
7489 package ['name' ] = project .get ('name' ) or ""
90+ package ['version' ] = project .get ('version' ) or ""
91+ package ['packagetype' ] = project .get ('packagetype' ) or ""
7592 package ['metadata_version' ] = project .get ('metadata_version' ) or ""
7693 package ['summary' ] = project .get ('summary' ) or ""
7794 package ['description' ] = project .get ('description' ) or ""
@@ -86,13 +103,15 @@ def parse_project_metadata(project):
86103 package ['project_url' ] = project .get ('project_url' ) or ""
87104 package ['platform' ] = project .get ('platform' ) or ""
88105 package ['supported_platform' ] = project .get ('supported_platform' ) or ""
106+ package ['requires_python' ] = project .get ('requires_python' ) or ""
89107 package ['requires_dist' ] = json .dumps (project .get ('requires_dist' , []))
90108 package ['provides_dist' ] = json .dumps (project .get ('provides_dist' , []))
91109 package ['obsoletes_dist' ] = json .dumps (project .get ('obsoletes_dist' , []))
92110 package ['requires_external' ] = json .dumps (project .get ('requires_external' , []))
93111 package ['classifiers' ] = json .dumps (project .get ('classifiers' , []))
94112 package ['project_urls' ] = json .dumps (project .get ('project_urls' , {}))
95113 package ['description_content_type' ] = project .get ('description_content_type' ) or ""
114+ package ['python_version' ] = project .get ('python_version' ) or ""
96115
97116 return package
98117
@@ -113,17 +132,15 @@ def parse_metadata(project, version, distribution):
113132 dictionary: of useful python metadata
114133
115134 """
116- package = {}
135+ package = parse_project_metadata ( project )
117136
118137 package ['filename' ] = distribution .get ('filename' ) or ""
119138 package ['packagetype' ] = distribution .get ('packagetype' ) or ""
120- package ['version' ] = version
139+ assert package ['version' ] = = version
121140 package ['url' ] = distribution .get ('url' ) or ""
122141 package ['sha256' ] = distribution .get ('digests' , {}).get ('sha256' ) or ""
123- package ['python_version' ] = distribution .get ('python_version' ) or ""
124- package ['requires_python' ] = distribution .get ('requires_python' ) or ""
125-
126- package .update (parse_project_metadata (project ))
142+ package ['python_version' ] = distribution .get ('python_version' ) or package .get ('python_version' )
143+ package ['requires_python' ] = distribution .get ('requires_python' ) or package .get ('requires_python' )
127144
128145 return package
129146
@@ -147,9 +164,30 @@ def get_project_metadata_from_artifact(filename, artifact):
147164 temp_file .flush ()
148165 metadata = DIST_TYPES [packagetype ](temp_file .name )
149166 metadata .packagetype = packagetype
167+ if packagetype == "sdist" :
168+ metadata .python_version = "source"
169+ else :
170+ pyver = ""
171+ regex = DIST_REGEXES [extensions [pkg_type_index ]]
172+ if bdist_name := regex .match (filename ):
173+ pyver = bdist_name .group ("pyver" ) or ""
174+ metadata .python_version = pyver
150175 return metadata
151176
152177
178+ def artifact_to_python_content_data (filename , artifact , domain = None ):
179+ """
180+ Takes the artifact/filename and returns the metadata needed to create a PythonPackageContent.
181+ """
182+ metadata = get_project_metadata_from_artifact (filename , artifact )
183+ data = parse_project_metadata (vars (metadata ))
184+ data ['sha256' ] = artifact .sha256
185+ data ['filename' ] = filename
186+ data ['pulp_domain' ] = domain or artifact .pulp_domain
187+ data ['_pulp_domain' ] = data ['pulp_domain' ]
188+ return data
189+
190+
153191def python_content_to_json (base_path , content_query , version = None , domain = None ):
154192 """
155193 Converts a QuerySet of PythonPackageContent into the PyPi JSON format
0 commit comments