syncmodels 0.1.312__py2.py3-none-any.whl → 0.1.314__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.312"
5
+ __version__ = "0.1.314"
syncmodels/crawler.py CHANGED
@@ -152,7 +152,7 @@ from syncmodels.http import (
152
152
  # from syncmodels.registry import iRegistry
153
153
  from syncmodels.auth import iAuthenticator
154
154
  from syncmodels.storage import WaveStorage, Storage
155
- from syncmodels.exceptions import NonRecoverable, NonRecoverableAuth, BadData
155
+ from syncmodels.exceptions import BadLogic, NonRecoverable, NonRecoverableAuth, BadData
156
156
  from syncmodels.syncmodels import SyncModel, COPY
157
157
  from .crud import parse_duri, DEFAULT_DATABASE, DEFAULT_NAMESPACE
158
158
 
@@ -217,7 +217,7 @@ class iAgent(iRunner):
217
217
  include=None,
218
218
  exclude=None,
219
219
  credentials=None,
220
- prefix=None,
220
+ prefix="",
221
221
  *args,
222
222
  **kw,
223
223
  ):
@@ -235,9 +235,8 @@ class iAgent(iRunner):
235
235
  }
236
236
 
237
237
  # prefix template
238
- if prefix:
239
- self.prefix_template = self._compile_template(prefix)
240
- self.prefix = prefix
238
+ self.prefix_template = self._compile_template(prefix)
239
+ self.prefix = prefix
241
240
 
242
241
  # config file
243
242
  if not config_path:
@@ -268,6 +267,11 @@ class iAgent(iRunner):
268
267
 
269
268
  return template
270
269
 
270
+ async def start(self):
271
+ "start runner"
272
+ await super().start()
273
+ await self._bootstrap()
274
+
271
275
  async def _bootstrap(self):
272
276
  "Add the initial tasks to be executed by agent"
273
277
  log.debug(">> [%s] entering bootstrap()", self.name)
@@ -403,7 +407,7 @@ class iAgent(iRunner):
403
407
  log.debug("+ Task: [%s]: [%s] %s", i, self.name, task)
404
408
 
405
409
  # TODO: agp: generalize and provide a better way to save activity records
406
- if activity_logger := getattr(self, "activity_logger"):
410
+ if activity_logger := getattr(self, "activity_logger", None):
407
411
  if activity := task.get(ACTIVITY_LOG_KEY):
408
412
  activity.status = "pending"
409
413
  await activity_logger.update_activity(activity)
@@ -766,6 +770,10 @@ class iBot(iAgent):
766
770
  # abort responsability chain
767
771
  log.error("Inexpected responsability chain abortion")
768
772
  break
773
+ except (BadLogic,) as why:
774
+ # separate to have more fine grain control
775
+ await self.handle_non_recoverable(why, context)
776
+
769
777
  except Exception as why:
770
778
  log.error(why)
771
779
  log.error("".join(traceback.format_exception(*sys.exc_info())))
@@ -1067,7 +1075,7 @@ class iBot(iAgent):
1067
1075
  result = await extract_result(response)
1068
1076
  # result = await response.text()
1069
1077
  log.error(
1070
- "[%s] server sent: %s",
1078
+ "Forbidden [%s] server sent: %s",
1071
1079
  response.status,
1072
1080
  result,
1073
1081
  )
@@ -1635,6 +1643,21 @@ class SortPlugin(iPlugin):
1635
1643
  kind = context.get(KIND_KEY)
1636
1644
  SortKeyFinder.register(kind, sort_key)
1637
1645
 
1646
+ mapper = self.bot.parent.MAPPERS.get(kind)
1647
+ if not mapper:
1648
+ log.error("cant find mapper [%s] in crawler??", kind)
1649
+ return
1650
+
1651
+ # TODO: unify this code (exists sort_key or not exists)
1652
+ model = mapper.PYDANTIC
1653
+ item_fields = model.model_fields
1654
+ reverse = list(set(sort_key).intersection(item_fields))
1655
+ if not reverse:
1656
+ log.error("model [%s] has not datetime alike key??", model)
1657
+ return
1658
+
1659
+ context[REVERSE_SORT_KEY] = reverse
1660
+
1638
1661
  def order(data, accessor):
