Skip to content

Commit 8681509

Browse files
committed
clean up
1 parent 53f01fb commit 8681509

File tree

1 file changed

+63
-75
lines changed

1 file changed

+63
-75
lines changed

src/posit/connect/resources.py

Lines changed: 63 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -85,47 +85,81 @@ def __init__(self, ctx: Context, path: str, pathinfo: str = "", /, **attributes)
8585

8686

8787
class ActiveSequence(ABC, Generic[T], Sequence[T]):
88+
"""A sequence for any HTTP endpoint that returns a collection."""
89+
8890
def __init__(self, ctx: Context, path: str, pathinfo: str = "", uid: str = "guid"):
89-
"""A sequence abstraction for any HTTP GET endpoint that returns a collection.
91+
"""A sequence abstraction for any HTTP GET endpoint that returns a collection."""
92+
super().__init__()
93+
self._ctx: Context = ctx
94+
self._path: str = posixpath.join(path, pathinfo)
95+
self._uid: str = uid
96+
self._cache: Optional[List[T]] = None
9097

91-
It lazily fetches data on demand, caches the results, and allows for standard sequence operations like indexing and slicing.
98+
@abstractmethod
99+
def _create_instance(self, path: str, pathinfo: str, /, **kwargs: Any) -> T:
100+
"""Create an instance of 'T'."""
101+
raise NotImplementedError()
92102

93-
Attributes
94-
----------
95-
_ctx : Context
96-
The context object containing the session and URL for API interactions
97-
_path : str
98-
The HTTP path for the collection endpoint.
99-
_uid : str
100-
The field name used to uniquely identify records.
101-
_cache: Optional[List[T]]
103+
def cached(self) -> bool:
104+
"""Returns True if the collection is cached.
105+
106+
Returns
107+
-------
108+
bool
109+
110+
See Also
111+
--------
112+
reload
113+
"""
114+
return self._cache is not None
115+
116+
def reload(self) -> Self:
117+
"""Reloads the collection from Connect.
118+
119+
Returns
120+
-------
121+
Self
102122
"""
103-
super().__init__()
104-
self._ctx = ctx
105-
self._path = posixpath.join(path, pathinfo)
106-
self._uid = uid
107123
self._cache = None
124+
return self
125+
126+
def _fetch(self) -> List[T]:
127+
"""Fetch the collection.
128+
129+
Fetches the collection directly from Connect. This operation does not effect the cache state.
130+
131+
Returns
132+
-------
133+
List[T]
134+
"""
135+
endpoint = self._ctx.url + self._path
136+
response = self._ctx.session.get(endpoint)
137+
results = response.json()
138+
return [self._to_instance(result) for result in results]
108139

109-
def _make(self, result: dict) -> T:
140+
def _to_instance(self, result: dict) -> T:
141+
"""Converts a result into an instance of T."""
110142
uid = result[self._uid]
111143
return self._create_instance(self._path, uid, **result)
112144

113-
def cached(self) -> bool:
114-
return self._cache is not None
115-
116145
@property
117146
def _data(self) -> List[T]:
118-
if self._cache is None:
119-
self._cache = self.fetch()
120-
return self._cache
147+
"""Get the collection.
121148
122-
@_data.setter
123-
def _data(self, value: List[T]):
124-
self._cache = value
149+
Fetches the collection from Connect and caches the result. Subsequent invocations return the cached results unless the cache is explicitly reset.
125150
126-
@_data.deleter
127-
def _data(self):
128-
self._cache = None
151+
Returns
152+
-------
153+
List[T]
154+
155+
See Also
156+
--------
157+
cached
158+
reload
159+
"""
160+
if self._cache is None:
161+
self._cache = self._fetch()
162+
return self._cache
129163

130164
@overload
131165
def __getitem__(self, index: int) -> T: ...
@@ -145,44 +179,6 @@ def __str__(self) -> str:
145179
def __repr__(self) -> str:
146180
return repr(self._data)
147181

148-
@abstractmethod
149-
def _create_instance(self, path: str, pathinfo: str, /, **kwargs: Any) -> T:
150-
"""Create an instance of 'T'.
151-
152-
Returns
153-
-------
154-
T
155-
"""
156-
raise NotImplementedError()
157-
158-
def reload(self) -> Self:
159-
"""
160-
Clear the cache and reload the data from the API on the next access.
161-
162-
Returns
163-
-------
164-
ActiveSequence
165-
The current instance with cleared cache, ready to reload data on next access.
166-
"""
167-
del self._data
168-
return self
169-
170-
def fetch(self) -> List[T]:
171-
"""
172-
Fetch the collection.
173-
174-
Sends a GET request to fetch the collection from Connect.
175-
176-
Returns
177-
-------
178-
List[T]
179-
A list of items of type `T` representing the fetched data.
180-
"""
181-
endpoint = self._ctx.url + self._path
182-
response = self._ctx.session.get(endpoint)
183-
results = response.json()
184-
return [self._make(result) for result in results]
185-
186182

187183
class ActiveFinderMethods(ActiveSequence[T], ABC):
188184
"""Finder methods.
@@ -206,8 +202,6 @@ def find(self, uid) -> T:
206202
T
207203
"""
208204
if self.cached():
209-
# Check if the record already exists in the cache.
210-
# It is assumed that local cache scan is faster than an additional HTTP request.
211205
conditions = {self._uid: uid}
212206
result = self.find_by(**conditions)
213207
if result:
@@ -216,13 +210,7 @@ def find(self, uid) -> T:
216210
endpoint = self._ctx.url + self._path + uid
217211
response = self._ctx.session.get(endpoint)
218212
result = response.json()
219-
result = self._create_instance(self._path, uid, **result)
220-
221-
# Invalidate the cache.
222-
# It is assumed that the cache is stale since a record exists on the server and not in the cache.
223-
self.reload()
224-
225-
return result
213+
return self._to_instance(result)
226214

227215
def find_by(self, **conditions: Any) -> Optional[T]:
228216
"""

0 commit comments

Comments
 (0)