|
1 | | -# TODO-barret-future; Piecemeal migrate everything to leverage `ApiDictEndpoint` and `ApiListEndpoint` classes. |
| 1 | +# TODO-barret-future; Piecemeal migrate everything to leverage `ApiDictEndpoint` |
2 | 2 | # TODO-barret-future; Merge any trailing behavior of `Active` or `ActiveList` into the new classes. |
3 | 3 |
|
4 | 4 | from __future__ import annotations |
5 | 5 |
|
6 | | -import itertools |
7 | | -import posixpath |
8 | | -from abc import ABC, abstractmethod |
9 | 6 | from collections.abc import Mapping |
10 | | -from typing import TYPE_CHECKING, Any, Generator, Generic, Optional, TypeVar, cast, overload |
| 7 | +from typing import TYPE_CHECKING, Any, Optional, cast |
11 | 8 |
|
12 | 9 | from ._api_call import ApiCallMixin, get_api |
13 | 10 | from ._json import Jsonifiable, JsonifiableDict, ResponseAttrs |
@@ -143,136 +140,3 @@ def __init__( |
143 | 140 | super().__init__(attrs) |
144 | 141 | self._ctx = ctx |
145 | 142 | self._path = path |
146 | | - |
147 | | - |
148 | | -T = TypeVar("T", bound="ReadOnlyDict") |
149 | | -"""A type variable that is bound to the `Active` class""" |
150 | | - |
151 | | - |
152 | | -class ApiListEndpoint(ApiCallMixin, Generic[T], ABC, object): |
153 | | - """A HTTP GET endpoint that can fetch a collection.""" |
154 | | - |
155 | | - def __init__(self, *, ctx: Context, path: str, uid_key: str = "guid") -> None: |
156 | | - """A sequence abstraction for any HTTP GET endpoint that returns a collection. |
157 | | -
|
158 | | - Parameters |
159 | | - ---------- |
160 | | - ctx : Context |
161 | | - The context object containing the session and URL for API interactions. |
162 | | - path : str |
163 | | - The HTTP path component for the collection endpoint |
164 | | - uid_key : str, optional |
165 | | - The field name of that uniquely identifiers an instance of T, by default "guid" |
166 | | - """ |
167 | | - super().__init__() |
168 | | - self._ctx = ctx |
169 | | - self._path = path |
170 | | - self._uid_key = uid_key |
171 | | - |
172 | | - @abstractmethod |
173 | | - def _create_instance(self, path: str, /, **kwargs: Any) -> T: |
174 | | - """Create an instance of 'T'.""" |
175 | | - raise NotImplementedError() |
176 | | - |
177 | | - def fetch(self) -> Generator[T, None, None]: |
178 | | - """Fetch the collection. |
179 | | -
|
180 | | - Fetches the collection directly from Connect. This operation does not effect the cache state. |
181 | | -
|
182 | | - Returns |
183 | | - ------- |
184 | | - List[T] |
185 | | - """ |
186 | | - results: Jsonifiable = self._get_api() |
187 | | - results_list = cast(list[JsonifiableDict], results) |
188 | | - for result in results_list: |
189 | | - yield self._to_instance(result) |
190 | | - |
191 | | - def __iter__(self) -> Generator[T, None, None]: |
192 | | - return self.fetch() |
193 | | - |
194 | | - def _to_instance(self, result: dict) -> T: |
195 | | - """Converts a result into an instance of T.""" |
196 | | - uid = result[self._uid_key] |
197 | | - path = posixpath.join(self._path, uid) |
198 | | - return self._create_instance(path, **result) |
199 | | - |
200 | | - @overload |
201 | | - def __getitem__(self, index: int) -> T: ... |
202 | | - |
203 | | - @overload |
204 | | - def __getitem__(self, index: slice) -> Generator[T, None, None]: ... |
205 | | - |
206 | | - def __getitem__(self, index: int | slice) -> T | Generator[T, None, None]: |
207 | | - if isinstance(index, slice): |
208 | | - results = itertools.islice(self.fetch(), index.start, index.stop, index.step) |
209 | | - for result in results: |
210 | | - yield result |
211 | | - else: |
212 | | - return list(itertools.islice(self.fetch(), index, index + 1))[0] |
213 | | - |
214 | | - # def __len__(self) -> int: |
215 | | - # return len(self.fetch()) |
216 | | - |
217 | | - def __str__(self) -> str: |
218 | | - return self.__repr__() |
219 | | - |
220 | | - def __repr__(self) -> str: |
221 | | - # Jobs - 123 items |
222 | | - return repr( |
223 | | - f"{self.__class__.__name__} - { len(list(self.fetch())) } items - {self._path}" |
224 | | - ) |
225 | | - |
226 | | - def find(self, uid: str) -> T | None: |
227 | | - """ |
228 | | - Find a record by its unique identifier. |
229 | | -
|
230 | | - Fetches the record from Connect by it's identifier. |
231 | | -
|
232 | | - Parameters |
233 | | - ---------- |
234 | | - uid : str |
235 | | - The unique identifier of the record. |
236 | | -
|
237 | | - Returns |
238 | | - ------- |
239 | | - : |
240 | | - Single instance of T if found, else None |
241 | | - """ |
242 | | - result: Jsonifiable = self._get_api(uid) |
243 | | - result_obj = cast(JsonifiableDict, result) |
244 | | - |
245 | | - return self._to_instance(result_obj) |
246 | | - |
247 | | - def find_by(self, **conditions: Any) -> T | None: |
248 | | - """ |
249 | | - Find the first record matching the specified conditions. |
250 | | -
|
251 | | - There is no implied ordering, so if order matters, you should specify it yourself. |
252 | | -
|
253 | | - Parameters |
254 | | - ---------- |
255 | | - **conditions : Any |
256 | | -
|
257 | | - Returns |
258 | | - ------- |
259 | | - T |
260 | | - The first record matching the conditions, or `None` if no match is found. |
261 | | - """ |
262 | | - results = self.fetch() |
263 | | - |
264 | | - conditions_items = conditions.items() |
265 | | - |
266 | | - # Get the first item of the generator that matches the conditions |
267 | | - # If no item is found, return None |
268 | | - return next( |
269 | | - ( |
270 | | - # Return result |
271 | | - result |
272 | | - # Iterate through `results` generator |
273 | | - for result in results |
274 | | - # If all `conditions`'s key/values are found in `result`'s key/values... |
275 | | - if result.items() >= conditions_items |
276 | | - ), |
277 | | - None, |
278 | | - ) |
0 commit comments