1639
1662
  result = data
1640
1663
  for key in accessor:
@@ -1642,7 +1665,6 @@ class SortPlugin(iPlugin):
1642
1665
  result = result[key]
1643
1666
  except Exception as why:
1644
1667
  pass
1645
-
1646
1668
  return result
1647
1669
 
1648
1670
  stream.sort(key=partial(order, accessor=sort_key))
@@ -2521,11 +2543,6 @@ class iAsyncCrawler(iCrawler):
2521
2543
  # TODO: REVIEW: always is a single value (len==1), why not return waves[0]
2522
2544
  return waves
2523
2545
 
2524
- async def start(self):
2525
- "start runner"
2526
- await super().start()
2527
- await self._bootstrap()
2528
-
2529
2546
  async def idle(self):
2530
2547
  "default implementation when loop has nothing to do"
2531
2548
  # check running bots
syncmodels/definitions.py CHANGED
@@ -100,6 +100,8 @@ GEOMETRY_COMP_KEY = "geometry__"
100
100
  GEOJSON_KEY = "geojson"
101
101
  GEOLINK_KEY = "geolink"
102
102
 
103
+ COMPARISON_PATTERNS = "compare__"
104
+
103
105
  GEOSPECS_KEYS = [GEOMETRY_KEY, GEOMETRY_SHAPE_KEY, GEOJSON_KEY]
104
106
 
105
107
  UBICATION_KEY = "ubication"
