11"""
22This module contains the asynchronous API to interface with Obelisk CORE.
3- These methods all return a :class: `Awaitable`.
3+ These methods all return a `Awaitable`.
44
5- Relevant entrance points are :class: `Client`.
5+ Relevant entrance points are `Client`.
66
77This API vaguely resembles that of clients to previous Obelisk versions,
88but also significantly diverts from it where the underlying Obelisk CORE API does so.
@@ -87,7 +87,7 @@ class ObeliskPosition(BaseModel):
8787
8888class IncomingDatapoint (BaseModel ):
8989 """A datapoint to be submitted to Obelisk. These are validated quite extensively, but not fully.
90- .. automethod:: check_metric_type(self)
90+ We check roughly if the value type corresponds to the declared type if its one of `number`, `number[]`, `bool` or `string`.
9191 """
9292
9393 timestamp : AwareDatetime | None = None
@@ -133,20 +133,29 @@ def serialize_comma_string(input: Any, handler: SerializerFunctionWrapHandler) -
133133
134134
135135class QueryParams (BaseModel ):
136+ """
137+ To avoid having too many parameters on query functions,
138+ and sharing the implementation between query and chunked query,
139+ this model collects the information needed to execute a query.
140+
141+ Contrary to the name, this does not correlate directly to URL query parameters sent to Obelisk.
142+ """
136143 dataset : str
137144 groupBy : Annotated [list [FieldName ] | None , WrapSerializer (serialize_comma_string )] = None
145+ """List of Field Names to aggregate by as defined in Obelisk docs, None selects the server-side defaults."""
138146 aggregator : Aggregator | None = None
139147 fields : Annotated [list [FieldName ] | None , WrapSerializer (serialize_comma_string )] = None
140- orderBy : Annotated [ list [ str ] | None , WrapSerializer ( serialize_comma_string )] = (
141- None # More complex than just FieldName, can be prefixed with - to invert sort
142- )
148+ """List of Field Names as defined in Obelisk docs, None selects the server-side defaults."""
149+ orderBy : Annotated [ list [ str ] | None , WrapSerializer ( serialize_comma_string )] = None
150+ """List of Field Names, with their potential prefixes and suffixes, to select ordering. None user server defaults."""
143151 dataType : DataType | None = None
152+ """Data type expected to be returned, is mandatory if the `value` field is requested in the `fields` parameter"""
144153 filter_ : Annotated [str | Filter | None , Field (serialization_alias = "filter" )] = None
145154 """
146- Obelisk CORE handles filtering in ` RSQL format < https://obelisk.pages.ilabt.imec.be/obelisk-core/query.html#rsql-format>`__ ,
147- to make it easier to also programatically write these filters, we provide the :class:` Filter` option as well.
155+ Obelisk CORE handles filtering in [ RSQL format]( https://obelisk.pages.ilabt.imec.be/obelisk-core/query.html#rsql-format) ,
156+ to make it easier to also programatically write these filters, we provide the `obelisk.types.core. Filter` option as well.
148157
149- Suffix to avoid collisions.
158+ Suffix to avoid collisions with builtin Python filter function .
150159 """
151160 cursor : str | None = None
152161 limit : int = 1000
@@ -161,10 +170,16 @@ def check_datatype_needed(self) -> Self:
161170 return self
162171
163172 def to_dict (self ) -> dict [str , Any ]:
164- return self .model_dump (exclude_none = True , by_alias = True , mode = 'json' )
173+ return self .model_dump (exclude_none = True , by_alias = True , mode = 'json' , exclude = { "dataset" } )
165174
166175
167176class ChunkedParams (BaseModel ):
177+ """
178+ The parameters to be used with `Client.query_time_chunked`,
179+ which allows fetching large spans of data in specified "chunks" specified in time units,
180+ for example processing weeks of data one hour at a time.
181+ This limits memory useage.
182+ """
168183 dataset : str
169184 groupBy : list [FieldName ] | None = None
170185 aggregator : Aggregator | None = None
@@ -178,6 +193,7 @@ class ChunkedParams(BaseModel):
178193 start : datetime
179194 end : datetime
180195 jump : timedelta = timedelta (hours = 1 )
196+ """The size of one chunk. 1 hour is a common default. You will receive however many datapoints are included in this interval."""
181197
182198 model_config = ConfigDict (arbitrary_types_allowed = True )
183199
@@ -189,6 +205,7 @@ def check_datatype_needed(self) -> Self:
189205 return self
190206
191207 def chunks (self ) -> Iterator [QueryParams ]:
208+ """Splits this model into an Iterator of ordinary `QueryParams` objects, to query one timestep at a time."""
192209 current_start = self .start
193210 while current_start < self .end :
194211 current_end = current_start + self .jump
@@ -210,19 +227,36 @@ def chunks(self) -> Iterator[QueryParams]:
210227
211228
212229class QueryResult (BaseModel ):
230+ """The data returned by a single chunk fetch"""
213231 cursor : str | None = None
232+ """Cursors always point to the next page of data matched by filters.
233+ They are none if there is no more data, they do not consider datapoint count limits."""
214234 items : list [Datapoint ]
215235
216236
217237class Client (BaseClient ):
238+ """
239+ This class performs all communication with Obelisk.
240+
241+ The intended methods to be used by consumers are `query` or `query_time_chunked`.
242+ These will respectively return all data matching specified parameters,
243+ or return all data, one timestep at a time respectively.
244+
245+ `send` is considered an implementation detail,
246+ but may be used by consumers for any endpoints not yet implemented by obelisk-py.
247+
248+ `fetch_single_chunk` is the underlying layer to both query methods and requires the user to handle cursors themselves.
249+ It may however still be useful in some circumstances.
250+ """
251+
218252 page_limit : int = 250
219253 """How many datapoints to request per page in a cursored fetch"""
220254
221255 def __init__ (
222256 self ,
223257 client : str ,
224258 secret : str ,
225- retry_strategy : RetryStrategy = NoRetryStrategy (), # noqa: B008 # This is fine to bew shared
259+ retry_strategy : RetryStrategy = NoRetryStrategy (), # noqa: B008 # This is fine to be shared
226260 ) -> None :
227261 BaseClient .__init__ (
228262 self ,
@@ -242,18 +276,18 @@ async def send(
242276
243277 Parameters
244278 ----------
245- dataset : str
279+ - dataset
246280 ID for the dataset to publish to
247- data : List[IncomingDatapoint]
281+ - data
248282 List of Obelisk-acceptable datapoints.
249283 Exact format varies between Classic or HFS,
250284 caller is responsible for formatting.
251285
252286 Raises
253287 ------
254288
255- ObeliskError
256- When the resulting status code is not 204, an :exc:`~ obelisk.exceptions.ObeliskError` is raised.
289+ - ObeliskError
290+ When the resulting status code is not 204, an ` obelisk.exceptions.ObeliskError` is raised.
257291 """
258292
259293 response = await self .http_post (
0 commit comments