syncmodels 0.1.342__py2.py3-none-any.whl → 0.1.344__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 +1 -1
- syncmodels/crawler.py +34 -28
- syncmodels/helpers/crawler.py +2 -0
- syncmodels/session/__init__.py +6 -0
- syncmodels/session/sql.py +6 -1
- syncmodels/storage.py +69 -34
- {syncmodels-0.1.342.dist-info → syncmodels-0.1.344.dist-info}/METADATA +2 -2
- {syncmodels-0.1.342.dist-info → syncmodels-0.1.344.dist-info}/RECORD +13 -13
- {syncmodels-0.1.342.dist-info → syncmodels-0.1.344.dist-info}/AUTHORS.rst +0 -0
- {syncmodels-0.1.342.dist-info → syncmodels-0.1.344.dist-info}/LICENSE +0 -0
- {syncmodels-0.1.342.dist-info → syncmodels-0.1.344.dist-info}/WHEEL +0 -0
- {syncmodels-0.1.342.dist-info → syncmodels-0.1.344.dist-info}/entry_points.txt +0 -0
- {syncmodels-0.1.342.dist-info → syncmodels-0.1.344.dist-info}/top_level.txt +0 -0
syncmodels/__init__.py
CHANGED
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
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
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
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
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
|
-
|
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
|
syncmodels/helpers/crawler.py
CHANGED
syncmodels/session/__init__.py
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
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(
|
@@ -994,20 +1025,24 @@ class WaveStorage(iWaves, iStorage):
|
|
994
1025
|
|
995
1026
|
# TODO: try to create only a single query
|
996
1027
|
# TODO: review different structures case
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1028
|
+
if is_sort_key_id(sort_keys):
|
1029
|
+
# using record_id style doesn't require search for similars object
|
1030
|
+
similar = []
|
1031
|
+
else:
|
1032
|
+
similar_bp = {
|
1033
|
+
LIMIT_KEY: kw.get(
|
1034
|
+
LIMIT_KEY, 25 # TODO: agp: set in definition?
|
1035
|
+
), # TODO: this is temporal, ideally None
|
1036
|
+
# ORDER_KEY: MONOTONIC_KEY,
|
1037
|
+
# DIRECTION_KEY: DIRECTION_DESC,
|
1038
|
+
ORG_KEY: uid,
|
1039
|
+
**data_sort_blueprint, # implies sv = True
|
1040
|
+
}
|
1041
|
+
similar = await self.storage.query(
|
1042
|
+
query,
|
1043
|
+
**similar_bp,
|
1044
|
+
**data_sort_bp,
|
1045
|
+
)
|
1011
1046
|
t1 = time.time()
|
1012
1047
|
_elapsed = t1 - t0
|
1013
1048
|
existing = identical + similar
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: syncmodels
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.344
|
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.
|
21
|
+
Requires-Dist: agptools>=0.1.344
|
22
22
|
Requires-Dist: aiocache
|
23
23
|
Requires-Dist: aiohttp
|
24
24
|
Requires-Dist: Click
|
@@ -1,6 +1,6 @@
|
|
1
|
-
syncmodels/__init__.py,sha256=
|
1
|
+
syncmodels/__init__.py,sha256=mTxSSoUW3Z9AossKi_RP_CZnlfe9VaRuqy8d9ByV6tw,142
|
2
2
|
syncmodels/context.py,sha256=k1Gs_ip9BfyRFpyRnzqYvRDKo0sYBqJsh6z9sWln9oE,451
|
3
|
-
syncmodels/crawler.py,sha256=
|
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=
|
14
|
+
syncmodels/storage.py,sha256=x01TmpETMrHvQvliL3TXfUp18RKr6Huz6DmrRZWD1DU,76418
|
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=
|
27
|
+
syncmodels/helpers/crawler.py,sha256=UNa_Sgmq8M1X3oQlVUalo-2fAePWsLlhJx1BViIO3fo,4840
|
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=
|
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=
|
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.
|
307
|
-
syncmodels-0.1.
|
308
|
-
syncmodels-0.1.
|
309
|
-
syncmodels-0.1.
|
310
|
-
syncmodels-0.1.
|
311
|
-
syncmodels-0.1.
|
312
|
-
syncmodels-0.1.
|
306
|
+
syncmodels-0.1.344.dist-info/AUTHORS.rst,sha256=3ZPoqg8Aav8DSYKd0fwcwn4_5HwSiMLart0E5Un00-U,168
|
307
|
+
syncmodels-0.1.344.dist-info/LICENSE,sha256=uzMOYtIiUsnsD0xHJR7aJWJ4v_bvan0kTnvufy5eNoA,1075
|
308
|
+
syncmodels-0.1.344.dist-info/METADATA,sha256=kQhHi-FKgA9wAb00IMrlehiQguZypbwv1drlhJyhIuA,2700
|
309
|
+
syncmodels-0.1.344.dist-info/WHEEL,sha256=SrDKpSbFN1G94qcmBqS9nyHcDMp9cUS9OC06hC0G3G0,109
|
310
|
+
syncmodels-0.1.344.dist-info/entry_points.txt,sha256=dMnigjZsHMxTwXiiZyBZdBbMYE0-hY3L5cG15EcDAzw,51
|
311
|
+
syncmodels-0.1.344.dist-info/top_level.txt,sha256=2DfQ9NuAhKMjY3BvQGVBA7GfqTm7EoHNbaehSUiqiHQ,11
|
312
|
+
syncmodels-0.1.344.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|