syncmodels 0.1.342__py2.py3-none-any.whl → 0.1.343__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
syncmodels/__init__.py CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  __author__ = """Asterio Gonzalez"""
4
4
  __email__ = "asterio.gonzalez@gmail.com"
5
- __version__ = "0.1.342"
5
+ __version__ = "0.1.343"
syncmodels/crawler.py CHANGED
@@ -1578,6 +1578,11 @@ class SortPlugin(iPlugin):
1578
1578
  or self.bot.context.get(SORT_KEY)
1579
1579
  or getattr(self.bot, "SORT_KEY", None)
1580
1580
  )
1581
+ if isinstance(sort_key, str):
1582
+ sort_key = (sort_key,)
1583
+ elif isinstance(sort_key, list):
1584
+ sort_key = tuple(sort_key)
1585
+
1581
1586
  if sort_key:
1582
1587
  context[SORT_KEY] = sort_key
1583
1588
 
@@ -1588,36 +1593,37 @@ class SortPlugin(iPlugin):
1588
1593
  # figure out the sort_key
1589
1594
  sort_key = SortKeyFinder.find_sort_key(stream)
1590
1595
 
1591
- kind = context.get(KIND_KEY) # must exixts
1592
- if not kind:
1593
- log.error("cant find KIND_KEY in context??")
1594
- return
1595
- mapper = self.bot.parent.MAPPERS.get(kind)
1596
- if not mapper:
1597
- log.error("cant find mapper [%s] in crawler??", kind)
1598
- return
1596
+ kind = context.get(KIND_KEY) # must exixts
1597
+ if not kind:
1598
+ log.error("cant find KIND_KEY in context??")
1599
+ return
1599
1600
 
1600
- model = mapper.PYDANTIC
1601
- item_fields = model.model_fields
1602
- # datetime
1603
- # reverse = list(
1604
- # set(
1605
- # [
1606
- # "datetime",
1607
- # ]
1608
- # ).intersection(item_fields)
1609
- # )
1610
- reverse = list(set(sort_key).intersection(item_fields))
1611
- if not reverse:
1612
- log.debug(
1613
- "model [%s] attributes:[%s] doesn't match any datetime alike sort keys: [%s]",
1614
- model,
1615
- list(item_fields),
1616
- sort_key,
1617
- )
1618
- # return
1601
+ mapper = self.bot.parent.MAPPERS.get(kind)
1602
+ if not mapper:
1603
+ log.error("cant find mapper [%s] in crawler??", kind)
1604
+ return
1619
1605
 
1620
- context[REVERSE_SORT_KEY] = reverse
1606
+ model = mapper.PYDANTIC
1607
+ item_fields = model.model_fields
1608
+ # datetime
1609
+ # reverse = list(
1610
+ # set(
1611
+ # [
1612
+ # "datetime",
1613
+ # ]
1614
+ # ).intersection(item_fields)
1615
+ # )
1616
+ reverse = list(set(sort_key).intersection(item_fields))
1617
+ if not reverse:
1618
+ log.debug(
1619
+ "model [%s] attributes:[%s] doesn't match any datetime alike sort keys: [%s]",
1620
+ model,
1621
+ list(item_fields),
1622
+ sort_key,
1623
+ )
1624
+ # return
1625
+
1626
+ context[REVERSE_SORT_KEY] = reverse
1621
1627
 
1622
1628
  if sort_key:
1623
1629
  context[SORT_KEY] = sort_key
@@ -35,6 +35,8 @@ class SortKeyFinder:
35
35
  # )
