1010
1111
1212class IdSync :
13+ """
14+ Synchronizes a model with the IDs from model JSON file.
15+ After syncing, the model will have all IDs assigned.
16+ The JSON file is written (from scratch) based on the model.
17+ """
18+
1319 def __init__ (self , model : Model , model_json_filepath : str ):
1420 self .model = model
1521
@@ -63,8 +69,9 @@ def _save_model_json(self):
6369 "id" : str (prop .iduid ),
6470 "name" : prop .name ,
6571 "type" : prop ._ob_type ,
66- "flags" : prop ._flags
6772 }
73+ if prop ._flags != 0 :
74+ prop_json ["flags" ] = prop ._flags
6875 if prop .index is not None :
6976 prop_json ["indexId" ] = str (prop .index .iduid )
7077 entity_json ["properties" ].append (prop_json )
@@ -80,6 +87,7 @@ def _find_entity_json_by_uid(self, uid: int) -> Optional[Dict[str, Any]]:
8087 """ Finds entity JSON by UID. """
8188 if self .model_json is None :
8289 return None
90+ # TODO put entities in a dict (e.g. while/after loading) for faster lookup
8391 for entity_json in self .model_json ["entities" ]:
8492 if IdUid .from_str (entity_json ["id" ]).uid == uid :
8593 return entity_json
@@ -89,20 +97,23 @@ def _find_entity_json_by_name(self, entity_name: str) -> Optional[Dict[str, Any]
8997 """ Finds entity JSON by name. """
9098 if self .model_json is None :
9199 return None
100+ # TODO put entities in a dict (e.g. while/after loading) for faster lookup
92101 for entity_json in self .model_json ["entities" ]:
93102 if entity_json ["name" ] == entity_name :
94103 return entity_json
95104 return None
96105
97106 def _find_property_json_by_uid (self , entity_json : Dict [str , Any ], uid : int ) -> Optional [Dict [str , Any ]]:
98107 """ Finds entity property JSON by property UID. """
108+ # TODO put properties in a multi-dict (e.g. while/after loading) for faster lookup
99109 for prop_json in entity_json ["properties" ]:
100110 if IdUid .from_str (prop_json ["id" ]).uid == uid :
101111 return prop_json
102112 return None
103113
104114 def _find_property_json_by_name (self , entity_json : Dict [str , Any ], prop_name : str ) -> Optional [Dict [str , Any ]]:
105115 """ Finds entity property JSON by property name. """
116+ # TODO put properties in a multi-dict (e.g. while/after loading) for faster lookup
106117 for prop_json in entity_json ["properties" ]:
107118 if prop_json ["name" ] == prop_name :
108119 return prop_json
@@ -113,6 +124,7 @@ def _generate_uid() -> int:
113124 return random .getrandbits (63 ) + 1 # 0 would be invalid
114125
115126 def _validate_uid_unassigned (self , uid : int ):
127+ # TODO use a dict/set for all assigned UIDs (for all entities/properties/indexes) for faster lookup
116128 """ Validates that a user supplied UID is not assigned for any other entity/property/index.
117129 Raises a ValueError if the UID is already assigned elsewhere.
118130 """
@@ -141,9 +153,12 @@ def _validate_matching_prop(self, entity: _Entity, prop: Property, prop_json: Di
141153 # raise ValueError(f"name {prop.name} != name {prop_json['name']} (in JSON)")
142154 if prop ._ob_type != prop_json ["type" ]:
143155 raise ValueError (f"OBX type { prop ._ob_type } != OBX type { prop_json ['type' ]} (in JSON)" )
144- elif prop ._flags != prop_json ["flags" ]:
145- raise ValueError (f"flags { prop ._flags } != flags { prop_json ['flags' ]} (in JSON)" )
146- elif prop .index is None and "indexId" in prop_json :
156+
157+ json_flags = prop_json .get ("flags" , 0 )
158+ if prop ._flags != json_flags :
159+ raise ValueError (f"flags { prop ._flags } != flags { json_flags } (in JSON)" )
160+
161+ if prop .index is None and "indexId" in prop_json :
147162 raise ValueError ("property hasn't index, but index found in JSON" )
148163 elif prop .index is not None and "indexId" not in prop_json :
149164 raise ValueError ("property has index, but index not found in JSON" )
@@ -169,7 +184,7 @@ def _load_or_assign_index(self, entity: _Entity, prop: Property, prop_json: Opti
169184
170185 if (iduid_json is not None ) and (not index .has_uid () or index .iduid .uid == iduid_json .uid ): # Load
171186 index .iduid = IdUid .from_str (prop_json ["indexId" ])
172- else : # Assign
187+ else : # Assign new ID to new index
173188 index .iduid = IdUid (self .model .last_index_iduid .id + 1 , index .uid )
174189 self .model .last_index_iduid = index .iduid
175190
@@ -186,11 +201,11 @@ def _load_or_assign_property(self, entity: _Entity, prop: Property, entity_json:
186201 if entity_json is not None :
187202 prop_json = self ._find_property_json_by_name (entity_json , prop .name )
188203
189- if prop_json is not None : # Load
204+ if prop_json is not None : # Load existing IDs from JSON
190205 # Property was matched with a JSON property (either by UID or by name), make sure they're equal
191206 self ._validate_matching_prop (entity , prop , prop_json )
192207 prop .iduid = IdUid .from_str (prop_json ["id" ])
193- else : # Assign
208+ else : # Assign new ID to new property
194209 if not prop .has_uid ():
195210 prop .iduid .uid = self ._generate_uid ()
196211 prop .iduid = IdUid (entity .last_property_iduid .id + 1 , prop .iduid .uid )
@@ -209,10 +224,10 @@ def _load_or_assign_entity(self, entity: _Entity):
209224 else :
210225 entity_json = self ._find_entity_json_by_name (entity .name )
211226
212- if entity_json is not None : # Load
227+ if entity_json is not None : # Load existing IDs from JSON
213228 entity .iduid = IdUid .from_str (entity_json ["id" ])
214229 entity .last_property_iduid = IdUid .from_str (entity_json ["lastPropertyId" ])
215- else : # Assign
230+ else : # Assign new ID to new entity
216231 if not entity .has_uid ():
217232 entity .iduid .uid = self ._generate_uid ()
218233 entity .iduid = IdUid (self .model .last_entity_iduid .id + 1 , entity .iduid .uid )
0 commit comments