Skip to content

Commit 0493db2

Browse files
committed
feat: add packages attribute to content
1 parent d69dac1 commit 0493db2

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

src/posit/connect/content.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from typing import Any, List, Literal, Optional, overload
99

1010
from posit.connect.oauth.associations import ContentItemAssociations
11+
from posit.connect.packages import PackagesMixin
1112

1213
from . import tasks
1314
from .bundles import Bundles
@@ -32,7 +33,8 @@ class ContentItemOwner(Resource):
3233
pass
3334

3435

35-
class ContentItem(Resource):
36+
class ContentItem(PackagesMixin, Resource):
37+
3638
def __getitem__(self, key: Any) -> Any:
3739
v = super().__getitem__(key)
3840
if key == "owner" and isinstance(v, dict):

src/posit/connect/packages.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
from typing import Literal, Optional, Sequence, TypedDict
2+
3+
from typing_extensions import NotRequired, Required, Unpack
4+
5+
from .resources import Resource, ResourceParameters, Resources
6+
7+
8+
class Package(Resource):
9+
"""A package resource."""
10+
11+
class PackageAttributes(TypedDict):
12+
"""Package attributes."""
13+
14+
language: Required[Literal['r', 'python']]
15+
name: Required[str]
16+
version: Required[str]
17+
hash: NotRequired[str]
18+
19+
def __init__(
20+
self,
21+
/,
22+
params: ResourceParameters,
23+
**kwargs: Unpack[PackageAttributes],
24+
):
25+
"""Initialize a Vanity.
26+
27+
Parameters
28+
----------
29+
params : ResourceParameters
30+
"""
31+
super().__init__(params, **kwargs)
32+
33+
34+
class Packages(Resources, Sequence[Package]):
35+
"""Manages a collection of vanities."""
36+
37+
def __init__(self, params, endpoint):
38+
super().__init__(params)
39+
self._endpoint = endpoint
40+
self._packages = []
41+
self.reload()
42+
43+
def __getitem__(self, index):
44+
"""Retrieve an item or slice from the sequence."""
45+
return self._packages[index]
46+
47+
def __len__(self):
48+
"""Return the length of the sequence."""
49+
return len(self._packages)
50+
51+
def __repr__(self):
52+
"""Return the string representation of the sequence."""
53+
return f"MySequence({', '.join(map(str, self._packages))})"
54+
55+
def count(self, value):
56+
"""Return the number of occurrences of a value in the sequence."""
57+
return self._packages.count(value)
58+
59+
def index(self, value, start=0, stop=None):
60+
"""Return the index of the first occurrence of a value in the sequence."""
61+
if stop is None:
62+
stop = len(self._packages)
63+
return self._packages.index(value, start, stop)
64+
65+
def reload(self) -> 'Packages':
66+
"""Retrieve all packages.
67+
68+
Returns
69+
-------
70+
List[Package]
71+
"""
72+
response = self.params.session.get(self._endpoint)
73+
results = response.json()
74+
packages = [Package(self.params, **result) for result in results]
75+
self._packages = packages
76+
return self
77+
78+
class PackagesMixin(Resource):
79+
"""Mixin class to add a packages to a resource."""
80+
81+
class HasGuid(TypedDict):
82+
"""Has a guid."""
83+
84+
guid: Required[str]
85+
86+
def __init__(self, params: ResourceParameters, **kwargs: Unpack[HasGuid]):
87+
super().__init__(params, **kwargs)
88+
self._guid = kwargs["guid"]
89+
self._packages: Optional[Packages] = None
90+
91+
@property
92+
def packages(self) -> Optional[Packages]:
93+
"""Get the vanity."""
94+
if self._packages:
95+
return self._packages
96+
97+
endpoint = self.params.url + f"v1/content/{self._guid}/packages"
98+
self._packages = Packages(self.params, endpoint)
99+
return self._packages.reload()

0 commit comments

Comments
 (0)