1
1
from __future__ import annotations
2
2
3
3
import dataclasses
4
+ import itertools
4
5
from datetime import date , datetime
5
6
from functools import cached_property
6
7
from typing import Type , Optional , List , Any , Iterator , Iterable , Set , Dict , Union , Tuple
@@ -145,9 +146,9 @@ def __init__(self):
145
146
self ._chunk_size = None
146
147
self ._slice_start : int = 0
147
148
self ._slice_stop : Optional [int ] = None
148
- self ._result_cache : Optional [CacheIterator [PortalModel ]] = None
149
149
self ._avoid_prefetch_cache = False
150
150
self ._only_prefetched = False
151
+ self ._result_cache : Optional [CacheIterator [PortalModel ]] = None
151
152
152
153
def _set_model (self , model : Model , meta_portal : ModelMetaPortalField ):
153
154
self ._model = model
@@ -160,7 +161,6 @@ def _clone(self):
160
161
qs ._chunk_size = self ._chunk_size
161
162
qs ._slice_start = self ._slice_start
162
163
qs ._slice_stop = self ._slice_stop
163
- qs ._result_cache = self ._result_cache
164
164
qs ._avoid_prefetch_cache = self ._avoid_prefetch_cache
165
165
qs ._only_prefetched = self ._only_prefetched
166
166
@@ -180,14 +180,14 @@ def _fetch_all(self):
180
180
return
181
181
182
182
# Try to use cache if the request is inside the prefetch data slice
183
- if prefetch_data is not None :
183
+ if not self . _avoid_prefetch_cache and prefetch_data is not None :
184
184
prefetch_data_slice_start = prefetch_data .offset - 1
185
185
prefetch_data_slice_stop = prefetch_data_slice_start + prefetch_data .limit
186
186
187
187
search_slice_is_inside_prefetch_slice = self ._slice_stop is not None and (
188
188
self ._slice_start >= prefetch_data_slice_start and self ._slice_stop <= prefetch_data_slice_stop )
189
189
190
- if not self . _avoid_prefetch_cache and search_slice_is_inside_prefetch_slice :
190
+ if search_slice_is_inside_prefetch_slice :
191
191
slice_relative_start = self ._slice_start - prefetch_data_slice_start
192
192
slice_relative_stop = self ._slice_stop - prefetch_data_slice_start
193
193
self ._result_cache = prefetch_data .cache [slice_relative_start :slice_relative_stop ]
@@ -239,24 +239,27 @@ def __getitem__(self, k):
239
239
if k .stop is not None and k .stop <= (k .start or 0 ):
240
240
raise ValueError ("Stop index must be greater than start index." )
241
241
242
- if self ._result_cache is not None :
243
- return self ._result_cache [k ]
244
-
245
242
new_qs = self ._clone ()
246
243
new_qs ._set_new_slice (k .start , k .stop )
247
244
245
+ if self ._result_cache is not None :
246
+ new_qs ._result_cache = CacheIterator (itertools .islice (self ._result_cache .__iter__ (), k .start , k .stop ))
247
+
248
248
# In case step is present, the list() force the execution of the query then use the list step to provide the result
249
249
return list (new_qs )[::k .step ] if k .step else new_qs
250
250
251
251
elif isinstance (k , int ):
252
252
if k < 0 :
253
253
raise ValueError ("Negative indexing is not supported." )
254
254
255
+ if self ._result_cache is not None :
256
+ return self ._result_cache [k ]
257
+
255
258
new_qs = self ._clone ()
256
259
new_qs ._set_new_slice (k , k + 1 )
257
260
new_qs ._fetch_all ()
258
261
259
- return self ._result_cache [0 ]
262
+ return new_qs ._result_cache [0 ]
260
263
261
264
else :
262
265
raise TypeError (
@@ -344,8 +347,6 @@ def _execute_query(self):
344
347
page_iterator = paged_result
345
348
))
346
349
347
- return self ._result_cache
348
-
349
350
def portals_record_from_portal_page_iterator (self ,
350
351
model : Model ,
351
352
portal_fm_name : str ,
@@ -368,7 +369,7 @@ def portals_record_from_portal_page_iterator(self,
368
369
369
370
370
371
class PortalModel (metaclass = PortalMetaclass ):
371
- #Example of Meta
372
+ # Example of Meta
372
373
#
373
374
# class Meta:
374
375
# base_schema: FileMakerSchema = None
@@ -651,11 +652,10 @@ def _clone(self):
651
652
qs ._sort = self ._sort [:]
652
653
qs ._scripts = self ._scripts .copy ()
653
654
qs ._chunk_size = self ._chunk_size
654
- qs ._portals = self ._portals
655
+ qs ._portals = self ._portals . copy ()
655
656
qs ._slice_start = self ._slice_start
656
657
qs ._slice_stop = self ._slice_stop
657
658
qs ._response_layout = self ._response_layout
658
- qs ._result_cache = self ._result_cache
659
659
660
660
return qs
661
661
@@ -831,24 +831,27 @@ def __getitem__(self, k):
831
831
if k .stop is not None and k .stop <= (k .start or 0 ):
832
832
raise ValueError ("Stop index must be greater than start index." )
833
833
834
- if self ._result_cache is not None :
835
- return self ._result_cache [k ]
836
-
837
834
new_qs = self ._clone ()
838
835
new_qs ._set_new_slice (k .start , k .stop )
839
836
837
+ if self ._result_cache is not None :
838
+ new_qs ._result_cache = CacheIterator (itertools .islice (self ._result_cache .__iter__ (), k .start , k .stop ))
839
+
840
840
# In case step is present, the list() force the execution of the query then use the list step to provide the result
841
841
return list (new_qs )[::k .step ] if k .step else new_qs
842
842
843
843
elif isinstance (k , int ):
844
844
if k < 0 :
845
845
raise ValueError ("Negative indexing is not supported." )
846
846
847
+ if self ._result_cache is not None :
848
+ return self ._result_cache [k ]
849
+
847
850
new_qs = self ._clone ()
848
851
new_qs ._set_new_slice (k , k + 1 )
849
852
new_qs ._fetch_all ()
850
853
851
- return self ._result_cache [0 ]
854
+ return new_qs ._result_cache [0 ]
852
855
853
856
else :
854
857
raise TypeError (
@@ -944,7 +947,6 @@ def _execute_query(self):
944
947
self ._result_cache = CacheIterator (
945
948
self .records_iterator_from_page_iterator (page_iterator = paged_result .pages .__iter__ (),
946
949
portals_input = self ._portals ))
947
- return self ._result_cache
948
950
949
951
def records_iterator_from_page_iterator (self ,
950
952
page_iterator : PageIterator ,
@@ -1150,7 +1152,8 @@ def __new__(mcls, name, bases, attrs):
1150
1152
client : FMClient = get_meta_attribute (cls = cls , attrs_meta = attrs_meta , attribute_name = "client" )
1151
1153
layout : str = get_meta_attribute (cls = cls , attrs_meta = attrs_meta , attribute_name = "layout" )
1152
1154
1153
- base_manager : Type [ModelManager ] = get_meta_attribute (cls = cls , attrs_meta = attrs_meta , attribute_name = "base_manager" ) or ModelManager
1155
+ base_manager : Type [ModelManager ] = get_meta_attribute (cls = cls , attrs_meta = attrs_meta ,
1156
+ attribute_name = "base_manager" ) or ModelManager
1154
1157
1155
1158
cls ._meta = ModelMeta (
1156
1159
client = client ,
@@ -1183,7 +1186,7 @@ class Model(metaclass=ModelMetaclass):
1183
1186
# base_schema: FileMakerSchema = None
1184
1187
# schema_config: dict = None
1185
1188
1186
- #TODO not used. Only for type hint
1189
+ # TODO not used. Only for type hint
1187
1190
objects : ModelManager = ModelManager ()
1188
1191
1189
1192
def __init__ (self , ** kwargs ):
0 commit comments