@@ -85,53 +85,80 @@ def __init__(self, ctx: Context, path: str, pathinfo: str = "", /, **attributes)
8585
8686
8787class 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
102113 """
103- super ().__init__ ()
104- self ._ctx = ctx
105- self ._path = posixpath .join (path , pathinfo )
106- self ._uid = uid
107- self ._cache : Optional [List [T ]] = None
114+ return self ._cache is not None
115+
116+ def reload (self ) -> Self :
117+ """Reloads the collection from Connect.
108118
109- def _get_or_fetch (self ) -> List [T ]:
119+ Returns
120+ -------
121+ Self
110122 """
111- Fetch and cache the data from the API.
123+ self ._cache = None
124+ return self
125+
126+ def _fetch (self ) -> List [T ]:
127+ """Fetch the collection.
112128
113- This method sends a GET request to the `_endpoint` and parses the response as a list of JSON objects.
114- Each JSON object is used to instantiate an item of type `T` using the class specified by `_cls`.
115- The results are cached after the first request and reused for subsequent access unless reloaded.
129+ Fetches the collection directly from Connect. This operation does not effect the cache state.
116130
117131 Returns
118132 -------
119133 List[T]
120- A list of items of type `T` representing the fetched data.
121134 """
122- if self ._cache is not None :
123- return self ._cache
124-
125135 endpoint = self ._ctx .url + self ._path
126136 response = self ._ctx .session .get (endpoint )
127137 results = response .json ()
138+ return [self ._to_instance (result ) for result in results ]
128139
129- self ._cache = []
130- for result in results :
131- uid = result [self ._uid ]
132- instance = self ._create_instance (self ._path , uid , ** result )
133- self ._cache .append (instance )
140+ def _to_instance (self , result : dict ) -> T :
141+ """Converts a result into an instance of T."""
142+ uid = result [self ._uid ]
143+ return self ._create_instance (self ._path , uid , ** result )
134144
145+ @property
146+ def _data (self ) -> List [T ]:
147+ """Get the collection.
148+
149+ Fetches the collection from Connect and caches the result. Subsequent invocations return the cached results unless the cache is explicitly reset.
150+
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 ()
135162 return self ._cache
136163
137164 @overload
@@ -141,42 +168,16 @@ def __getitem__(self, index: int) -> T: ...
141168 def __getitem__ (self , index : slice ) -> Sequence [T ]: ...
142169
143170 def __getitem__ (self , index ):
144- data = self ._get_or_fetch ()
145- return data [index ]
171+ return self ._data [index ]
146172
147173 def __len__ (self ) -> int :
148- data = self ._get_or_fetch ()
149- return len (data )
174+ return len (self ._data )
150175
151176 def __str__ (self ) -> str :
152- data = self ._get_or_fetch ()
153- return str (data )
177+ return str (self ._data )
154178
155179 def __repr__ (self ) -> str :
156- data = self ._get_or_fetch ()
157- return repr (data )
158-
159- @abstractmethod
160- def _create_instance (self , path : str , pathinfo : str , / , ** kwargs : Any ) -> T :
161- """Create an instance of 'T'.
162-
163- Returns
164- -------
165- T
166- """
167- raise NotImplementedError ()
168-
169- def reload (self ) -> Self :
170- """
171- Clear the cache and reload the data from the API on the next access.
172-
173- Returns
174- -------
175- ActiveSequence
176- The current instance with cleared cache, ready to reload data on next access.
177- """
178- self ._cache = None
179- return self
180+ return repr (self ._data )
180181
181182
182183class ActiveFinderMethods (ActiveSequence [T ], ABC ):
@@ -200,9 +201,7 @@ def find(self, uid) -> T:
200201 -------
201202 T
202203 """
203- if self ._cache :
204- # Check if the record already exists in the cache.
205- # It is assumed that local cache scan is faster than an additional HTTP request.
204+ if self .cached ():
206205 conditions = {self ._uid : uid }
207206 result = self .find_by (** conditions )
208207 if result :
@@ -211,13 +210,7 @@ def find(self, uid) -> T:
211210 endpoint = self ._ctx .url + self ._path + uid
212211 response = self ._ctx .session .get (endpoint )
213212 result = response .json ()
214- result = self ._create_instance (self ._path , uid , ** result )
215-
216- # Invalidate the cache.
217- # It is assumed that the cache is stale since a record exists on the server and not in the cache.
218- self ._cache = None
219-
220- return result
213+ return self ._to_instance (result )
221214
222215 def find_by (self , ** conditions : Any ) -> Optional [T ]:
223216 """
@@ -234,5 +227,4 @@ def find_by(self, **conditions: Any) -> Optional[T]:
234227 Optional[T]
235228 The first record matching the conditions, or `None` if no match is found.
236229 """
237- data = self ._get_or_fetch ()
238- return next ((v for v in data if v .items () >= conditions .items ()), None )
230+ return next ((v for v in self ._data if v .items () >= conditions .items ()), None )
0 commit comments