1+ import posixpath
12import warnings
23from abc import ABC , abstractmethod
34from dataclasses import dataclass
@@ -50,7 +51,7 @@ def __init__(self, params: ResourceParameters) -> None:
5051
5152
5253class Active (ABC , Resource ):
53- def __init__ (self , ctx : Context , parent : Optional [ "Active" ] = None , ** kwargs ):
54+ def __init__ (self , ctx : Context , ** kwargs ):
5455 """A base class representing an active resource.
5556
5657 Extends the `Resource` class and provides additional functionality for via the session context and an optional parent resource.
@@ -59,55 +60,54 @@ def __init__(self, ctx: Context, parent: Optional["Active"] = None, **kwargs):
5960 ----------
6061 ctx : Context
6162 The context object containing the session and URL for API interactions.
62- parent : Optional[Active], optional
63- An optional parent resource that establishes a hierarchical relationship, by default None.
6463 **kwargs : dict
6564 Additional keyword arguments passed to the parent `Resource` class.
6665 """
6766 params = ResourceParameters (ctx .session , ctx .url )
6867 super ().__init__ (params , ** kwargs )
6968 self ._ctx = ctx
70- self ._parent = parent
7169
7270
7371T = TypeVar ("T" , bound = "Active" )
7472"""A type variable that is bound to the `Active` class"""
7573
7674
7775class ActiveSequence (ABC , Generic [T ], Sequence [T ]):
78- def __init__ (self , ctx : Context , parent : Optional [ Active ] = None ):
76+ def __init__ (self , ctx : Context , base : str , name : str , uid = "guid" ):
7977 """A sequence abstraction for any HTTP GET endpoint that returns a collection.
8078
8179 It lazily fetches data on demand, caches the results, and allows for standard sequence operations like indexing and slicing.
8280
8381 Parameters
8482 ----------
8583 ctx : Context
86- The context object that holds the HTTP session used for sending the GET request.
87- parent : Optional[Active], optional
88- An optional parent resource to establish a nested relationship, by default None.
84+ The context object containing the session and URL for API interactions
85+ base : str
86+ The base HTTP path for the collection endpoint
87+ name : str
88+ The collection name
89+ uid : str, optional
90+ The field name used to uniquely identify records, by default "guid"
91+
92+ Attributes
93+ ----------
94+ _ctx : Context
95+ The context object containing the session and URL for API interactions
96+ _path : str
97+ The HTTP path for the collection endpoint.
98+ _endpoint : Url
99+ The HTTP URL for the collection endpoint.
100+ _uid : str
101+ The default field name used to uniquely identify records.
102+ _cache: Optional[List[T]]
89103 """
90104 super ().__init__ ()
91105 self ._ctx = ctx
92- self ._parent = parent
106+ self ._path : str = posixpath .join (base , name )
107+ self ._endpoint : Url = ctx .url + self ._path
108+ self ._uid : str = uid
93109 self ._cache : Optional [List [T ]] = None
94110
95- @property
96- @abstractmethod
97- def _endpoint (self ) -> str :
98- """
99- Abstract property to define the endpoint URL for the GET request.
100-
101- Subclasses must implement this property to return the API endpoint URL that will
102- be queried to fetch the data.
103-
104- Returns
105- -------
106- str
107- The API endpoint URL.
108- """
109- raise NotImplementedError ()
110-
111111 @property
112112 def _data (self ) -> List [T ]:
113113 """
@@ -127,7 +127,13 @@ def _data(self) -> List[T]:
127127
128128 response = self ._ctx .session .get (self ._endpoint )
129129 results = response .json ()
130- self ._cache = [self ._create_instance (** result ) for result in results ]
130+
131+ self ._cache = []
132+ for result in results :
133+ uid = result [self ._uid ]
134+ instance = self ._create_instance (self ._path , uid , ** result )
135+ self ._cache .append (instance )
136+
131137 return self ._cache
132138
133139 @overload
@@ -149,7 +155,7 @@ def __repr__(self) -> str:
149155 return repr (self ._data )
150156
151157 @abstractmethod
152- def _create_instance (self , ** kwargs ) -> T :
158+ def _create_instance (self , base : str , uid : str , / , ** kwargs : Any ) -> T :
153159 """Create an instance of 'T'.
154160
155161 Returns
@@ -171,29 +177,12 @@ def reload(self) -> Self:
171177 return self
172178
173179
174- class ActiveFinderMethods (ActiveSequence [T ], ABC , Generic [T ]):
175- def __init__ (self , ctx : Context , parent : Optional [Active ] = None , uid : str = "guid" ):
176- """Finder methods.
177-
178- Provides various finder methods for locating records in any endpoint supporting HTTP GET requests.
179-
180- Parameters
181- ----------
182- ctx : Context
183- The context containing the HTTP session used to interact with the API.
184- parent : Optional[Active], optional
185- Optional parent resource for maintaining hierarchical relationships, by default None
186- uid : str, optional
187- The default field name used to uniquely identify records, by default "guid"
188- """
189- super ().__init__ (ctx , parent )
190- self ._uid = uid
191-
180+ class ActiveFinderMethods (ActiveSequence [T ], ABC ):
192181 def find (self , uid ) -> T :
193182 """
194183 Find a record by its unique identifier.
195184
196- Fetches a record either by searching the cache or by making a GET request to the endpoint .
185+ If the cache is already populated, it is checked first for matching record. If not, a conventional GET request is made to the Connect server .
197186
198187 Parameters
199188 ----------
@@ -203,24 +192,23 @@ def find(self, uid) -> T:
203192 Returns
204193 -------
205194 T
206-
207- Raises
208- ------
209- ValueError
210- If no record is found.
211195 """
212- # todo - add some more comments about this
213196 if self ._cache :
197+ # Check if the record already exists in the cache.
198+ # It is assumed that local cache scan is faster than an additional HTTP request.
214199 conditions = {self ._uid : uid }
215200 result = self .find_by (** conditions )
216- else :
217- endpoint = self ._endpoint + uid
218- response = self ._ctx .session .get (endpoint )
219- result = response .json ()
220- result = self ._create_instance (** result )
221-
222- if not result :
223- raise ValueError (f"Failed to find instance where { self ._uid } is '{ uid } '" )
201+ if result :
202+ return result
203+
204+ endpoint = self ._endpoint + uid
205+ response = self ._ctx .session .get (endpoint )
206+ result = response .json ()
207+ result = self ._create_instance (self ._path , uid , ** result )
208+
209+ # Invalidate the cache.
210+ # It is assumed that the cache is stale since a record exists on the server and not in the cache.
211+ self ._cache = None
224212
225213 return result
226214
0 commit comments