syncmodels/exceptions.py CHANGED
@@ -23,5 +23,9 @@ class NonRecoverableAuth(NonRecoverable):
23
23
  """
24
24
 
25
25
 
26
+ class BadLogic(NonRecoverable):
27
+ """Bad Logic File"""
28
+
29
+
26
30
  class BadData(SyncModelException):
27
31
  """Data is not properly formatted."""
@@ -117,7 +117,7 @@ class OrionInjector:
117
117
  "put",
118
118
  self.target_url
119
119
  # + "/v2/entities/{id}/attrs?options=append,keyValues",
120
- + "/v2/entities/{id}/attrs",
120
+ + "/v2/entities/{id}/attrs?type={type}",
121
121
  self.FULL_EXCLUDE,
122
122
  ],
123
123
  ),
@@ -137,6 +137,7 @@ class OrionInjector:
137
137
  self.target_url
138
138
  # + "/v2/entities/{id}/attrs?options=append,keyValues",
139
139
  + "/v2/entities/{id}",
140
+ # + "/v2/entities/{id}?type={type}", # TODO: avoid posibly 409 if id is used in other fs_pathservice
140
141
  # self.EXCLUDE_ALL,
141
142
  self.FULL_EXCLUDE,
142
143
  ],
@@ -45,7 +45,7 @@ from syncmodels.crud import parse_duri
45
45
  from ..definitions import TASK_KEY, KIND_KEY, ORG_URL, DURI, ID_KEY, VOL_DATA
46
46
  from ..session import iSession
47
47
  from ..crawler import iBot
48
- from ..crawler import MetaExtractPlugin, PutPlugin, SetURIPlugin
48
+ from ..crawler import MetaExtractPlugin, PutPlugin, SetURIPlugin, SortPlugin
49
49
 
50
50
  from .swarm import SwarmBot, SwarmCrawler, SWARM_REGISTER, SWARM_TASKS
51
51
  from .analyzer import XPathAnalyzer
@@ -717,13 +717,15 @@ class BrowserLogicBot(SwarmBot):
717
717
  )
718
718
 
719
719
  def _add_plugins(self):
720
- super()._add_plugins()
720
+ # super()._add_plugins()
721
+ # self.plugins.clear()
721
722
 
722
- self.plugins.clear()
723
723
  # self.add_plugin(HashStreamPlugin())
724
724
  self.add_plugin(MetaExtractPlugin(geojson=False))
725
725
  self.add_plugin(PutPlugin())
726
726
  self.add_plugin(SetURIPlugin())
727
+ # self.add_plugin(SortPlugin())
728
+
727
729
  # self.add_plugin(RenameKeys())
728
730
  # self.add_plugin(UnwrapResponse())
729
731
  # self.add_plugin(RegExtractor())
@@ -7,4 +7,5 @@ from .model import (
7
7
  IntEnum,
8
8
  Field,
9
9
  field_validator,
10
+ model_validator,
10
11
  )
syncmodels/model/model.py CHANGED
@@ -23,7 +23,7 @@ from typing_extensions import Annotated
23
23
  from pydantic import BaseModel as _BaseModel
24
24
  from pydantic import Field
25
25
  from pydantic import PlainSerializer, BeforeValidator
26
- from pydantic.functional_validators import field_validator
26
+ from pydantic.functional_validators import field_validator, model_validator
27
27
 
28
28
  # from pydantic.dataclasses import dataclass
29
29
 
syncmodels/runner.py CHANGED
@@ -62,7 +62,9 @@ class iRunner:
62
62
  self.t0 = 0
63
63
  self.t1 = 0
64
64
  self.nice = 600
65
+ self.clock = 0
65
66
 
67
+ self.hooks = []
66
68
  self.stop_when_empty = stop_when_empty
67
69
 
68
70
  self._wip = []
@@ -160,6 +162,9 @@ class iRunner:
160
162
  if not func:
161
163
  func = getattr(self, task[FUNC_KEY]) # let fail with AttributeError
162
164
  await func(**task)
165
+ self.clock += 1
166
+ for hook in self.hooks:
167
+ await hook(**task)
163
168
 
164
169
  async def idle(self):
165
170
  "default implementation when loop has nothing to do"
syncmodels/storage.py CHANGED
@@ -9,7 +9,7 @@ import time
9
9
  import sys
10
10
  import traceback
11
11
  from typing import List
12
- from datetime import timedelta
12
+ from datetime import timedelta, datetime
13
13
  import pytz
14
14
  from multiprocessing import Process
15
15
  import random
@@ -26,7 +26,13 @@ from surrealist import Surreal as Surrealist
26
26
 
27
27
  from agptools.logs import logger
28
28
  from agptools.helpers import parse_uri, build_uri, DATE, tf
29
- from agptools.containers import merge as merge_dict, build_dict, json_compatible
29
+ from agptools.containers import (
30
+ merge as merge_dict,
31
+ build_dict,
32
+ json_compatible,
33
+ Walk,
34
+ CWalk,
35
+ )
30
36
 
31
37
  from syncmodels.definitions import (
32
38
  REVERSE_SORT_KEY,
@@ -40,6 +46,13 @@ from syncmodels.http import (
40
46
  # USER_AGENT,
41
47
  APPLICATION_JSON,
42
48
  )
49
+ from syncmodels.exceptions import (
50
+ SyncModelException,
51
+ BadLogic,
52
+ NonRecoverable,
53
+ NonRecoverableAuth,
54
+ BadData,
55
+ )
43
56
 
44
57
  from .helpers.importers import JSONVerter
45
58
 
@@ -72,6 +85,7 @@ from .definitions import (
72
85
  SORT_KEY,
73
86
  LIMIT_KEY,
74
87
  WAVE_LAST_KEY,
88
+ COMPARISON_PATTERNS,
75
89
  )
76
90
  from .crud import (
77
91
  DEFAULT_DATABASE,
@@ -120,6 +134,12 @@ UTC_TZ = pytz.timezone("UTC")
120
134
 
121
135
 
122
136
  # REGEXP_FQUI = re.compile(r"((?P<ns>[^/]*?)/)?(?P<table>[^:]+):(?P<uid>.*)$")
137
+
138
+
139
+ def comparable_struct(data, patterns):
140
+ wdata = Walk(data)
141
+
142
+
123
143
  def split_fqui(fqid):
124
144
  "try to split FQUID into table and uid"
125
145
  try:
@@ -129,6 +149,20 @@ def split_fqui(fqid):
129
149
  return fqid, None
130
150
 
131
151
 
152
+ def normalize_payload(data, keys):
153
+ for key in set(keys or []).intersection(data):
154
+ value = DATE(data[key])
155
+ if isinstance(value, datetime):
156
+ if not value.tzinfo:
157
+ value = pytz.utc.localize(value)
158
+ value = value.astimezone(UTC_TZ)
159
+ value = value.strftime("%Y-%m-%dT%H:%M:%SZ")
160
+
161
+ data[key] = value
162
+
163
+ return data
164
+
165
+
132
166
  # ---------------------------------------------------------
133
167
  # Data Store / Ignore Policies
134
168
  # ---------------------------------------------------------
@@ -763,7 +797,7 @@ class WaveStorage(iWaves, iStorage):
763
797
 
764
798
  2. if the object has been inserted in `tube` then:
765
799
  - create / update Snapshot
766
- - cteate / update Wave info with original the original query data
800
+ - create / update Wave info with original the original query data
767
801
 
768
802
 
769
803
  e: exists
@@ -804,8 +838,8 @@ class WaveStorage(iWaves, iStorage):
804
838
  if model := kw.get(MODEL_KEY):
805
839
  self.register_metadata(uri, {"model": model})
806
840
 
807
- sort_keys = kw.get(SORT_KEY, [])
808
- reverse_sort_keys = kw.get(REVERSE_SORT_KEY, [])
841
+ sort_keys = kw.get(SORT_KEY) or []
842
+ reverse_sort_keys = kw.get(REVERSE_SORT_KEY) or []
809
843
  sort_kw_presence = all([kw.get(_) for _ in sort_keys])
810
844
  sort_data_presence = all([data.get(_) for _ in reverse_sort_keys])
811
845
 
@@ -830,7 +864,7 @@ class WaveStorage(iWaves, iStorage):
830
864
  # stream = [kw]
831
865
  if not (sort_keys := SortKeyFinder.find_sort_key(stream=stream)):
832
866
  kind = kw.get(KIND_KEY)
833
- sort_keys = kw[SORT_KEY] = SortKeyFinder.get(kind)
867
+ sort_keys = kw[SORT_KEY] = SortKeyFinder.get(kind) or []
834
868
 
835
869
  kw[SORT_KEY] = sort_keys
836
870
  log.debug("[%s] found: %s as sort_keys", uri, sort_keys)
@@ -853,8 +887,11 @@ class WaveStorage(iWaves, iStorage):
853
887
  # now
854
888
  # ['2005-06-01T00:00:00.000+02:00']
855
889
  # [datetime.datetime(2005, 6, 1, 0, 0, tzinfo=tzoffset(None, 7200))]
890
+
891
+ normalize_payload(data, sort_keys)
892
+
856
893
  monotonic = data.setdefault(MONOTONIC_KEY, monotonic_wave())
857
- for monotonic_key in set(sort_keys or []).intersection(data):
894
+ for monotonic_key in set(sort_keys).intersection(data):
858
895
  monotonic_value = DATE(data[monotonic_key])
859
896
 
860
897
  # seconds
@@ -868,7 +905,6 @@ class WaveStorage(iWaves, iStorage):
868
905
  since_value = pytz.utc.localize(since_value)
869
906
  since_value = since_value.astimezone(UTC_TZ)
870
907
  since_value = since_value.strftime("%Y-%m-%dT%H:%M:%SZ")
871
-
872
908
  break
873
909
  else:
874
910
  monotonic_key = MONOTONIC_KEY # ??
@@ -878,8 +914,8 @@ class WaveStorage(iWaves, iStorage):
878
914
 
879
915
  query = f"{namespace}://{database}/{thing}"
880
916
 
881
- # data_sort_blueprint = build_dict(data, sort_keys)
882
- data_sort_blueprint = build_dict(data, reverse_sort_keys)
917
+ data_sort_blueprint = build_dict(data, sort_keys)
918
+ # data_sort_blueprint = build_comparisson_dict(data, reverse_sort_keys)
883
919
  blueprint = {
884
920
  MONOTONIC_SINCE_KEY: monotonic_key,
885
921
  MONOTONIC_SINCE_VALUE: since_value,
@@ -890,7 +926,7 @@ class WaveStorage(iWaves, iStorage):
890
926
  LIMIT_KEY, 50 # TODO: agp: set in definition?
891
927
  ), # TODO: this is temporal, ideally None
892
928
  ORG_KEY: uid,
893
- **data_sort_blueprint, # implies sv = True
929
+ # **data_sort_blueprint, # implies sv = True
894
930
  }
895
931
  # TODO: LIMIT 1 ?
896
932
 
@@ -904,8 +940,6 @@ class WaveStorage(iWaves, iStorage):
904
940
  sort_keys,
905
941
  MASK,
906
942
  )
907
- # existing = await self.storage.query(query, **blueprint)
908
- # N = len(existing)
909
943
 
910
944
  # TODO: agp: cache and get behaviour from database?
911
945
  if not (behavior := self.behavior_uri.get(query)):
@@ -922,64 +956,93 @@ class WaveStorage(iWaves, iStorage):
922
956
  self.behavior_uri[query] = behavior
923
957
 
924
958
  t0 = time.time()
925
- existing2 = await self.storage.query(
959
+ # search the same data
960
+ # TODO: update blueprint
961
+ blueprint = {
962
+ # MONOTONIC_SINCE_KEY: monotonic_key,
963
+ # MONOTONIC_SINCE_VALUE: since_value,
964
+ # MONOTONIC_SINCE_OPERATOR: ">=",
965
+ # ORDER_KEY: monotonic_key,
966
+ # DIRECTION_KEY: DIRECTION_DESC,
967
+ LIMIT_KEY: kw.get(
968
+ LIMIT_KEY, 50 # TODO: agp: set in definition?
969
+ ), # TODO: this is temporal, ideally None
970
+ ORG_KEY: uid,
971
+ **data_sort_blueprint, # implies sv = True
972
+ }
973
+ identical = await self.storage.query(
974
+ query,
975
+ **blueprint,
976
+ # **data_sort_bp,
977
+ )
978
+ # TODO: try to create only a single query
979
+ # TODO: review different structures case
980
+ similar = await self.storage.query(
926
981
  query,
927
982
  **blueprint,
928
983
  # **data_sort_bp,
929
984
  )
930
985
  t1 = time.time()
931
986
  _elapsed = t1 - t0
932
- N2 = len(existing2)
933
- if data_sort_blueprint and N2 > 1:
987
+ existing = identical + similar
988
+ N = len(existing)
989
+ log.debug(
990
+ "[%s] found [%s] similar records in %s secs",
991
+ blueprint,
992
+ N,
993
+ _elapsed,
994
+ )
995
+ if data_sort_blueprint and N > 1:
934
996
  if behavior & ALLOW_DUPLICATED_ITEMS:
935
997
  log.debug(
936
998
  "tube [%s] has multiples records: [%s] records, but ALLOW_SAME_DATE_DIFFERENT_VALUES is defined",
937
999
  uid,
938
- N2,
1000
+ N,
939
1001
  )
940
- existing2.clear()
1002
+ existing.clear()
941
1003
  else:
942
1004
  log.debug(
943
1005
  "tube has multiples records: [%s] = %s records, must just 1 and sort_key is defined by: [%s]",
944
1006
  uid,
945
- N2,
1007
+ N,
946
1008
  data_sort_blueprint,
947
1009
  )
948
1010
 
949
1011
  push = True
950
- for exists in existing2:
1012
+ patterns = kw.get(COMPARISON_PATTERNS)
1013
+ if patterns:
1014
+ wdata = CWalk(data, include=patterns, exclude=MASK)
1015
+ if not wdata:
1016
+ log.warning("patterns don't get any data")
1017
+ raise BadLogic(data)
1018
+ else:
1019
+ patterns = [r".*"]
1020
+ wdata = CWalk(data, include=patterns, exclude=MASK)
1021
+ for exists in existing:
1022
+ wexists = CWalk(exists, include=patterns, exclude=MASK)
951
1023
  existing_sort_blueprint = build_dict(exists, reverse_sort_keys)
952
-
953
- # check if stream provide an old-echo item
954
- # sort_keys must exists in both data
955
- old_echo = [
956
- old_echo.append(data[_] < exists[_]) if _ in exists else False
957
- ]
958
- if any(old_echo):
959
- log.warning(
960
- "provider give old data again, preserving storage value and ignore this old_echo"
961
- )
962
- push = False
963
- break
1024
+ # existing_sort_blueprint = build_comparisson_dict(exists, reverse_sort_keys)
964
1025
 
965
1026
  same_sort_key = existing_sort_blueprint == data_sort_blueprint
966
1027
 
967
1028
  # check if we must "duplicate" data inside tube
968
- keys0 = set(exists).difference(MASK)
969
- keys1 = set(data).difference(MASK)
1029
+ # keys0 = set(exists).difference(MASK)
1030
+ # keys1 = set(data).difference(MASK)
1031
+ keys0 = set(wexists)
1032
+ keys1 = set(wdata)
970
1033
  same_structure = keys0 == keys1
971
1034
 
972
1035
  same_values = False
973
1036
  if same_sort_key and same_structure:
974
1037
  for key in keys0:
975
- if exists[key] != data[key]:
1038
+ if wexists[key] != wdata[key]:
976
1039
  log.debug(
977
1040
  "[%s].[%s].[%s]: %s != %s",
978
1041
  uid,
979
1042
  data_sort_blueprint,
980
1043
  key,
981
- exists[key],
982
- data[key],
1044
+ wexists[key],
1045
+ wdata[key],
983
1046
  )
984
1047
  break
985
1048
  else:
@@ -1206,6 +1269,8 @@ class WaveStorage(iWaves, iStorage):
1206
1269
  return all([res0, res1, res2])
1207
1270
  else:
1208
1271
  return True
1272
+ except SyncModelException as why:
1273
+ raise why
1209
1274
  except Exception as why: # pragma: nocover
1210
1275
  log.error(why)
1211
1276
  log.error("".join(traceback.format_exception(*sys.exc_info())))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: syncmodels
3
- Version: 0.1.312
3
+ Version: 0.1.314
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.312
21
+ Requires-Dist: agptools>=0.1.314
22
22
  Requires-Dist: aiocache
23
23
  Requires-Dist: aiohttp
24
24
  Requires-Dist: Click
@@ -1,17 +1,17 @@
1
- syncmodels/__init__.py,sha256=ZH2kRAl4tVru0sACzSbL7-N33RPSBU6YP06lTOu_Bzk,142
1
+ syncmodels/__init__.py,sha256=G_3tlPvmtf1CQaauaKV6PoulB_iHJ43bVbH_1q_p8aI,142
2
2
  syncmodels/context.py,sha256=k1Gs_ip9BfyRFpyRnzqYvRDKo0sYBqJsh6z9sWln9oE,451
3
- syncmodels/crawler.py,sha256=cyGX1ZiVWaEWdQAUjDhjH9Qb8VAeV-yB4rFA1weAC9I,93701
3
+ syncmodels/crawler.py,sha256=U6F0QlzmxkReCB6X2Xbxmm2rRn99GEX005dG7AFl8xE,94430
4
4
  syncmodels/crud.py,sha256=viHBwzczcjNyFiLxL7VGYSbWJW5VjU8AvKaPufBMP7M,15303
5
- syncmodels/definitions.py,sha256=2P-Sfgj18viSHZ-wAK4WfQEzDKdyygs8Z-XLzA0jg_k,5420
6
- syncmodels/exceptions.py,sha256=8EOYW8h_2noeoKAYqG4aEQTgB1FEkamxKt3t4pDJ3pM,626
5
+ syncmodels/definitions.py,sha256=dTMxcwcIeYQthZCZXNQmaO1SolWY-WhafASyl91xTo0,5455
6
+ syncmodels/exceptions.py,sha256=ZLAwu19cs2UN2Sv3jaLnixT_jRI7T42TfyutCkUsuIk,685
7
7
  syncmodels/geofactory.py,sha256=1FkrdEn0QA0O4_lSUAwjqXH2dmlQWi32AkntnG4AEQY,10372
8
8
  syncmodels/http.py,sha256=FFVT3QJJgur2dv1Q_7l9ZsWN8z6_gUjOT9hJff1ZAqk,3335
9
9
  syncmodels/parallel.py,sha256=Ll8HmyFF9v9fIofqqSgfhyTlklvb77mTtNdG5Y9lqdQ,7145
10
10
  syncmodels/registry.py,sha256=YaQtgbSwa0je1MpCcVHALI3_b85vrddyOlhsnrUcKZs,8224
11
11
  syncmodels/requests.py,sha256=wWoC5hPDm1iBM_zrlyKRauzhXgdKR3pT5RqyC-5UZhQ,538
12
- syncmodels/runner.py,sha256=T6A_aZPtj4vqoqEf1bhd_efFEGbE6aSVjP8nJlAHFWQ,5320
12
+ syncmodels/runner.py,sha256=IHDKuQ3yJ1DN9wktMiIrerPepYX61tc3AzbFfuUqEFw,5454
13
13
  syncmodels/schema.py,sha256=uinUt8Asq_x7xa6MKWVXNyoWO6gKocjGPppjimaXzEU,2492
14
- syncmodels/storage.py,sha256=vyIW_C6FoSh4VdCs-GcvNOKdpIfqyaIc1Cq5PV081Lo,69485
14
+ syncmodels/storage.py,sha256=-kdXuPjkHBPauoXTWcmwK4jmH9hr2X1JFERqluznL1Q,71513
15
15
  syncmodels/syncmodels.py,sha256=EzSC4C75V4wJDmsLLbp8YUVwqA6A16KCNW8nB-MqPcs,10567
16
16
  syncmodels/timequeue.py,sha256=YRd3ULRaIhoszaBsYhfr0epMqAbL6-NwVEtScjUYttM,595
17
17
  syncmodels/wave.py,sha256=Gra22BLiA9z2nF-6diXpjAc4GZv9nebmyvHxdAfXec4,7764
@@ -32,22 +32,22 @@ syncmodels/helpers/geojson.py,sha256=9VZjdEw19fLS_Q9topapUOPGxRg2D4GOqm2tlx11W7M
32
32
  syncmodels/helpers/importers.py,sha256=KImR9pQu4ir6EI6Ipta0q3RWloFT_VTJi67kM0lZsKQ,3919
33
33
  syncmodels/helpers/loaders.py,sha256=aus0aRcbU1vVa_zWo42aX6uV3B0fQ0aQpkTWlR9xGLA,4325
34
34
  syncmodels/helpers/models.py,sha256=c_ATzmiw5mVY1IGnwmyhjIuu5d2idHU-XeRigZSMkOQ,719
35
- syncmodels/helpers/orion.py,sha256=Fx-sVvI35FyKFcSd0vfY2Tjp7hlIwBJpshs2vb3fcsc,30584
35
+ syncmodels/helpers/orion.py,sha256=Lblk4OGRNidYl1-2lZKUPXyvuR1hXip7FHloXLtU-XA,30717
36
36
  syncmodels/helpers/surreal.py,sha256=zoWtGm5oAxwvgJNq_NTpKOHN3h9FNObhFDLuiBOl1YY,10050
37
37
  syncmodels/helpers/units.py,sha256=g50m5DQrAyP_qpDRa4LCEA5Rz2UZUmlIixfWG_ddw9I,3571
38
38
  syncmodels/logic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
39
  syncmodels/logic/activity_logger.py,sha256=8wjvgRwaNbibYWGgl-trovSS70yNkoCTlb-AIx3aZEE,14053
40
40
  syncmodels/logic/analyzer.py,sha256=7JDIvZIiDVgdABaaRk7TEbzOFM6HAH3RaSsIDmL4QVE,12291
41
- syncmodels/logic/browser.py,sha256=W_s_rIWceGni2GMdhlrdZTTxTG-43n2CQDhPgyJfdE0,84711
41
+ syncmodels/logic/browser.py,sha256=KqvOLPAl2p5EBol7FK-XYvOXeDnu0h9Dz7xfagKTheM,84768
42
42
  syncmodels/logic/swarm.py,sha256=eRBVlNAOzzWKFGCb7LGLx2aj7yQlTY1OwLoeSEllvXY,17207
43
43
  syncmodels/mapper/__init__.py,sha256=jS82LFr9zzyqXBz82tSw04vDowhTpKxhg_W2XvhUlt0,129
44
44
  syncmodels/mapper/fiware.py,sha256=auszPmhCS46z_68MXjksrQAFUfctjbVrVdBvOpOkMj8,523
45
45
  syncmodels/mapper/mapper.py,sha256=SphMhr59bbTWWxnvitonURk3lSPDerGqUTs5-P-Tjlg,17397
46
- syncmodels/model/__init__.py,sha256=tHoKorgbN77ulv2SZ_fGqZqkq7yoWUvqM5SKKxrJWRE,127
46
+ syncmodels/model/__init__.py,sha256=mD6fpRvBOl7i98pqqwpB2NKlviyD-G8iRXqufjU-9z8,148
47
47
  syncmodels/model/activity.py,sha256=tKzc9zc_5Sx549yTdaTYkfnLnbEsEmzpu53BHstqvFQ,4592
48
48
  syncmodels/model/geofilters.py,sha256=YxZZPk60MvzrBslOrpJec_Er1aTWGg1wgYrXPovrpP8,9284
49
49
  syncmodels/model/geojson.py,sha256=BsW3phXHBGeaIOyOZg7U8bRYKKerAEgNjCl8EnBS2Dg,8329
50
- syncmodels/model/model.py,sha256=0DtnsqlK1oEzHe5CdPMRnNaYJT3Hi2S-adqdydBSyYM,11541
50
+ syncmodels/model/model.py,sha256=c8fAvGZ8_oXYQbdNixltRFhWjY3zYE1Y7MTLXIjbpac,11558
51
51
  syncmodels/model/swarm.py,sha256=0QMc1iyiuW5goLLQGFTIky3dJcc5BfuBPHtVbn7iRK4,1266
52
52
  syncmodels/model/schema_org/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
53
  syncmodels/model/schema_org/aboutpage.py,sha256=_sqPMc7LxGWNSHwkvTB6OZZAfEovgHltisp6AAz2t9Y,452
@@ -302,10 +302,10 @@ syncmodels/session/postgresql.py,sha256=ZMIu1Rv93pKfvFlovFBmWArzlrT2xaQWNYGZT_LW
302
302
  syncmodels/session/sql.py,sha256=bD7zXRrEKKJmqY2UoibWENuWb5zHrrU72F3_dYbS6LY,6569
303
303
  syncmodels/session/sqlite.py,sha256=nCDjopLiBpX1F10qkKoARM7JrVdIpJ1WdGOduFVxaiA,2080
304
304
  syncmodels/source/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
305
- syncmodels-0.1.312.dist-info/AUTHORS.rst,sha256=3ZPoqg8Aav8DSYKd0fwcwn4_5HwSiMLart0E5Un00-U,168
306
- syncmodels-0.1.312.dist-info/LICENSE,sha256=uzMOYtIiUsnsD0xHJR7aJWJ4v_bvan0kTnvufy5eNoA,1075
307
- syncmodels-0.1.312.dist-info/METADATA,sha256=CvmyXbM7GlQD3qm93hNGd_yq6yWd_MXAC6BatNPu_iA,2700
308
- syncmodels-0.1.312.dist-info/WHEEL,sha256=SrDKpSbFN1G94qcmBqS9nyHcDMp9cUS9OC06hC0G3G0,109
309
- syncmodels-0.1.312.dist-info/entry_points.txt,sha256=dMnigjZsHMxTwXiiZyBZdBbMYE0-hY3L5cG15EcDAzw,51
310
- syncmodels-0.1.312.dist-info/top_level.txt,sha256=2DfQ9NuAhKMjY3BvQGVBA7GfqTm7EoHNbaehSUiqiHQ,11
311
- syncmodels-0.1.312.dist-info/RECORD,,
305
+ syncmodels-0.1.314.dist-info/AUTHORS.rst,sha256=3ZPoqg8Aav8DSYKd0fwcwn4_5HwSiMLart0E5Un00-U,168
306
+ syncmodels-0.1.314.dist-info/LICENSE,sha256=uzMOYtIiUsnsD0xHJR7aJWJ4v_bvan0kTnvufy5eNoA,1075
307
+ syncmodels-0.1.314.dist-info/METADATA,sha256=59uo0tcMb8sXzIoBOlGNPUdyivZA7wIhkYj1hXZ1sMU,2700
308
+ syncmodels-0.1.314.dist-info/WHEEL,sha256=SrDKpSbFN1G94qcmBqS9nyHcDMp9cUS9OC06hC0G3G0,109
309
+ syncmodels-0.1.314.dist-info/entry_points.txt,sha256=dMnigjZsHMxTwXiiZyBZdBbMYE0-hY3L5cG15EcDAzw,51
310
+ syncmodels-0.1.314.dist-info/top_level.txt,sha256=2DfQ9NuAhKMjY3BvQGVBA7GfqTm7EoHNbaehSUiqiHQ,11
311
+ syncmodels-0.1.314.dist-info/RECORD,,