Skip to content

Commit 85dd5eb

Browse files
committed
Add detail_context and PulpMasterContext
1 parent 2feb2da commit 85dd5eb

File tree

3 files changed

+63
-49
lines changed

3 files changed

+63
-49
lines changed

CHANGES/pulp-glue/+cast.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added `detail_context` to master-detail contexts.

pulp-glue/pulp_glue/common/context.py

Lines changed: 37 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,7 +1304,36 @@ def needs_capability(self, capability: str) -> None:
13041304
)
13051305

13061306

1307-
class PulpRemoteContext(PulpEntityContext):
1307+
class PulpMasterContext(PulpEntityContext):
1308+
TYPE_REGISTRY: t.Final[t.ClassVar[t.Dict[str, t.Type["t.Self"]]]]
1309+
1310+
def __init_subclass__(cls, **kwargs: t.Any) -> None:
1311+
super().__init_subclass__(**kwargs)
1312+
if not hasattr(cls, "RESOURCE_TYPE"):
1313+
cls.TYPE_REGISTRY = {}
1314+
elif hasattr(cls, "PLUGIN"):
1315+
cls.TYPE_REGISTRY[f"{cls.PLUGIN}:{cls.RESOURCE_TYPE}"] = cls
1316+
1317+
def detail_context(self, pulp_href: str) -> "t.Self":
1318+
"""
1319+
Provide a detail context for a matching href.
1320+
"""
1321+
m = re.search(self.HREF_PATTERN, pulp_href)
1322+
if m is None:
1323+
raise PulpException(f"'{pulp_href}' is not an href for {self.ENTITY}.")
1324+
plugin = m.group("plugin")
1325+
resource_type = m.group("resource_type")
1326+
try:
1327+
detail_class = self.TYPE_REGISTRY[f"{plugin}:{resource_type}"]
1328+
except KeyError:
1329+
raise PulpException(
1330+
f"{self.ENTITY} with plugin '{plugin}' and"
1331+
f"resource type '{resource_type}' is unknown."
1332+
)
1333+
return detail_class(self.pulp_ctx, pulp_href=pulp_href)
1334+
1335+
1336+
class PulpRemoteContext(PulpMasterContext):
13081337
"""
13091338
Base class for remote contexts.
13101339
"""
@@ -1330,27 +1359,15 @@ class PulpRemoteContext(PulpEntityContext):
13301359
"sock_read_timeout",
13311360
"rate_limit",
13321361
}
1333-
TYPE_REGISTRY: t.Final[t.Dict[str, t.Type["PulpRemoteContext"]]] = {}
1334-
1335-
def __init_subclass__(cls, **kwargs: t.Any) -> None:
1336-
super().__init_subclass__(**kwargs)
1337-
if hasattr(cls, "PLUGIN") and hasattr(cls, "RESOURCE_TYPE"):
1338-
cls.TYPE_REGISTRY[f"{cls.PLUGIN}:{cls.RESOURCE_TYPE}"] = cls
13391362

13401363

1341-
class PulpPublicationContext(PulpEntityContext):
1364+
class PulpPublicationContext(PulpMasterContext):
13421365
"""Base class for publication contexts."""
13431366

13441367
ENTITY = _("publication")
13451368
ENTITIES = _("publications")
13461369
ID_PREFIX = "publications"
13471370
HREF_PATTERN = r"publications/(?P<plugin>[\w\-_]+)/(?P<resource_type>[\w\-_]+)/"
1348-
TYPE_REGISTRY: t.Final[t.Dict[str, t.Type["PulpPublicationContext"]]] = {}
1349-
1350-
def __init_subclass__(cls, **kwargs: t.Any) -> None:
1351-
super().__init_subclass__(**kwargs)
1352-
if hasattr(cls, "PLUGIN") and hasattr(cls, "RESOURCE_TYPE"):
1353-
cls.TYPE_REGISTRY[f"{cls.PLUGIN}:{cls.RESOURCE_TYPE}"] = cls
13541371

