-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fully supported only for Portage, pkgcore can return only remote-ids.
- Loading branch information
1 parent
597b022
commit ca8076d
Showing
6 changed files
with
195 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
# (c) 2011-2024 Michał Górny <[email protected]> | ||
# (c) 2024 Anna <[email protected]> | ||
# SPDX-License-Identifier: GPL-2.0-or-later | ||
|
||
import os.path | ||
import typing | ||
from abc import abstractmethod, abstractproperty | ||
|
||
from ..util import ( | ||
|
@@ -14,6 +16,7 @@ | |
|
||
from .atom import PMAtom, PMPackageKey | ||
from .environ import PMPackageEnvironment | ||
from gentoopm.basepm.upstream import PMUpstream | ||
|
||
PMPackageState = EnumTuple("PMPackageState", "installable", "installed") | ||
|
||
|
@@ -417,6 +420,13 @@ def maintainers(self): | |
""" | ||
pass | ||
|
||
@property | ||
@abstractmethod | ||
def upstream(self) -> typing.Optional[PMUpstream]: | ||
""" | ||
Get the package upstream metadata (or ``None`` if unavailable). | ||
""" | ||
|
||
@abstractproperty | ||
def repo_masked(self): | ||
""" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# (c) 2024 Anna <[email protected]> | ||
# SPDX-License-Identifier: GPL-2.0-or-later | ||
|
||
import typing | ||
from collections.abc import Iterable | ||
from dataclasses import dataclass | ||
from enum import Enum, auto | ||
|
||
|
||
class PMUpstreamMaintainerStatus(Enum): | ||
""" | ||
Maintainer status enumeration. | ||
""" | ||
|
||
NONE = auto() | ||
ACTIVE = auto() | ||
INACTIVE = auto() | ||
|
||
|
||
@dataclass(frozen=True, order=True) | ||
class PMUpstreamMaintainer: | ||
""" | ||
Representation of an upstream maintainer. | ||
""" | ||
|
||
name: str | ||
email: typing.Optional[str] = None | ||
status: PMUpstreamMaintainerStatus = PMUpstreamMaintainerStatus.NONE | ||
|
||
def __str__(self) -> str: | ||
if self.name and self.email: | ||
return f"{self.name} <{self.email}>" | ||
return self.name | ||
|
||
|
||
@dataclass(frozen=True) | ||
class PMUpstreamDoc: | ||
""" | ||
Representation of a link to the upstream documentation. | ||
""" | ||
|
||
url: str | ||
lang: typing.Optional[str] = None | ||
|
||
def __str__(self) -> str: | ||
return self.url | ||
|
||
|
||
@dataclass(frozen=True) | ||
class PMUpstreamRemoteID: | ||
""" | ||
Representation of an upstream remote-id. | ||
""" | ||
|
||
name: str | ||
site: str | ||
|
||
def __str__(self) -> str: | ||
return f"{self.name}: {self.site}" | ||
|
||
|
||
@dataclass | ||
class PMUpstream: | ||
""" | ||
Representation of upstream metadata. | ||
""" | ||
|
||
bugs_to: typing.Optional[str] = None | ||
changelog: typing.Optional[str] = None | ||
docs: typing.Optional[Iterable[PMUpstreamDoc]] = None | ||
maintainers: typing.Optional[Iterable[PMUpstreamMaintainer]] = None | ||
remote_ids: typing.Optional[Iterable[PMUpstreamRemoteID]] = None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
# (c) 2011-2024 Michał Górny <[email protected]> | ||
# (c) 2024 Anna <[email protected]> | ||
# SPDX-License-Identifier: GPL-2.0-or-later | ||
|
||
import typing | ||
|
||
from ..basepm.pkg import ( | ||
PMPackage, | ||
PMPackageDescription, | ||
|
@@ -12,6 +15,11 @@ | |
PMPackageMaintainer, | ||
) | ||
from ..basepm.pkgset import PMPackageSet, PMFilteredPackageSet | ||
from gentoopm.basepm.upstream import ( | ||
PMUpstream, | ||
PMUpstreamMaintainer, | ||
PMUpstreamRemoteID, | ||
) | ||
from ..util import SpaceSepTuple, SpaceSepFrozenSet | ||
|
||
from .atom import PkgCoreAtom, PkgCorePackageKey | ||
|
@@ -103,6 +111,14 @@ def _iter_maints(): | |
return tuple.__new__(self, _iter_maints()) | ||
|
||
|
||
class PkgCoreUpstream(PMUpstream): | ||
def __getattribute__(self, key: str) -> typing.Any: | ||
if key == "remote_ids": | ||
return super().__getattribute__(key) | ||
raise NotImplementedError("This metadata attribute is not implemented " | ||
"for pkgcore") | ||
|
||
|
||
class PkgCorePackage(PMPackage, PkgCoreAtom): | ||
def __init__(self, pkg, repo_index=0): | ||
self._pkg = pkg | ||
|
@@ -228,6 +244,13 @@ def restrict(self): | |
def maintainers(self): | ||
return PkgCoreMaintainerTuple(self._pkg.maintainers) | ||
|
||
@property | ||
def upstream(self) -> typing.Optional[PkgCoreUpstream]: | ||
result = PkgCoreUpstream() | ||
result.remote_ids = tuple(PMUpstreamRemoteID(r.type, r.name) | ||
for r in self._pkg.upstreams) | ||
return result | ||
|
||
@property | ||
def repo_masked(self): | ||
for m in self._pkg.repo.masked: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,11 @@ | ||
# (c) 2017-2024 Michał Górny <[email protected]> | ||
# (c) 2024 Anna <[email protected]> | ||
# SPDX-License-Identifier: GPL-2.0-or-later | ||
|
||
import errno | ||
import os.path | ||
import typing | ||
from collections.abc import Iterable | ||
from pathlib import Path | ||
|
||
from portage.versions import cpv_getkey | ||
from portage.xml.metadata import MetaDataXML | ||
|
@@ -18,6 +21,12 @@ | |
PMUseFlag, | ||
PMPackageMaintainer, | ||
) | ||
from gentoopm.basepm.upstream import ( | ||
PMUpstream, | ||
PMUpstreamDoc, | ||
PMUpstreamMaintainer, | ||
PMUpstreamRemoteID, | ||
) | ||
from ..basepm.pkgset import PMPackageSet, PMFilteredPackageSet | ||
from ..util import SpaceSepTuple, SpaceSepFrozenSet | ||
|
||
|
@@ -298,6 +307,18 @@ def __init__(self, cpv, dbapi, tree, repo_prio): | |
self._tree = tree | ||
self._repo_prio = repo_prio | ||
|
||
@property | ||
def _metadata(self) -> typing.Optional[MetaDataXML]: | ||
# yes, seriously, the only API portage has is direct parser | ||
# for the XML file | ||
xml_path = Path(self.path).parent / "metadata.xml" | ||
try: | ||
return MetaDataXML(xml_path, None) | ||
except (IOError, OSError) as e: | ||
if e.errno == errno.ENOENT: | ||
return None | ||
raise e | ||
|
||
@property | ||
def path(self): | ||
return self._dbapi.findname(self._cpv, self._tree) | ||
|
@@ -307,19 +328,39 @@ def repository(self): | |
return self._dbapi.getRepositoryName(self._tree) | ||
|
||
@property | ||
def maintainers(self): | ||
# yes, seriously, the only API portage has is direct parser | ||
# for the XML file | ||
xml_path = os.path.join(os.path.dirname(self.path), "metadata.xml") | ||
try: | ||
meta = MetaDataXML(xml_path, None) | ||
except (IOError, OSError) as e: | ||
if e.errno == errno.ENOENT: | ||
return () | ||
raise | ||
|
||
def maintainers(self) -> typing.Optional[Iterable[PortagePackageMaintainer]]: | ||
if (meta := self._metadata) is None: | ||
return None | ||
return tuple(PortagePackageMaintainer(m) for m in meta.maintainers()) | ||
|
||
@property | ||
def upstream(self) -> typing.Optional[PMUpstream]: | ||
if (meta := self._metadata) is None: | ||
return None | ||
|
||
upstreams = meta.upstream() | ||
if len(upstreams) == 0: | ||
return None | ||
upstream = upstreams[0] | ||
|
||
result = PMUpstream() | ||
if len(upstream.bugtrackers) != 0: | ||
result.bugs_to = upstream.bugtrackers[0] | ||
if len(upstream.changelogs) != 0: | ||
result.changelog = upstream.changelogs[0] | ||
|
||
result.docs = tuple(PMUpstreamDoc(url, lang) | ||
for url, lang in upstream.docs) or None | ||
|
||
result.maintainers = tuple(PMUpstreamMaintainer(m.name, m.email) | ||
for m in upstream.maintainers | ||
if m.name) or None | ||
|
||
result.remote_ids = tuple(PMUpstreamRemoteID(name, site) | ||
for site, name in upstream.remoteids | ||
if name and site) or None | ||
return result | ||
|
||
@property | ||
def repo_masked(self): | ||
raise NotImplementedError(".repo_masked is not implemented for Portage") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
# (c) 2011-2024 Michał Górny <[email protected]> | ||
# (c) 2024 Anna <[email protected]> | ||
# SPDX-License-Identifier: GPL-2.0-or-later | ||
|
||
import pytest | ||
|
@@ -125,6 +126,34 @@ def test_no_maintainers(subslotted_pkg): | |
assert list(subslotted_pkg.maintainers) == [] | ||
|
||
|
||
def test_upstream(stack_pkg): | ||
assert (upstream := stack_pkg.upstream) is not None | ||
try: | ||
assert upstream.bugs_to == "https://bugs.example.com/enter_bug.cgi" | ||
assert upstream.changelog == "https://example.com/changelog.txt" | ||
except NotImplementedError: | ||
pytest.skip("upstream.bugs_to not implemented") | ||
|
||
|
||
def test_upstream_remote_id(stack_pkg): | ||
assert (upstream := stack_pkg.upstream) is not None | ||
assert [(r.name, r.site) for r in upstream.remote_ids] == [ | ||
("github", "projg2/gentoopm"), | ||
("pypi", "gentoopm") | ||
] | ||
|
||
|
||
def test_upstream_docs(stack_pkg): | ||
assert (upstream := stack_pkg.upstream) is not None | ||
try: | ||
assert [(d.url, d.lang) for d in upstream.docs] == [ | ||
("https://docs.example.com/en/", None), | ||
("https://docs.example.com/pl/", "pl"), | ||
] | ||
except NotImplementedError: | ||
pytest.skip("upstream.docs not implemented") | ||
|
||
|
||
def test_repo_masked(pm): | ||
pkg = pm.stack.select(PackageNames.pmasked) | ||
try: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,4 +9,12 @@ | |
<email>[email protected]</email> | ||
<name>Michał Górny</name> | ||
</maintainer> | ||
<upstream> | ||
<bugs-to>https://bugs.example.com/enter_bug.cgi</bugs-to> | ||
<changelog>https://example.com/changelog.txt</changelog> | ||
<doc>https://docs.example.com/en/</doc> | ||
<doc lang="pl">https://docs.example.com/pl/</doc> | ||
<remote-id type="github">projg2/gentoopm</remote-id> | ||
<remote-id type="pypi">gentoopm</remote-id> | ||
</upstream> | ||
</pkgmetadata> |