|
1 | 1 | import pkginfo |
2 | 2 | import re |
| 3 | +import requests |
3 | 4 | import shutil |
4 | 5 | import tempfile |
5 | 6 | import json |
6 | 7 | from collections import defaultdict |
7 | 8 | from django.conf import settings |
8 | 9 | from jinja2 import Template |
9 | | -from packaging.utils import canonicalize_name |
| 10 | +from packaging.utils import canonicalize_name, parse_sdist_filename, parse_wheel_filename |
10 | 11 | from packaging.requirements import Requirement |
11 | 12 | from packaging.version import parse, InvalidVersion |
12 | 13 |
|
@@ -189,6 +190,64 @@ def artifact_to_python_content_data(filename, artifact, domain=None): |
189 | 190 | return data |
190 | 191 |
|
191 | 192 |
|
| 193 | +def get_project_metadata_from_pypi_json(package_name, version): |
| 194 | + """ |
| 195 | + Fetches metadata for a specific version of a given package from PyPI's JSON API. |
| 196 | + """ |
| 197 | + # todo: fix URL |
| 198 | + # https://pypi.org/pypi/scipy/1.1.0/json |
| 199 | + # https://fixtures.pulpproject.org/python-pypi/pypi/scipy/1.1.0/json |
| 200 | + URL = "https://fixtures.pulpproject.org/python-pypi/" |
| 201 | + |
| 202 | + url = f"{URL}pypi/{package_name}/{version}/json" |
| 203 | + # todo: raise if version does not exist |
| 204 | + response = requests.get(url, timeout=10) |
| 205 | + response.raise_for_status() |
| 206 | + data = response.json() |
| 207 | + |
| 208 | + return data["info"] |
| 209 | + |
| 210 | + |
| 211 | +def get_packagetype_and_python_version(filename): |
| 212 | + extensions = list(DIST_EXTENSIONS.keys()) |
| 213 | + pkg_type_index = [filename.endswith(ext) for ext in extensions].index(True) |
| 214 | + packagetype = DIST_EXTENSIONS[extensions[pkg_type_index]] |
| 215 | + |
| 216 | + if packagetype == "sdist": |
| 217 | + python_version = "source" |
| 218 | + else: |
| 219 | + pyver = "" |
| 220 | + regex = DIST_REGEXES[extensions[pkg_type_index]] |
| 221 | + if bdist_name := regex.match(filename): |
| 222 | + pyver = bdist_name.group("pyver") or "" |
| 223 | + python_version = pyver |
| 224 | + |
| 225 | + return packagetype, python_version |
| 226 | + |
| 227 | + |
| 228 | +def remote_artifact_to_python_content_data(filename, remote_artifact, domain=None): |
| 229 | + ra_filename = remote_artifact.url.rsplit("/", 1)[-1] |
| 230 | + # todo: better handle, more formats? |
| 231 | + if ra_filename.endswith(".whl"): |
| 232 | + name, version, *_ = parse_wheel_filename(ra_filename) |
| 233 | + elif ra_filename.endswith((".tar.gz", ".zip")): |
| 234 | + name, version = parse_sdist_filename(ra_filename) |
| 235 | + |
| 236 | + metadata = get_project_metadata_from_pypi_json(name, version) |
| 237 | + |
| 238 | + # todo: rewrite |
| 239 | + packagetype, python_version = get_packagetype_and_python_version(filename) |
| 240 | + metadata["packagetype"] = packagetype |
| 241 | + metadata["python_version"] = python_version |
| 242 | + |
| 243 | + data = parse_project_metadata(metadata) |
| 244 | + # data['sha256'] = remote_artifact.sha256 |
| 245 | + data["filename"] = filename |
| 246 | + data["pulp_domain"] = domain or remote_artifact.pulp_domain |
| 247 | + data["_pulp_domain"] = data["pulp_domain"] |
| 248 | + return data |
| 249 | + |
| 250 | + |
192 | 251 | def python_content_to_json(base_path, content_query, version=None, domain=None): |
193 | 252 | """ |
194 | 253 | Converts a QuerySet of PythonPackageContent into the PyPi JSON format |
|
0 commit comments