commit: 8e70727b745e8259fe0b9e5821b01947143367f5 Author: Michał Górny <mgorny <AT> gentoo <DOT> org> AuthorDate: Tue Feb 7 17:36:15 2023 +0000 Commit: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> CommitDate: Wed Feb 15 17:49:28 2023 +0000 URL: https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=8e70727b
checks: Add a check for PyPI URL replacement with pypi.eclass Signed-off-by: Michał Górny <mgorny <AT> gentoo.org> Closes: https://github.com/pkgcore/pkgcheck/pull/543 Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org> src/pkgcheck/checks/python.py | 153 ++++++++++- .../PythonInlinePyPIURI/expected.json | 20 ++ .../PythonInlinePyPIURI/fix.patch | 304 +++++++++++++++++++++ .../PythonInlinePyPIURL/Manifest | 10 + .../PythonInlinePyPIURL-0.ebuild | 15 + .../PythonInlinePyPIURL-1_alpha1-r1.ebuild | 16 ++ .../PythonInlinePyPIURL-1_alpha1.ebuild | 13 + .../PythonInlinePyPIURL-2_p4-r1.ebuild | 16 ++ .../PythonInlinePyPIURL-2_p4.ebuild | 13 + .../PythonInlinePyPIURL-3-r1.ebuild | 16 ++ .../PythonInlinePyPIURL-3.ebuild | 21 ++ .../PythonInlinePyPIURL-4.ebuild | 16 ++ .../PythonInlinePyPIURL/metadata.xml | 7 + .../python-inline-pypi-url/Manifest | 5 + .../python-inline-pypi-url/metadata.xml | 7 + .../python-inline-pypi-url-0.ebuild | 12 + .../python-inline-pypi-url-1.ebuild | 12 + .../python-inline-pypi-url-100.ebuild | 12 + .../python-inline-pypi-url-1000-r1.ebuild | 12 + .../python-inline-pypi-url-1000-r100.ebuild | 12 + .../python-inline-pypi-url-1000-r101.ebuild | 12 + .../python-inline-pypi-url-1000-r200.ebuild | 12 + .../python-inline-pypi-url-1000.ebuild | 12 + .../python-inline-pypi-url-200.ebuild | 12 + .../repos/python/app-arch/unzip/unzip-0.ebuild | 4 + testdata/repos/python/eclass/pypi.eclass | 107 ++++++++ testdata/repos/python/metadata/stubs | 1 + testdata/repos/python/profiles/thirdpartymirrors | 1 + 28 files changed, 851 insertions(+), 2 deletions(-) diff --git a/src/pkgcheck/checks/python.py b/src/pkgcheck/checks/python.py index 8cd00782..291a56b4 100644 --- a/src/pkgcheck/checks/python.py +++ b/src/pkgcheck/checks/python.py @@ -1,5 +1,6 @@ import itertools import re +import typing from collections import defaultdict from operator import attrgetter @@ -23,6 +24,15 @@ IUSE_PREFIX_S = "python_single_target_" GITHUB_ARCHIVE_RE = re.compile(r"^https://github\.com/[^/]+/[^/]+/archive/") SNAPSHOT_RE = re.compile(r"[a-fA-F0-9]{40}\.tar\.gz$") +PYPI_URI_PREFIX = "https://files.pythonhosted.org/packages/" +PYPI_SDIST_URI_RE = re.compile( + re.escape(PYPI_URI_PREFIX) + r"source/[^/]/(?P<package>[^/]+)/" + r"(?P<fn_package>(?P=package)|[^/-]+)-(?P<version>[^/]+)(?P<suffix>\.tar\.gz|\.zip)$" +) +PYPI_WHEEL_URI_RE = re.compile( + re.escape(PYPI_URI_PREFIX) + r"(?P<pytag>[^/]+)/[^/]/(?P<package>[^/]+)/" + r"(?P<fn_package>[^/-]+)-(?P<version>[^/-]+)-(?P=pytag)-(?P<abitag>[^/]+)\.whl$" +) USE_FLAGS_PYTHON_USEDEP = re.compile(r"\[(.+,)?\$\{PYTHON_USEDEP\}(,.+)?\]$") PROJECT_SYMBOL_NORMALIZE_RE = re.compile(r"[-_.]+") @@ -687,11 +697,44 @@ class PythonGHDistfileSuffix(results.VersionResult, results.Warning): ) +class PythonInlinePyPIURI(results.VersionResult, results.Warning): + """PyPI URI used inline instead of via pypi.eclass""" + + def __init__( + self, + url: str, + replacement: typing.Optional[tuple[str, ...]] = None, + normalize: typing.Optional[bool] = None, + append: typing.Optional[bool] = None, + **kwargs, + ) -> None: + super().__init__(**kwargs) + self.url = url + self.replacement = tuple(replacement) if replacement is not None else None + self.normalize = normalize + self.append = append + + @property + def desc(self) -> str: + if self.replacement is None: + no_norm = "" if self.normalize else "set PYPI_NO_NORMALIZE=1, " + final = "use SRC_URI+= for other URIs" if self.append else "remove SRC_URI" + return ( + "inline PyPI URI found matching pypi.eclass default, inherit the eclass, " + f"{no_norm}and {final} instead" + ) + else: + return ( + f"inline PyPI URI found: {self.url}, inherit pypi.eclass and replace with " + f"$({' '.join(self.replacement)})" + ) + + class PythonFetchableCheck(Check): - """Perform Python-specific checks on fetchables.""" + """Perform Python-specific checks to fetchables.""" required_addons = (addons.UseAddon,) - known_results = frozenset({PythonGHDistfileSuffix}) + known_results = frozenset({PythonGHDistfileSuffix, PythonInlinePyPIURI}) def __init__(self, *args, use_addon): super().__init__(*args) @@ -718,6 +761,111 @@ class PythonFetchableCheck(Check): yield PythonGHDistfileSuffix(f.filename, uri, pkg=pkg) break + @staticmethod + def simplify_pn_pv(pn: str, pv: str, pkg, allow_none: bool) -> tuple[str, str]: + if pv == pkg.version: + pv = None if allow_none else '"${PV}"' + + if pn == pkg.package: + pn = None if pv is None else '"${PN}"' + # check for common PN transforms that conform to naming policy + elif pn == pkg.package.replace("-", ".", 1): + pn = '"${PN/-/.}"' + elif pn == pkg.package.replace("-", "."): + pn = '"${PN//-/.}"' + elif pn == pkg.package.replace("-", "_", 1): + pn = '"${PN/-/_}"' + elif pn == pkg.package.replace("-", "_"): + pn = '"${PN//-/_}"' + # .title() is not exactly the same as ^ + elif pn == f"{pkg.package[:1].upper()}{pkg.package[1:]}": + pn = '"${PN^}"' + + return pn, pv + + @staticmethod + def normalize_distribution_name(name: str) -> str: + """Normalize the distribution according to sdist/wheel spec""" + return PROJECT_SYMBOL_NORMALIZE_RE.sub("_", name).lower() + + @staticmethod + def translate_version(version: str) -> str: + """Translate Gentoo version into PEP 440 version""" + return ( + version.replace("_alpha", "a") + .replace("_beta", "b") + .replace("_rc", "rc") + .replace("_p", ".post") + ) + + def check_pypi_mirror(self, pkg, fetchables): + # consider only packages that don't inherit pypi.eclass already + if "pypi" in pkg.inherited: + return + + uris = [(uri, f.filename) for f in fetchables for uri in f.uri] + # check if we have any mirror://pypi URLs in the first place + pypi_uris = [uri for uri in uris if uri[0].startswith(PYPI_URI_PREFIX)] + if not pypi_uris: + return + + # if there's exactly one PyPI URI, perhaps inheriting the eclass will suffice + if len(pypi_uris) == 1: + uri, filename = pypi_uris[0] + + def matches_fn(expected_fn: str) -> bool: + expected = f"{PYPI_URI_PREFIX}source/{pkg.package[0]}/{pkg.package}/{expected_fn}" + return uri == expected and filename == expected_fn + + version = self.translate_version(pkg.version) + append = len(uris) > 1 + if matches_fn(f"{self.normalize_distribution_name(pkg.package)}-{version}.tar.gz"): + yield PythonInlinePyPIURI(uri, normalize=True, append=append, pkg=pkg) + return + if matches_fn(f"{pkg.package}-{version}.tar.gz"): + yield PythonInlinePyPIURI(uri, normalize=False, append=append, pkg=pkg) + return + + # otherwise, yield result for every URL, with suggested replacement + for uri, dist_filename in pypi_uris: + if source_match := PYPI_SDIST_URI_RE.match(uri): + pn, filename_pn, pv, suffix = source_match.groups() + + if filename_pn == self.normalize_distribution_name(pn): + no_normalize_arg = None + elif filename_pn == pn: + no_normalize_arg = "--no-normalize" + else: # incorrect project name? + continue + if suffix == ".tar.gz": + suffix = None + pn, pv = self.simplify_pn_pv(pn, pv, pkg, suffix is None) + + args = tuple(filter(None, ("pypi_sdist_url", no_normalize_arg, pn, pv, suffix))) + yield PythonInlinePyPIURI(uri, args, pkg=pkg) + continue + + if wheel_match := PYPI_WHEEL_URI_RE.match(uri): + pytag, pn, filename_pn, pv, abitag = wheel_match.groups() + unpack_arg = None + + # only normalized wheel names are supported + if filename_pn != self.normalize_distribution_name(pn): + return + if dist_filename in ( + f"{filename_pn}-{pv}-{pytag}-{abitag}.whl.zip", + f"{filename_pn}-{pv}-{pytag}-{abitag}.zip", + ): + unpack_arg = "--unpack" + if abitag == "none-any": + abitag = None + if pytag == "py3" and abitag is None: + pytag = None + pn, pv = self.simplify_pn_pv(pn, pv, pkg, abitag is None) + + args = tuple(filter(None, ("pypi_wheel_url", unpack_arg, pn, pv, pytag, abitag))) + yield PythonInlinePyPIURI(uri, args, pkg=pkg) + def feed(self, pkg): fetchables, _ = self.iuse_filter( (fetch.fetchable,), @@ -728,6 +876,7 @@ class PythonFetchableCheck(Check): ) yield from self.check_gh_suffix(pkg, fetchables) + yield from self.check_pypi_mirror(pkg, fetchables) class PythonMismatchedPackageName(results.PackageResult, results.Info): diff --git a/testdata/data/repos/python/PythonFetchableCheck/PythonInlinePyPIURI/expected.json b/testdata/data/repos/python/PythonFetchableCheck/PythonInlinePyPIURI/expected.json new file mode 100644 index 00000000..e8c01812 --- /dev/null +++ b/testdata/data/repos/python/PythonFetchableCheck/PythonInlinePyPIURI/expected.json @@ -0,0 +1,20 @@ +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "PythonInlinePyPIURL", "version": "0", "url": "https://files.pythonhosted.org/packages/source/P/PythonInlinePyPIURL/PythonInlinePyPIURL-0.zip", "replacement": ["pypi_sdist_url", "--no-normalize", "\"${PN}\"", "\"${PV}\"", ".zip"], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "PythonInlinePyPIURL", "version": "1_alpha1", "url": "https://files.pythonhosted.org/packages/source/P/PythonInlinePyPIURL/PythonInlinePyPIURL-1a1.tar.gz", "replacement": null, "normalize": false, "append": false} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "PythonInlinePyPIURL", "version": "1_alpha1-r1", "url": "https://files.pythonhosted.org/packages/source/P/PythonInlinePyPIURL/PythonInlinePyPIURL-1a1.tar.gz", "replacement": null, "normalize": false, "append": true} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "PythonInlinePyPIURL", "version": "2_p4", "url": "https://files.pythonhosted.org/packages/source/P/PythonInlinePyPIURL/pythoninlinepypiurl-2.post4.tar.gz", "replacement": null, "normalize": true, "append": false} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "PythonInlinePyPIURL", "version": "2_p4-r1", "url": "https://files.pythonhosted.org/packages/source/P/PythonInlinePyPIURL/pythoninlinepypiurl-2.post4.tar.gz", "replacement": null, "normalize": true, "append": true} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "PythonInlinePyPIURL", "version": "3", "url": "https://files.pythonhosted.org/packages/py3/p/pypi-url/pypi_url-3-py3-none-any.whl", "replacement": ["pypi_wheel_url", "--unpack", "pypi-url"], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "PythonInlinePyPIURL", "version": "3", "url": "https://files.pythonhosted.org/packages/source/p/pypi-url/pypi-url-3.zip", "replacement": ["pypi_sdist_url", "--no-normalize", "pypi-url", "\"${PV}\"", ".zip"], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "PythonInlinePyPIURL", "version": "3-r1", "url": "https://files.pythonhosted.org/packages/py3/p/pypi-url/pypi_url-3-py3-none-any.whl", "replacement": ["pypi_wheel_url", "pypi-url"], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "PythonInlinePyPIURL", "version": "3-r1", "url": "https://files.pythonhosted.org/packages/source/p/pypi-url/pypi-url-3.tar.gz", "replacement": ["pypi_sdist_url", "--no-normalize", "pypi-url"], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "PythonInlinePyPIURL", "version": "4", "url": "https://files.pythonhosted.org/packages/cp310/P/PythonInlinePyPIURL/pythoninlinepypiurl-4-cp310-cp310-linux_x86_64.whl", "replacement": ["pypi_wheel_url", "\"${PN}\"", "\"${PV}\"", "cp310", "cp310-linux_x86_64"], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "PythonInlinePyPIURL", "version": "4", "url": "https://files.pythonhosted.org/packages/source/p/pypi-url/pypi_url-4.tar.gz", "replacement": ["pypi_sdist_url", "pypi-url"], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "python-inline-pypi-url", "version": "0", "url": "https://files.pythonhosted.org/packages/source/p/python.inline-pypi-url/python.inline-pypi-url-0.tar.gz", "replacement": ["pypi_sdist_url", "--no-normalize", "\"${PN/-/.}\""], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "python-inline-pypi-url", "version": "1", "url": "https://files.pythonhosted.org/packages/source/p/python.inline.pypi.url/python.inline.pypi.url-1.tar.gz", "replacement": ["pypi_sdist_url", "--no-normalize", "\"${PN//-/.}\""], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "python-inline-pypi-url", "version": "100", "url": "https://files.pythonhosted.org/packages/source/p/python_inline-pypi-url/python_inline-pypi-url-100.tar.gz", "replacement": ["pypi_sdist_url", "--no-normalize", "\"${PN/-/_}\""], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "python-inline-pypi-url", "version": "200", "url": "https://files.pythonhosted.org/packages/source/P/Python-inline-pypi-url/Python-inline-pypi-url-200.tar.gz", "replacement": ["pypi_sdist_url", "--no-normalize", "\"${PN^}\""], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "python-inline-pypi-url", "version": "1000", "url": "https://files.pythonhosted.org/packages/source/p/python.inline-pypi-url/python_inline_pypi_url-1000.tar.gz", "replacement": ["pypi_sdist_url", "\"${PN/-/.}\""], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "python-inline-pypi-url", "version": "1000-r1", "url": "https://files.pythonhosted.org/packages/source/p/python.inline.pypi.url/python_inline_pypi_url-1000.tar.gz", "replacement": ["pypi_sdist_url", "\"${PN//-/.}\""], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "python-inline-pypi-url", "version": "1000-r100", "url": "https://files.pythonhosted.org/packages/source/p/python_inline-pypi-url/python_inline_pypi_url-1000.tar.gz", "replacement": ["pypi_sdist_url", "\"${PN/-/_}\""], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "python-inline-pypi-url", "version": "1000-r101", "url": "https://files.pythonhosted.org/packages/source/p/python_inline_pypi_url/python_inline_pypi_url-1000.tar.gz", "replacement": ["pypi_sdist_url", "\"${PN//-/_}\""], "normalize": null, "append": null} +{"__class__": "PythonInlinePyPIURI", "category": "PythonFetchableCheck", "package": "python-inline-pypi-url", "version": "1000-r200", "url": "https://files.pythonhosted.org/packages/source/P/Python-inline-pypi-url/python_inline_pypi_url-1000.tar.gz", "replacement": ["pypi_sdist_url", "\"${PN^}\""], "normalize": null, "append": null} diff --git a/testdata/data/repos/python/PythonFetchableCheck/PythonInlinePyPIURI/fix.patch b/testdata/data/repos/python/PythonFetchableCheck/PythonInlinePyPIURI/fix.patch new file mode 100644 index 00000000..e30ff89e --- /dev/null +++ b/testdata/data/repos/python/PythonFetchableCheck/PythonInlinePyPIURI/fix.patch @@ -0,0 +1,304 @@ +diff -Naur python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-0.ebuild fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-0.ebuild +--- python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-0.ebuild 2023-02-13 18:02:07.141313182 +0100 ++++ fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-0.ebuild 2023-02-13 18:16:47.391898323 +0100 +@@ -3,9 +3,11 @@ + + EAPI=8 + ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI="mirror://pypi/${PN::1}/${PN/-/.}/${P/-/.}.tar.gz" ++SRC_URI="$(pypi_sdist_url --no-normalize "${PN/-/.}")" + S=${WORKDIR}/${P/-/.} + + LICENSE="BSD" +diff -Naur python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000.ebuild fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000.ebuild +--- python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000.ebuild 2023-02-13 18:02:37.101867819 +0100 ++++ fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000.ebuild 2023-02-13 18:16:52.222022177 +0100 +@@ -3,10 +3,11 @@ + + EAPI=8 + ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI="mirror://pypi/${PN::1}/${PN/-/.}/${PN//-/_}-${PV}.tar.gz" +-S=${WORKDIR}/${PN//-/_}-${PV} ++SRC_URI="$(pypi_sdist_url "${PN/-/.}")" + + LICENSE="BSD" + SLOT="0" +diff -Naur python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r100.ebuild fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r100.ebuild +--- python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r100.ebuild 2023-02-13 18:05:32.871560794 +0100 ++++ fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r100.ebuild 2023-02-13 18:16:55.365435891 +0100 +@@ -3,10 +3,11 @@ + + EAPI=8 + ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI="mirror://pypi/${PN::1}/${PN/-/_}/${PN//-/_}-${PV}.tar.gz" +-S=${WORKDIR}/${PN//-/_}-${PV} ++SRC_URI="$(pypi_sdist_url "${PN/-/_}")" + + LICENSE="BSD" + SLOT="0" +diff -Naur python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r101.ebuild fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r101.ebuild +--- python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r101.ebuild 2023-02-13 18:05:45.775104791 +0100 ++++ fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r101.ebuild 2023-02-13 18:16:57.982169331 +0100 +@@ -3,10 +3,11 @@ + + EAPI=8 + ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI="mirror://pypi/${PN::1}/${PN//-/_}/${PN//-/_}-${PV}.tar.gz" +-S=${WORKDIR}/${PN//-/_}-${PV} ++SRC_URI="$(pypi_sdist_url "${PN//-/_}")" + + LICENSE="BSD" + SLOT="0" +diff -Naur python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r1.ebuild fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r1.ebuild +--- python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r1.ebuild 2023-02-13 18:04:32.533891351 +0100 ++++ fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r1.ebuild 2023-02-13 18:17:01.165583737 +0100 +@@ -3,10 +3,11 @@ + + EAPI=8 + ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI="mirror://pypi/${PN::1}/${PN//-/.}/${PN//-/_}-${PV}.tar.gz" +-S=${WORKDIR}/${PN//-/_}-${PV} ++SRC_URI="$(pypi_sdist_url "${PN//-/.}")" + + LICENSE="BSD" + SLOT="0" +diff -Naur python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r200.ebuild fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r200.ebuild +--- python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r200.ebuild 2023-02-13 18:06:26.842434235 +0100 ++++ fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r200.ebuild 2023-02-13 18:17:04.392332387 +0100 +@@ -3,10 +3,11 @@ + + EAPI=8 + ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI="mirror://pypi/P/${PN^}/${PN//-/_}-${PV}.tar.gz" +-S=${WORKDIR}/${PN//-/_}-${PV} ++SRC_URI="$(pypi_sdist_url "${PN^}")" + + LICENSE="BSD" + SLOT="0" +diff -Naur python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-100.ebuild fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-100.ebuild +--- python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-100.ebuild 2023-02-13 18:10:56.409921917 +0100 ++++ fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-100.ebuild 2023-02-13 18:17:19.662717926 +0100 +@@ -3,9 +3,11 @@ + + EAPI=8 + ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI="mirror://pypi/${PN::1}/${PN/-/_}/${P/-/_}.tar.gz" ++SRC_URI="$(pypi_sdist_url --no-normalize "${PN/-/_}")" + S=${WORKDIR}/${P/-/_} + + LICENSE="BSD" +diff -Naur python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1.ebuild fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1.ebuild +--- python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1.ebuild 2023-02-13 18:10:03.499125550 +0100 ++++ fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1.ebuild 2023-02-13 18:17:19.666051344 +0100 +@@ -3,9 +3,11 @@ + + EAPI=8 + ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI="mirror://pypi/${PN::1}/${PN//-/.}/${PN//-/.}-${PV}.tar.gz" ++SRC_URI="$(pypi_sdist_url --no-normalize "${PN//-/.}")" + S=${WORKDIR}/${PN//-/.}-${PV} + + LICENSE="BSD" +diff -Naur python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-200.ebuild fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-200.ebuild +--- python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-200.ebuild 2023-02-13 18:12:05.330950479 +0100 ++++ fixed/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-200.ebuild 2023-02-13 18:17:19.666051344 +0100 +@@ -3,9 +3,11 @@ + + EAPI=8 + ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI="mirror://pypi/P/${PN^}/${P^}.tar.gz" ++SRC_URI="$(pypi_sdist_url --no-normalize "${PN^}")" + S=${WORKDIR}/${P^} + + LICENSE="BSD" +diff -Naur python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-0.ebuild fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-0.ebuild +--- python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-0.ebuild 2023-02-13 13:53:39.474144315 +0100 ++++ fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-0.ebuild 2023-02-13 18:13:52.757100032 +0100 +@@ -3,9 +3,11 @@ + + EAPI=8 + ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI="mirror://pypi/${PN::1}/${PN}/${P}.zip" ++SRC_URI="$(pypi_sdist_url --no-normalize "${PN}" "${PV}" .zip)" + + LICENSE="BSD" + SLOT="0" +diff -Naur python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1.ebuild fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1.ebuild +--- python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1.ebuild 2023-02-13 13:45:21.784711215 +0100 ++++ fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1.ebuild 2023-02-13 18:13:52.757100032 +0100 +@@ -3,11 +3,11 @@ + + EAPI=8 + +-MY_P=${P/_alpha/a} ++PYPI_NO_NORMALIZE=1 ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI="mirror://pypi/${PN::1}/${PN}/${MY_P}.tar.gz" +-S=${WORKDIR}/${MY_P} + + LICENSE="BSD" + SLOT="0" +diff -Naur python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1-r1.ebuild fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1-r1.ebuild +--- python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1-r1.ebuild 2023-02-13 13:45:46.604987058 +0100 ++++ fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1-r1.ebuild 2023-02-13 18:13:52.757100032 +0100 +@@ -3,14 +3,14 @@ + + EAPI=8 + +-MY_P=${P/_alpha/a} ++PYPI_NO_NORMALIZE=1 ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI=" +- mirror://pypi/${PN::1}/${PN}/${MY_P}.tar.gz ++SRC_URI+=" + https://example.com/foo.patch + " +-S=${WORKDIR}/${MY_P} + + LICENSE="BSD" + SLOT="0" +diff -Naur python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4.ebuild fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4.ebuild +--- python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4.ebuild 2023-02-13 13:46:34.949608190 +0100 ++++ fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4.ebuild 2023-02-13 18:13:52.757100032 +0100 +@@ -3,11 +3,10 @@ + + EAPI=8 + +-MY_P=${PN,,}-${PV/_p/.post} ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI="mirror://pypi/${PN::1}/${PN}/${MY_P}.tar.gz" +-S=${WORKDIR}/${MY_P} + + LICENSE="BSD" + SLOT="0" +diff -Naur python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4-r1.ebuild fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4-r1.ebuild +--- python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4-r1.ebuild 2023-02-13 13:46:34.949608190 +0100 ++++ fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4-r1.ebuild 2023-02-13 18:13:52.757100032 +0100 +@@ -3,14 +3,13 @@ + + EAPI=8 + +-MY_P=${PN,,}-${PV/_p/.post} ++inherit pypi ++ + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" +-SRC_URI=" +- mirror://pypi/${PN::1}/${PN}/${MY_P}.tar.gz ++SRC_URI+=" + https://example.com/foo.patch + " +-S=${WORKDIR}/${MY_P} + + LICENSE="BSD" + SLOT="0" +diff -Naur python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3.ebuild fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3.ebuild +--- python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3.ebuild 2023-02-13 15:30:06.802489789 +0100 ++++ fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3.ebuild 2023-02-13 18:13:52.757100032 +0100 +@@ -3,13 +3,14 @@ + + EAPI=8 + ++inherit pypi ++ + MY_P=pypi-url-${PV} + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" + SRC_URI=" +- mirror://pypi/p/pypi-url/${MY_P}.zip +- https://files.pythonhosted.org/packages/py3/p/pypi-url/pypi_url-${PV}-py3-none-any.whl +- -> pypi_url-${PV}-py3-none-any.whl.zip ++ $(pypi_sdist_url --no-normalize pypi-url "${PV}" .zip) ++ $(pypi_wheel_url --unpack pypi-url) + " + S=${WORKDIR}/${MY_P} + +diff -Naur python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3-r1.ebuild fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3-r1.ebuild +--- python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3-r1.ebuild 2023-02-13 15:24:31.819467907 +0100 ++++ fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3-r1.ebuild 2023-02-13 18:13:52.757100032 +0100 +@@ -3,12 +3,14 @@ + + EAPI=8 + ++inherit pypi ++ + MY_P=pypi-url-${PV} + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" + SRC_URI=" +- mirror://pypi/p/pypi-url/${MY_P}.tar.gz +- https://files.pythonhosted.org/packages/py3/p/pypi-url/pypi_url-3-py3-none-any.whl ++ $(pypi_sdist_url --no-normalize pypi-url) ++ $(pypi_wheel_url pypi-url) + " + S=${WORKDIR}/${MY_P} + +diff -Naur python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-4.ebuild fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-4.ebuild +--- python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-4.ebuild 2023-02-13 15:30:54.598707954 +0100 ++++ fixed/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-4.ebuild 2023-02-13 18:13:52.757100032 +0100 +@@ -3,12 +3,14 @@ + + EAPI=8 + ++inherit pypi ++ + MY_P=pypi_url-${PV} + DESCRIPTION="Ebuild with PyPI URL" + HOMEPAGE="https://example.com" + SRC_URI=" +- mirror://pypi/p/pypi-url/${MY_P}.tar.gz +- https://files.pythonhosted.org/packages/cp310/${PN::1}/${PN}/${P,,}-cp310-cp310-linux_x86_64.whl ++ $(pypi_sdist_url pypi-url) ++ $(pypi_wheel_url "${PN}" "${PV}" cp310 cp310-linux_x86_64) + " + S=${WORKDIR}/${MY_P} + diff --git a/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/Manifest b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/Manifest new file mode 100644 index 00000000..39d6377a --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/Manifest @@ -0,0 +1,10 @@ +DIST PythonInlinePyPIURL-0.zip 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 +DIST PythonInlinePyPIURL-1a1.tar.gz 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 +DIST foo.patch 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 +DIST pypi-url-3.tar.gz 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 +DIST pypi-url-3.zip 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 +DIST pypi_url-3-py3-none-any.whl 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 +DIST pypi_url-3-py3-none-any.whl.zip 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 +DIST pythoninlinepypiurl-4-cp310-cp310-linux_x86_64.whl 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 +DIST pypi_url-4.tar.gz 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 +DIST pythoninlinepypiurl-2.post4.tar.gz 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 diff --git a/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-0.ebuild b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-0.ebuild new file mode 100644 index 00000000..e37d2061 --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-0.ebuild @@ -0,0 +1,15 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI="mirror://pypi/${PN::1}/${PN}/${P}.zip" + +LICENSE="BSD" +SLOT="0" + +BDEPEND=" + app-arch/unzip +" diff --git a/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1-r1.ebuild b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1-r1.ebuild new file mode 100644 index 00000000..ef9e9a25 --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1-r1.ebuild @@ -0,0 +1,16 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +MY_P=${P/_alpha/a} +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI=" + mirror://pypi/${PN::1}/${PN}/${MY_P}.tar.gz + https://example.com/foo.patch +" +S=${WORKDIR}/${MY_P} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1.ebuild b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1.ebuild new file mode 100644 index 00000000..ed737716 --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-1_alpha1.ebuild @@ -0,0 +1,13 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +MY_P=${P/_alpha/a} +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI="mirror://pypi/${PN::1}/${PN}/${MY_P}.tar.gz" +S=${WORKDIR}/${MY_P} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4-r1.ebuild b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4-r1.ebuild new file mode 100644 index 00000000..88b8ab43 --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4-r1.ebuild @@ -0,0 +1,16 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +MY_P=${PN,,}-${PV/_p/.post} +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI=" + mirror://pypi/${PN::1}/${PN}/${MY_P}.tar.gz + https://example.com/foo.patch +" +S=${WORKDIR}/${MY_P} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4.ebuild b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4.ebuild new file mode 100644 index 00000000..3ff2d8bf --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-2_p4.ebuild @@ -0,0 +1,13 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +MY_P=${PN,,}-${PV/_p/.post} +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI="mirror://pypi/${PN::1}/${PN}/${MY_P}.tar.gz" +S=${WORKDIR}/${MY_P} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3-r1.ebuild b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3-r1.ebuild new file mode 100644 index 00000000..b6232cee --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3-r1.ebuild @@ -0,0 +1,16 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +MY_P=pypi-url-${PV} +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI=" + mirror://pypi/p/pypi-url/${MY_P}.tar.gz + https://files.pythonhosted.org/packages/py3/p/pypi-url/pypi_url-3-py3-none-any.whl +" +S=${WORKDIR}/${MY_P} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3.ebuild b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3.ebuild new file mode 100644 index 00000000..ffa836be --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-3.ebuild @@ -0,0 +1,21 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +MY_P=pypi-url-${PV} +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI=" + mirror://pypi/p/pypi-url/${MY_P}.zip + https://files.pythonhosted.org/packages/py3/p/pypi-url/pypi_url-${PV}-py3-none-any.whl + -> pypi_url-${PV}-py3-none-any.whl.zip +" +S=${WORKDIR}/${MY_P} + +LICENSE="BSD" +SLOT="0" + +BDEPEND=" + app-arch/unzip +" diff --git a/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-4.ebuild b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-4.ebuild new file mode 100644 index 00000000..606bb4bc --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/PythonInlinePyPIURL-4.ebuild @@ -0,0 +1,16 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +MY_P=pypi_url-${PV} +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI=" + mirror://pypi/p/pypi-url/${MY_P}.tar.gz + https://files.pythonhosted.org/packages/cp310/${PN::1}/${PN}/${P,,}-cp310-cp310-linux_x86_64.whl +" +S=${WORKDIR}/${MY_P} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/metadata.xml b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/metadata.xml new file mode 100644 index 00000000..74fae2ac --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/PythonInlinePyPIURL/metadata.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE pkgmetadata SYSTEM "https://www.gentoo.org/dtd/metadata.dtd"> +<pkgmetadata> + <upstream> + <remote-id type="pypi">frobnicate</remote-id> + </upstream> +</pkgmetadata> diff --git a/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/Manifest b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/Manifest new file mode 100644 index 00000000..d541566b --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/Manifest @@ -0,0 +1,5 @@ +DIST python.inline-pypi-url-0.tar.gz 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 +DIST python.inline.pypi.url-1.tar.gz 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 +DIST python_inline-pypi-url-100.tar.gz 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 +DIST Python-inline-pypi-url-200.tar.gz 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 +DIST python_inline_pypi_url-1000.tar.gz 153310 BLAKE2B b7484cd9bebe912f9c8877c0f09df059130c2dc5c4da8c926f8df7945bcb7b255cdf810ce8cd16a987fb5bca3d1e71c088cd894968641db5dfae1c4c059df836 SHA512 86ff9e1c4b9353b1fbb475c7bb9d2a97bd9db8421ea5190b5a84832930b34cb5b79f8c3da68a5eb8db334f06851ec129cc6611a371e47b7c5de7a615feec5e05 diff --git a/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/metadata.xml b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/metadata.xml new file mode 100644 index 00000000..74fae2ac --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/metadata.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE pkgmetadata SYSTEM "https://www.gentoo.org/dtd/metadata.dtd"> +<pkgmetadata> + <upstream> + <remote-id type="pypi">frobnicate</remote-id> + </upstream> +</pkgmetadata> diff --git a/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-0.ebuild b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-0.ebuild new file mode 100644 index 00000000..2fb8d24e --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-0.ebuild @@ -0,0 +1,12 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI="mirror://pypi/${PN::1}/${PN/-/.}/${P/-/.}.tar.gz" +S=${WORKDIR}/${P/-/.} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1.ebuild b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1.ebuild new file mode 100644 index 00000000..983d264f --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1.ebuild @@ -0,0 +1,12 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI="mirror://pypi/${PN::1}/${PN//-/.}/${PN//-/.}-${PV}.tar.gz" +S=${WORKDIR}/${PN//-/.}-${PV} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-100.ebuild b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-100.ebuild new file mode 100644 index 00000000..34189990 --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-100.ebuild @@ -0,0 +1,12 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI="mirror://pypi/${PN::1}/${PN/-/_}/${P/-/_}.tar.gz" +S=${WORKDIR}/${P/-/_} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r1.ebuild b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r1.ebuild new file mode 100644 index 00000000..4528e886 --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r1.ebuild @@ -0,0 +1,12 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI="mirror://pypi/${PN::1}/${PN//-/.}/${PN//-/_}-${PV}.tar.gz" +S=${WORKDIR}/${PN//-/_}-${PV} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r100.ebuild b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r100.ebuild new file mode 100644 index 00000000..3b9ef524 --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r100.ebuild @@ -0,0 +1,12 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI="mirror://pypi/${PN::1}/${PN/-/_}/${PN//-/_}-${PV}.tar.gz" +S=${WORKDIR}/${PN//-/_}-${PV} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r101.ebuild b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r101.ebuild new file mode 100644 index 00000000..24c7fa9d --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r101.ebuild @@ -0,0 +1,12 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI="mirror://pypi/${PN::1}/${PN//-/_}/${PN//-/_}-${PV}.tar.gz" +S=${WORKDIR}/${PN//-/_}-${PV} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r200.ebuild b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r200.ebuild new file mode 100644 index 00000000..543eda6e --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000-r200.ebuild @@ -0,0 +1,12 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI="mirror://pypi/P/${PN^}/${PN//-/_}-${PV}.tar.gz" +S=${WORKDIR}/${PN//-/_}-${PV} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000.ebuild b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000.ebuild new file mode 100644 index 00000000..07e3a6dd --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-1000.ebuild @@ -0,0 +1,12 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI="mirror://pypi/${PN::1}/${PN/-/.}/${PN//-/_}-${PV}.tar.gz" +S=${WORKDIR}/${PN//-/_}-${PV} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-200.ebuild b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-200.ebuild new file mode 100644 index 00000000..e2a5eeb8 --- /dev/null +++ b/testdata/repos/python/PythonFetchableCheck/python-inline-pypi-url/python-inline-pypi-url-200.ebuild @@ -0,0 +1,12 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +DESCRIPTION="Ebuild with PyPI URL" +HOMEPAGE="https://example.com" +SRC_URI="mirror://pypi/P/${PN^}/${P^}.tar.gz" +S=${WORKDIR}/${P^} + +LICENSE="BSD" +SLOT="0" diff --git a/testdata/repos/python/app-arch/unzip/unzip-0.ebuild b/testdata/repos/python/app-arch/unzip/unzip-0.ebuild new file mode 100644 index 00000000..0b7766f5 --- /dev/null +++ b/testdata/repos/python/app-arch/unzip/unzip-0.ebuild @@ -0,0 +1,4 @@ +DESCRIPTION="Stub unzip package to suppress NonexistentDeps results" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" +SLOT="0" +LICENSE="BSD" diff --git a/testdata/repos/python/eclass/pypi.eclass b/testdata/repos/python/eclass/pypi.eclass new file mode 100644 index 00000000..af21dc7f --- /dev/null +++ b/testdata/repos/python/eclass/pypi.eclass @@ -0,0 +1,107 @@ +# Copyright 2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: pypi.eclass +# @MAINTAINER: +# Michał Górny <[email protected]> +# @AUTHOR: +# Michał Górny <[email protected]> +# @SUPPORTED_EAPIS: 7 8 + +# @ECLASS_VARIABLE: PYPI_NO_NORMALIZE +# @PRE_INHERIT +# @DEFAULT_UNSET +# @DESCRIPTION: + +# @FUNCTION: pypi_normalize_name +# @USAGE: <name> +# @DESCRIPTION: +# Normalize the project name according to sdist/wheel normalization +# rules. That is, convert to lowercase and replace runs of [._-] +# with a single underscore. +# +# Based on the spec, as of 2023-02-10: +# https://packaging.python.org/en/latest/specifications/#package-distribution-file-formats +pypi_normalize_name() { + local name=${1} + shopt -s extglob + name=${name//+([._-])/_} + echo "${name,,}" +} + +# @FUNCTION: pypi_translate_version +# @USAGE: <version> +# @DESCRIPTION: +# Translate the specified Gentoo version into the usual Python +# counterpart. Assumes PEP 440 versions. +# +# Note that we do not have clear counterparts for the epoch segment, +# nor for development release segment. +pypi_translate_version() { + local version=${1} + version=${version/_alpha/a} + version=${version/_beta/b} + version=${version/_rc/rc} + version=${version/_p/.post} + echo "${version}" +} + +# @FUNCTION: pypi_sdist_url +# @USAGE: [--no-normalize] [<project> [<version> [<suffix>]]] +# @DESCRIPTION: +pypi_sdist_url() { + local normalize=1 + if [[ ${1} == --no-normalize ]]; then + normalize= + shift + fi + + local project=${1-"${PN}"} + local version=${2-"$(pypi_translate_version "${PV}")"} + local suffix=${3-.tar.gz} + local fn_project=${project} + [[ ${normalize} ]] && fn_project=$(pypi_normalize_name "${project}") + printf "https://files.pythonhosted.org/packages/source/%s" \ + "${project::1}/${project}/${fn_project}-${version}${suffix}" +} + +# @FUNCTION: pypi_wheel_name +# @USAGE: [<project> [<version> [<python-tag> [<abi-platform-tag>]]]] +# @DESCRIPTION: +pypi_wheel_name() { + local project=$(pypi_normalize_name "${1-"${PN}"}") + local version=${2-"$(pypi_translate_version "${PV}")"} + local pytag=${3-py3} + local abitag=${4-none-any} + echo "${project}-${version}-${pytag}-${abitag}.whl" +} + +# @FUNCTION: pypi_wheel_url +# @USAGE: [--unpack] [<project> [<version> [<python-tag> [<abi-platform-tag>]]]] +# @DESCRIPTION: +pypi_wheel_url() { + local unpack= + if [[ ${1} == --unpack ]]; then + unpack=1 + shift + fi + + local filename=$(pypi_wheel_name "${@}") + local project=${1-"${PN}"} + local version=${2-"$(pypi_translate_version "${PV}")"} + local pytag=${3-py3} + printf "https://files.pythonhosted.org/packages/%s" \ + "${pytag}/${project::1}/${project}/${filename}" + + if [[ ${unpack} ]]; then + echo " -> ${filename}.zip" + fi +} + +if [[ ${PYPI_NO_NORMALIZE} ]]; then + SRC_URI="$(pypi_sdist_url --no-normalize)" + S="${WORKDIR}/${PN}-$(pypi_translate_version "${PV}")" +else + SRC_URI="$(pypi_sdist_url)" + S="${WORKDIR}/$(pypi_normalize_name "${PN}")-$(pypi_translate_version "${PV}")" +fi diff --git a/testdata/repos/python/metadata/stubs b/testdata/repos/python/metadata/stubs index 466e30c2..7a9e32b7 100644 --- a/testdata/repos/python/metadata/stubs +++ b/testdata/repos/python/metadata/stubs @@ -1 +1,2 @@ +app-arch/unzip dev-lang/python diff --git a/testdata/repos/python/profiles/thirdpartymirrors b/testdata/repos/python/profiles/thirdpartymirrors new file mode 100644 index 00000000..1605d348 --- /dev/null +++ b/testdata/repos/python/profiles/thirdpartymirrors @@ -0,0 +1 @@ +pypi https://files.pythonhosted.org/packages/source