36
36
  DATE_KEYS = [
37
37
  # ".*date", # keys that does not belongs to Pydantic models
38
+ # "id",
39
+ # "record_id",
38
40
  "time",
39
41
  "year",
40
42
  "ts",
@@ -32,6 +32,7 @@ from syncmodels.definitions import (
32
32
  # MONOTONIC_SINCE,
33
33
  MONOTONIC_SINCE_KEY,
34
34
  MONOTONIC_SINCE_VALUE,
35
+ SORT_KEY,
35
36
  URI,
36
37
  DURI,
37
38
  WAVE_LAST_KEY,
@@ -410,6 +411,11 @@ class iSession(iContext, iSchema, iRegistry): # , iAuthenticator):
410
411
  break
411
412
  break
412
413
 
414
+ if not params.get(MONOTONIC_SINCE_KEY):
415
+ if since_key := params.get(SORT_KEY):
416
+ # if the 1st time that crawler want to retrieve data
417
+ params[MONOTONIC_SINCE_KEY] = since_key
418
+
413
419
  call_kw = {
414
420
  "url": url,
415
421
  "headers": self.headers,
syncmodels/session/sql.py CHANGED
@@ -16,6 +16,7 @@ from syncmodels.definitions import (
16
16
  JSON,
17
17
  LIMIT_KEY_VALUE,
18
18
  )
19
+ from syncmodels.storage import is_sort_key_id
19
20
 
20
21
  from ..crud import DEFAULT_NAMESPACE, parse_duri
21
22
  from ..schema import StructShema
@@ -118,7 +119,11 @@ class iSQLSession(iSession):
118
119
 
119
120
  query = f"SELECT * FROM {table}"
120
121
  if MONOTONIC_SINCE_VALUE in params:
121
- query += f" WHERE {since_key} >= :{MONOTONIC_SINCE_VALUE}"
122
+ if is_sort_key_id(since_key):
123
+ query += f" WHERE {since_key} > :{MONOTONIC_SINCE_VALUE}"
124
+ else:
125
+ query += f" WHERE {since_key} >= :{MONOTONIC_SINCE_VALUE}"
126
+
122
127
  if since_key:
123
128
  query += f" ORDER BY {since_key}"
124
129
  # limit = 128 # TODO: agp: REMOVE
syncmodels/storage.py CHANGED
@@ -137,6 +137,12 @@ UTC_TZ = pytz.timezone("UTC")
137
137
  # REGEXP_FQUI = re.compile(r"((?P<ns>[^/]*?)/)?(?P<table>[^:]+):(?P<uid>.*)$")
138
138
 
139
139
 
140
+ def is_sort_key_id(sort_keys):
141
+ if isinstance(sort_keys, str):
142
+ return re.search(REGEXP_RECORD_ID, sort_keys)
143
+ return any([re.search(REGEXP_RECORD_ID, _) for _ in sort_keys])
144
+
145
+
140
146
  def comparable_struct(data, patterns):
141
147
  wdata = Walk(data)
142
148
 
@@ -150,8 +156,15 @@ def split_fqui(fqid):
150
156
  return fqid, None
151
157
 
152
158
 
159
+ REGEXP_RECORD_ID = r"(\W*|_)id$"
160
+
161
+
153
162
  def normalize_payload(data, keys):
154
163
  for key in set(keys or []).intersection(data):
164
+ # skip record_id and similar keys
165
+ if re.search(REGEXP_RECORD_ID, key):
166
+ continue
167
+
155
168
  value = DATE(data[key])
156
169
  if isinstance(value, datetime):
157
170
  if not value.tzinfo:
@@ -908,27 +921,45 @@ class WaveStorage(iWaves, iStorage):
908
921
  nonlocal uid
909
922
  nonlocal monotonic
910
923
  nonlocal data_sort_blueprint
911
- for monotonic_key in set(sort_keys).intersection(data):
912
- monotonic_value = DATE(data[monotonic_key])
913
-
914
- # seconds
915
- grace_period = kw.get(GRACE_PERIOD_KEY, DEFAULT_GRACE_PERIOD)
916
- grace_period = timedelta(seconds=grace_period)
917
- since_value = monotonic_value - grace_period
918
- # pass to UTC time
919
- if not since_value.tzinfo:
920
- # x = x.replace(tzinfo=timezone.utc)
921
- # x = x.replace(tzinfo=LOCAL_TZ)
922
- since_value = pytz.utc.localize(since_value)
923
- since_value = since_value.astimezone(UTC_TZ)
924
- since_value = since_value.strftime("%Y-%m-%dT%H:%M:%SZ")
925
924
 
926
- break
925
+ # using record_id alike sort_key?
926
+ if is_sort_key_id(sort_keys):
927
+ for monotonic_key in set(sort_keys).intersection(data):
928
+ monotonic_value = data[monotonic_key]
929
+ break
930
+ else:
931
+ log.error("can't find %s key in %s", monotonic_key, data)
932
+ # in this case, no grace_period is needed
933
+ since_value = monotonic_value
934
+ monotonic_operator = ">"
927
935
  else:
928
- monotonic_key = MONOTONIC_KEY # ??
929
- grace_period = kw.get(GRACE_PERIOD_KEY, DEFAULT_GRACE_PERIOD)
930
- grace_period *= 10**9 # nanoseconds
931
- since_value = monotonic - grace_period
936
+ # using datetime alike sort_key
937
+ monotonic_operator = ">="
938
+ for monotonic_key in set(sort_keys).intersection(data):
939
+ monotonic_value = DATE(data[monotonic_key])
940
+
941
+ # seconds
942
+ grace_period = kw.get(
943
+ GRACE_PERIOD_KEY, DEFAULT_GRACE_PERIOD
944
+ )
945
+ grace_period = timedelta(seconds=grace_period)
946
+ since_value = monotonic_value - grace_period
947
+ # pass to UTC time
948
+ if not since_value.tzinfo:
949
+ # x = x.replace(tzinfo=timezone.utc)
950
+ # x = x.replace(tzinfo=LOCAL_TZ)
951
+ since_value = pytz.utc.localize(since_value)
952
+ since_value = since_value.astimezone(UTC_TZ)
953
+ since_value = since_value.strftime("%Y-%m-%dT%H:%M:%SZ")
954
+
955
+ break
956
+ else:
957
+ monotonic_key = MONOTONIC_KEY # ??
958
+ grace_period = kw.get(
959
+ GRACE_PERIOD_KEY, DEFAULT_GRACE_PERIOD
960
+ )
961
+ grace_period *= 10**9 # nanoseconds
962
+ since_value = monotonic - grace_period
932
963
 
933
964
  query = f"{namespace}://{database}/{thing}"
934
965
 
@@ -937,7 +968,7 @@ class WaveStorage(iWaves, iStorage):
937
968
  data_sort_bp = {
938
969
  MONOTONIC_SINCE_KEY: monotonic_key,
939
970
  MONOTONIC_SINCE_VALUE: since_value,
940
- MONOTONIC_SINCE_OPERATOR: ">=",
971
+ MONOTONIC_SINCE_OPERATOR: monotonic_operator,
941
972
  ORDER_KEY: monotonic_key,
942
973
  DIRECTION_KEY: DIRECTION_DESC,
943
974
  # LIMIT_KEY: kw.get(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: syncmodels
3
- Version: 0.1.342
3
+ Version: 0.1.343
4
4
  Summary: Synchronizable Models
5
5
  Home-page: https://github.com/asterio.gonzalez/syncmodels
6
6
  Author: Asterio Gonzalez
@@ -18,7 +18,7 @@ Classifier: Programming Language :: Python :: 3.11
18
18
  Requires-Python: >=3.6
19
19
  License-File: LICENSE
20
20
  License-File: AUTHORS.rst
21
- Requires-Dist: agptools>=0.1.342
21
+ Requires-Dist: agptools>=0.1.343
22
22
  Requires-Dist: aiocache
23
23
  Requires-Dist: aiohttp
24
24
  Requires-Dist: Click
@@ -1,6 +1,6 @@
1
- syncmodels/__init__.py,sha256=KBpZRQtPAp9QZRGYrhYbVtV2U5L5_46b333KNp6y6PU,142
1
+ syncmodels/__init__.py,sha256=Mpde6Eca9MTKd_YLLbuJt4XCAjhQkFJWIMHIgyNtej0,142
2
2
  syncmodels/context.py,sha256=k1Gs_ip9BfyRFpyRnzqYvRDKo0sYBqJsh6z9sWln9oE,451
3
- syncmodels/crawler.py,sha256=ITKxBrcaLrkuQv4w93sMsCRVu7sFKfqrI02TKrAetw4,94497
3
+ syncmodels/crawler.py,sha256=lx0IU586JD0qcdozWiv0y7970CkUEg3SzFB6gOYDS6I,94540
4
4
  syncmodels/crud.py,sha256=oZIcwEKR2i-lesEF_059Y4yThohd9m7gs6R6xYgLH-I,15351
5
5
  syncmodels/definitions.py,sha256=w-3TrSomp9T8OzLmJhKeZQDzrUIJLKldyh1lzlE7Yj0,5476
6
6
  syncmodels/exceptions.py,sha256=ZLAwu19cs2UN2Sv3jaLnixT_jRI7T42TfyutCkUsuIk,685
@@ -11,7 +11,7 @@ syncmodels/registry.py,sha256=YaQtgbSwa0je1MpCcVHALI3_b85vrddyOlhsnrUcKZs,8224
11
11
  syncmodels/requests.py,sha256=wWoC5hPDm1iBM_zrlyKRauzhXgdKR3pT5RqyC-5UZhQ,538
12
12
  syncmodels/runner.py,sha256=IHDKuQ3yJ1DN9wktMiIrerPepYX61tc3AzbFfuUqEFw,5454
13
13
  syncmodels/schema.py,sha256=uinUt8Asq_x7xa6MKWVXNyoWO6gKocjGPppjimaXzEU,2492
14
- syncmodels/storage.py,sha256=9Tn9uohZB4ZrjZlwznDSg-e5duAdauJPqv3Iar2jkmw,74908
14
+ syncmodels/storage.py,sha256=GLEDryiBkgN9SgtvcqBRxP_22T00gGkIbiZqM6AqKDI,76158
15
15
  syncmodels/syncmodels.py,sha256=jcUxVbv1hrx5hI81VCO1onIM6WyORTqJVPwIqlPocOc,10596
16
16
  syncmodels/timequeue.py,sha256=YRd3ULRaIhoszaBsYhfr0epMqAbL6-NwVEtScjUYttM,595
17
17
  syncmodels/wave.py,sha256=Gra22BLiA9z2nF-6diXpjAc4GZv9nebmyvHxdAfXec4,7764
@@ -24,7 +24,7 @@ syncmodels/cli/surreal.py,sha256=eL7pDicLo0_68JhpCZacde6DOVcfHE_UEzczvgDuvAc,106
24
24
  syncmodels/cli/wingdbstub.py,sha256=q4z-RqHN1ttzNtiLYTzqQG2ZYZ6W3NOnEd2E5NGhfao,17165
25
25
  syncmodels/cli/workspace.py,sha256=wajZnxf567nYoQysTEgxrDAp8ZBU8zSuoP4KyZtqvdc,2461
26
26
  syncmodels/helpers/__init__.py,sha256=qZet64gMJNAAqzUdEqCV5WDk5D2Dbw1Kxlt9Jo6x3m4,23
27
- syncmodels/helpers/crawler.py,sha256=2WiDxnjxZKbGa8x71bgeSc2wmabKa_wD-ofQMbgVXLo,4805
27
+ syncmodels/helpers/crawler.py,sha256=ptqj4g96nQfQIvdp18HRDovnWfB0RJXtTBzHQsNPrM8,4844
28
28
  syncmodels/helpers/explorer.py,sha256=-Dol3z1pALCMI9OPSvVbROaTzLjbUpS0suJ82Z6Rmb4,7447
29
29
  syncmodels/helpers/faker.py,sha256=tPtibNh28KoHb9kcwE9WaPdPrSrN6xMbCv5HhNFEVG0,1222
30
30
  syncmodels/helpers/general.py,sha256=UAcSfrvsaT15iJuxsR3WMk51UjpLLGDf14xmpBojndg,6160
@@ -297,16 +297,16 @@ syncmodels/model/schema_org/webpage.py,sha256=-bqKOpEs_2lW7qrey2nHtvOZ9xbmmwcviN
297
297
  syncmodels/model/schema_org/webpageelement.py,sha256=brXfhU3l3FBXpy8qnR1Ve-EckjHW8VGoyR2IsnT7t2Y,1104
298
298
  syncmodels/model/schema_org/website.py,sha256=48Rox27BbFIg1u3wDlOtX-lLCPoFgvvrCw5Hrdf6uRU,912
299
299
  syncmodels/model/schema_org/xpathtype.py,sha256=D8gKiCrGSSuUVYw7BIWmOIUbKATfv2IpbkV1B2TmjC0,484
300
- syncmodels/session/__init__.py,sha256=uy9nMxUUT6VeExOLLzr5Zebe7LvP67WY34WzOs67WB4,15765
300
+ syncmodels/session/__init__.py,sha256=xjgmogPs-Nu5merFY-foJVT9X-qDbLk_fYbe9uGx6sY,16003
301
301
  syncmodels/session/http.py,sha256=tf7z0ccAEYoCOZT4Ukv3NBXz9hUO3vs2s9bm491pCj8,1480
302
302
  syncmodels/session/postgresql.py,sha256=ZMIu1Rv93pKfvFlovFBmWArzlrT2xaQWNYGZT_LW61k,175
303
- syncmodels/session/sql.py,sha256=BL-vaR__6DdDc_vxfTvnvRD9rXXEALKyc-Xg6j4nUpw,6851
303
+ syncmodels/session/sql.py,sha256=auZ_3RZTSWViED4UrExYaes42Y2bTZKixEsfOpa_zaU,7036
304
304
  syncmodels/session/sqlite.py,sha256=nCDjopLiBpX1F10qkKoARM7JrVdIpJ1WdGOduFVxaiA,2080
305
305
  syncmodels/source/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
306
- syncmodels-0.1.342.dist-info/AUTHORS.rst,sha256=3ZPoqg8Aav8DSYKd0fwcwn4_5HwSiMLart0E5Un00-U,168
307
- syncmodels-0.1.342.dist-info/LICENSE,sha256=uzMOYtIiUsnsD0xHJR7aJWJ4v_bvan0kTnvufy5eNoA,1075
308
- syncmodels-0.1.342.dist-info/METADATA,sha256=XZynUjEQ7Ii6K4jQUchBf89Hg3ztVzgxVndZcZgxU3A,2700
309
- syncmodels-0.1.342.dist-info/WHEEL,sha256=SrDKpSbFN1G94qcmBqS9nyHcDMp9cUS9OC06hC0G3G0,109
310
- syncmodels-0.1.342.dist-info/entry_points.txt,sha256=dMnigjZsHMxTwXiiZyBZdBbMYE0-hY3L5cG15EcDAzw,51
311
- syncmodels-0.1.342.dist-info/top_level.txt,sha256=2DfQ9NuAhKMjY3BvQGVBA7GfqTm7EoHNbaehSUiqiHQ,11
312
- syncmodels-0.1.342.dist-info/RECORD,,
306
+ syncmodels-0.1.343.dist-info/AUTHORS.rst,sha256=3ZPoqg8Aav8DSYKd0fwcwn4_5HwSiMLart0E5Un00-U,168
307
+ syncmodels-0.1.343.dist-info/LICENSE,sha256=uzMOYtIiUsnsD0xHJR7aJWJ4v_bvan0kTnvufy5eNoA,1075
308
+ syncmodels-0.1.343.dist-info/METADATA,sha256=sXMUvCabKs5rQ2jAfNc1Vgp6XBoQbcpPCXhRq4rQ9a8,2700
309
+ syncmodels-0.1.343.dist-info/WHEEL,sha256=SrDKpSbFN1G94qcmBqS9nyHcDMp9cUS9OC06hC0G3G0,109
310
+ syncmodels-0.1.343.dist-info/entry_points.txt,sha256=dMnigjZsHMxTwXiiZyBZdBbMYE0-hY3L5cG15EcDAzw,51
311
+ syncmodels-0.1.343.dist-info/top_level.txt,sha256=2DfQ9NuAhKMjY3BvQGVBA7GfqTm7EoHNbaehSUiqiHQ,11
312
+ syncmodels-0.1.343.dist-info/RECORD,,