13551372
def list(self, limit: int, offset: int, parameters: t.Dict[str, t.Any]) -> t.List[t.Any]:
13561373
if parameters.get("repository") is not None:
@@ -1360,20 +1377,14 @@ def list(self, limit: int, offset: int, parameters: t.Dict[str, t.Any]) -> t.Lis
13601377
return super().list(limit, offset, parameters)
13611378

13621379

1363-
class PulpDistributionContext(PulpEntityContext):
1380+
class PulpDistributionContext(PulpMasterContext):
13641381
"""Base class for distribution contexts."""
13651382

13661383
ENTITY = _("distribution")
13671384
ENTITIES = _("distributions")
13681385
ID_PREFIX = "distributions"
13691386
HREF_PATTERN = r"distributions/(?P<plugin>[\w\-_]+)/(?P<resource_type>[\w\-_]+)/"
13701387
NULLABLES = {"content_guard", "publication", "remote", "repository", "repository_version"}
1371-
TYPE_REGISTRY: t.Final[t.Dict[str, t.Type["PulpDistributionContext"]]] = {}
1372-
1373-
def __init_subclass__(cls, **kwargs: t.Any) -> None:
1374-
super().__init_subclass__(**kwargs)
1375-
if hasattr(cls, "PLUGIN") and hasattr(cls, "RESOURCE_TYPE"):
1376-
cls.TYPE_REGISTRY[f"{cls.PLUGIN}:{cls.RESOURCE_TYPE}"] = cls
13771388

13781389

13791390
class PulpRepositoryVersionContext(PulpEntityContext):
@@ -1432,7 +1443,7 @@ def repair(self) -> t.Any:
14321443
return self.call("repair", parameters={self.HREF: self.pulp_href}, body={})
14331444

14341445

1435-
class PulpRepositoryContext(PulpEntityContext):
1446+
class PulpRepositoryContext(PulpMasterContext):
14361447
"""Base class for repository contexts."""
14371448

14381449
ENTITY = _("repository")
@@ -1441,12 +1452,6 @@ class PulpRepositoryContext(PulpEntityContext):
14411452
ID_PREFIX = "repositories"
14421453
VERSION_CONTEXT: t.ClassVar[t.Type[PulpRepositoryVersionContext]] = PulpRepositoryVersionContext
14431454
NULLABLES = {"description", "retain_repo_versions"}
1444-
TYPE_REGISTRY: t.Final[t.Dict[str, t.Type["PulpRepositoryContext"]]] = {}
1445-
1446-
def __init_subclass__(cls, **kwargs: t.Any) -> None:
1447-
super().__init_subclass__(**kwargs)
1448-
if hasattr(cls, "PLUGIN") and hasattr(cls, "RESOURCE_TYPE"):
1449-
cls.TYPE_REGISTRY[f"{cls.PLUGIN}:{cls.RESOURCE_TYPE}"] = cls
14501455

