1+ from __future__ import annotations
2+
13import posixpath
2- from typing import Literal , Optional , TypedDict , overload
4+ from typing import List , Literal , Optional , TypedDict , overload
35
46from typing_extensions import NotRequired , Required , Unpack
57
68from posit .connect .context import requires
9+ from posit .connect .errors import ClientError
710from posit .connect .paginator import Paginator
811
912from .resources import Active , ActiveFinderMethods , ActiveSequence
@@ -30,6 +33,14 @@ def __init__(self, ctx, path):
3033 def _create_instance (self , path , / , ** attributes ):
3134 return ContentPackage (self ._ctx , ** attributes )
3235
36+ def fetch (self , ** conditions ):
37+ try :
38+ return super ().fetch (** conditions )
39+ except ClientError as e :
40+ if e .http_status == 204 :
41+ return []
42+ raise e
43+
3344 def find (self , uid ):
3445 raise NotImplementedError ("The 'find' method is not support by the Packages API." )
3546
@@ -87,30 +98,53 @@ class ContentPackagesMixin(Active):
8798 """Mixin class to add a packages attribute."""
8899
89100 @property
90- @requires (version = "2024.11.0 " )
101+ @requires (version = "2024.10.0-dev " )
91102 def packages (self ):
92103 path = posixpath .join (self ._path , "packages" )
93104 return ContentPackages (self ._ctx , path )
94105
95106
96- class GlobalPackage (Active ):
97- class _GlobalPackage (TypedDict ):
98- language : Required [str ]
107+ class Package (Active ):
108+ class _Package (TypedDict ):
109+ language : Required [Literal ["python" , "r" ]]
110+ """Programming language ecosystem, options are 'python' and 'r'"""
111+
99112 name : Required [str ]
113+ """The package name"""
114+
100115 version : Required [str ]
116+ """The package version"""
117+
101118 hash : Required [Optional [str ]]
119+ """Package description hash for R packages."""
120+
121+ bundle_id : Required [str ]
122+ """The unique identifier of the bundle this package is associated with"""
102123
103- def __init__ (self , ctx , / , ** attributes : Unpack [_GlobalPackage ]):
124+ app_id : Required [str ]
125+ """The numerical identifier of the application this package is associated with"""
126+
127+ app_guid : Required [str ]
128+ """The numerical identifier of the application this package is associated with"""
129+
130+ def __init__ (self , ctx , / , ** attributes : Unpack [_Package ]):
104131 # todo - passing "" is a hack since path isn't needed. Instead, this class should inherit from Resource, but ActiveSequence is designed to operate on Active. That should change.
105132 super ().__init__ (ctx , "" , ** attributes )
106133
107134
108- class GlobalPackages ( ContentPackages ):
135+ class Packages ( ActiveFinderMethods [ "Package" ], ActiveSequence [ "Package" ] ):
109136 def __init__ (self , ctx , path ):
110137 super ().__init__ (ctx , path , "name" )
111138
112139 def _create_instance (self , path , / , ** attributes ):
113- return ContentPackage (self ._ctx , ** attributes )
140+ return Package (self ._ctx , ** attributes )
141+
142+ def fetch (self , ** conditions ) -> List ["Package" ]:
143+ # todo - add pagination support to ActiveSequence
144+ url = self ._ctx .url + self ._path
145+ paginator = Paginator (self ._ctx .session , url , conditions )
146+ results = paginator .fetch_results ()
147+ return [self ._create_instance ("" , ** result ) for result in results ]
114148
115149 def find (self , uid ):
116150 raise NotImplementedError ("The 'find' method is not support by the Packages API." )
@@ -128,14 +162,17 @@ class _FindBy(TypedDict, total=False):
128162 hash : NotRequired [Optional [str ]]
129163 """Package description hash for R packages."""
130164
131- def fetch (self , ** conditions ):
132- url = self ._ctx .url + self ._path
133- paginator = Paginator (self ._ctx .session , url , conditions )
134- results = paginator .fetch_results ()
135- return [self ._create_instance ("" , ** result ) for result in results ]
165+ bundle_id : NotRequired [str ]
166+ """The unique identifier of the bundle this package is associated with"""
167+
168+ app_id : NotRequired [str ]
169+ """The numerical identifier of the application this package is associated with"""
170+
171+ app_guid : NotRequired [str ]
172+ """The numerical identifier of the application this package is associated with"""
136173
137174 @overload
138- def find_by (self , ** conditions : Unpack [_FindBy ]):
175+ def find_by (self , ** conditions : Unpack [_FindBy ]) -> "Package | None" :
139176 """
140177 Find the first record matching the specified conditions.
141178
@@ -160,12 +197,12 @@ def find_by(self, **conditions: Unpack[_FindBy]):
160197
161198 Returns
162199 -------
163- Optional[T ]
200+ Optional[Package ]
164201 The first record matching the specified conditions, or `None` if no such record exists.
165202 """
166203
167204 @overload
168- def find_by (self , ** conditions ): ...
205+ def find_by (self , ** conditions ) -> "Package | None" : ...
169206
170- def find_by (self , ** conditions ):
207+ def find_by (self , ** conditions ) -> "Package | None" :
171208 return super ().find_by (** conditions )
0 commit comments