14511456
def get_version_context(
14521457
self,
@@ -1555,19 +1560,14 @@ def reclaim(
15551560
return self.call("reclaim_space_reclaim", body=body)
15561561

15571562

1558-
class PulpContentContext(PulpEntityContext):
1563+
class PulpContentContext(PulpMasterContext):
15591564
"""Base class for content contexts."""
15601565

15611566
ENTITY = _("content")
15621567
ENTITIES = _("content")
1568+
HREF_PATTERN = r"content/(?P<plugin>[\w\-_]+)/(?P<resource_type>[\w\-_]+)/"
15631569
ID_PREFIX = "content"
15641570
HREF_PATTERN = r"content/(?P<plugin>[\w\-_]+)/(?P<resource_type>[\w\-_]+)/"
1565-
TYPE_REGISTRY: t.Final[t.Dict[str, t.Type["PulpContentContext"]]] = {}
1566-
1567-
def __init_subclass__(cls, **kwargs: t.Any) -> None:
1568-
super().__init_subclass__(**kwargs)
1569-
if hasattr(cls, "PLUGIN") and hasattr(cls, "RESOURCE_TYPE"):
1570-
cls.TYPE_REGISTRY[f"{cls.PLUGIN}:{cls.RESOURCE_TYPE}"] = cls
15711571

15721572
def __init__(
15731573
self,
@@ -1669,38 +1669,26 @@ def upload(
16691669
return self.create(body=body)
16701670

16711671

1672-
class PulpACSContext(PulpEntityContext):
1672+
class PulpACSContext(PulpMasterContext):
16731673
"""Base class for ACS contexts."""
16741674

16751675
ENTITY = _("ACS")
16761676
ENTITIES = _("ACSes")
16771677
HREF_PATTERN = r"acs/(?P<plugin>[\w\-_]+)/(?P<resource_type>[\w\-_]+)/"
16781678
ID_PREFIX = "acs"
1679-
TYPE_REGISTRY: t.Final[t.Dict[str, t.Type["PulpACSContext"]]] = {}
1680-
1681-
def __init_subclass__(cls, **kwargs: t.Any) -> None:
1682-
super().__init_subclass__(**kwargs)
1683-
if hasattr(cls, "PLUGIN") and hasattr(cls, "RESOURCE_TYPE"):
1684-
cls.TYPE_REGISTRY[f"{cls.PLUGIN}:{cls.RESOURCE_TYPE}"] = cls
16851679

16861680
def refresh(self, href: t.Optional[str] = None) -> t.Any:
16871681
return self.call("refresh", parameters={self.HREF: href or self.pulp_href})
16881682

16891683

1690-
class PulpContentGuardContext(PulpEntityContext):
1684+
class PulpContentGuardContext(PulpMasterContext):
16911685
"""Base class for content guard contexts."""
16921686

16931687
ENTITY = "content guard"
16941688
ENTITIES = "content guards"
16951689
ID_PREFIX = "contentguards"
16961690
HREF_PATTERN = r"contentguards/(?P<plugin>[\w\-_]+)/(?P<resource_type>[\w\-_]+)/"
16971691
NULLABLES = {"description"}
1698-
TYPE_REGISTRY: t.Final[t.Dict[str, t.Type["PulpContentGuardContext"]]] = {}
1699-
1700-
def __init_subclass__(cls, **kwargs: t.Any) -> None:
1701-
super().__init_subclass__(**kwargs)
1702-
if hasattr(cls, "PLUGIN") and hasattr(cls, "RESOURCE_TYPE"):
1703-
cls.TYPE_REGISTRY[f"{cls.PLUGIN}:{cls.RESOURCE_TYPE}"] = cls
17041692

17051693

17061694
EntityFieldDefinition = t.Union[None, str, PulpEntityContext]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import random
2+
import string
3+
import typing as t
4+
5+
import pytest
6+
7+
from pulp_glue.common.context import PulpContext, PulpRepositoryContext
8+
from pulp_glue.file.context import PulpFileRepositoryContext
9+
10+
pytestmark = pytest.mark.glue
11+
12+
13+
@pytest.fixture
14+
def file_repository(pulp_ctx: PulpContext) -> t.Dict[str, t.Any]:
15+
name = "".join(random.choices(string.ascii_letters, k=8))
16+
file_repository_ctx = PulpFileRepositoryContext(pulp_ctx)
17+
yield file_repository_ctx.create(body={"name": name})
18+
file_repository_ctx.delete()
19+
20+
21+
def test_detail_context(pulp_ctx: PulpContext, file_repository: t.Dict[str, t.Any]) -> None:
22+
master_ctx = PulpRepositoryContext(pulp_ctx)
23+
detail_ctx = master_ctx.detail_context(pulp_href=file_repository["pulp_href"])
24+
assert isinstance(detail_ctx, PulpFileRepositoryContext)
25+
assert detail_ctx.entity["name"] == file_repository["name"]

0 commit comments

Comments
 (0)