55from abc import abstractmethod , ABC
66from datetime import timedelta , datetime
77from enum import Enum
8- from typing import Dict , List , Tuple , Callable , Union , Optional , Generic , Type
8+ from typing import Dict , List , Tuple , Callable , Union , Optional , Generic , Type , Any , TYPE_CHECKING
99
1010import inflect
1111
2525
2626_T = TypeVar ("_T" )
2727
28+ if TYPE_CHECKING :
29+ from ravendb .documents .session .document_session_operations .in_memory_document_session_operations import (
30+ InMemoryDocumentSessionOperations ,
31+ )
32+
2833
2934class DocumentConventions (object ):
3035 @classmethod
@@ -63,7 +68,8 @@ def __init__(self):
6368
6469 # Utilities
6570 self .document_id_generator : Optional [Callable [[str , object ], str ]] = None
66- self ._find_identity_property = lambda q : q .__name__ == "key"
71+ self ._find_identity_property_name : Callable [[Type [Any ]], str ] = lambda type_ : "Id"
72+ self ._id_property_name_cache : Dict [Type , str ] = {}
6773 self ._find_python_class : Optional [Callable [[str , Dict ], str ]] = None
6874 self ._find_collection_name : Callable [[Type ], str ] = self .default_get_collection_name
6975 self ._find_collection_name_for_dict : Callable [[str ], str ] = self .default_get_collection_name_for_dict
@@ -106,7 +112,7 @@ def find_collection_name(self) -> Callable[[type], str]:
106112
107113 @find_collection_name .setter
108114 def find_collection_name (self , value ) -> None :
109- self .__assert_not_frozen ()
115+ self ._assert_not_frozen ()
110116 self ._find_collection_name = value
111117
112118 @property
@@ -122,7 +128,7 @@ def __default(key: str, doc: Dict) -> Optional[str]:
122128
123129 @find_python_class .setter
124130 def find_python_class (self , value : Callable [[str , Dict ], str ]):
125- self .__assert_not_frozen ()
131+ self ._assert_not_frozen ()
126132 self ._find_python_class = value
127133
128134 def get_python_class (self , key : str , document : Dict ) -> str :
@@ -134,7 +140,7 @@ def transform_class_collection_name_to_document_id_prefix(self) -> Callable[[str
134140
135141 @transform_class_collection_name_to_document_id_prefix .setter
136142 def transform_class_collection_name_to_document_id_prefix (self , value : Callable [[str ], str ]) -> None :
137- self .__assert_not_frozen ()
143+ self ._assert_not_frozen ()
138144 self ._transform_class_collection_name_to_document_id_prefix = value
139145
140146 @property
@@ -167,7 +173,7 @@ def find_python_class_name(self) -> Callable[[type], str]:
167173
168174 @find_python_class_name .setter
169175 def find_python_class_name (self , value ) -> None :
170- self .__assert_not_frozen ()
176+ self ._assert_not_frozen ()
171177 self ._find_python_class_name = value
172178
173179 @property
@@ -176,7 +182,7 @@ def should_ignore_entity_changes(self) -> ShouldIgnoreEntityChanges:
176182
177183 @should_ignore_entity_changes .setter
178184 def should_ignore_entity_changes (self , value : ShouldIgnoreEntityChanges ) -> None :
179- self .__assert_not_frozen ()
185+ self ._assert_not_frozen ()
180186 self ._should_ignore_entity_changes = value
181187
182188 @property
@@ -185,7 +191,7 @@ def load_balancer_context_seed(self) -> int:
185191
186192 @load_balancer_context_seed .setter
187193 def load_balancer_context_seed (self , value : int ):
188- self .__assert_not_frozen ()
194+ self ._assert_not_frozen ()
189195 self ._load_balancer_context_seed = value
190196
191197 @property
@@ -194,7 +200,7 @@ def load_balance_behavior(self):
194200
195201 @load_balance_behavior .setter
196202 def load_balance_behavior (self , value : LoadBalanceBehavior ):
197- self .__assert_not_frozen ()
203+ self ._assert_not_frozen ()
198204 self ._load_balance_behavior = value
199205
200206 @property
@@ -203,7 +209,7 @@ def read_balance_behavior(self) -> ReadBalanceBehavior:
203209
204210 @read_balance_behavior .setter
205211 def read_balance_behavior (self , value : ReadBalanceBehavior ):
206- self .__assert_not_frozen ()
212+ self ._assert_not_frozen ()
207213 self ._read_balance_behavior = value
208214
209215 @property
@@ -216,9 +222,17 @@ def disable_atomic_document_writes_in_cluster_wide_transaction(self) -> bool:
216222
217223 @disable_atomic_document_writes_in_cluster_wide_transaction .setter
218224 def disable_atomic_document_writes_in_cluster_wide_transaction (self , value : bool ):
219- self .__assert_not_frozen ()
225+ self ._assert_not_frozen ()
220226 self ._disable_atomic_document_writes_in_cluster_wide_transaction = value
221227
228+ @property
229+ def find_identity_property_name (self ) -> Callable [[Type [Any ]], str ]:
230+ return self ._find_identity_property_name
231+
232+ @find_identity_property_name .setter
233+ def find_identity_property_name (self , find_identity_property_name_function : Callable [[Type [Any ]], str ]):
234+ self ._find_identity_property_name = find_identity_property_name_function
235+
222236 @staticmethod
223237 def json_default (o ):
224238 if o is None :
@@ -325,7 +339,7 @@ def default_get_collection_name_for_dict(key: str) -> str:
325339 return result
326340
327341 @staticmethod
328- def try_get_type_from_metadata (metadata ) :
342+ def try_get_type_from_metadata (metadata : Dict [ str , Any ]) -> Optional [ str ] :
329343 if "Raven-Python-Type" in metadata :
330344 return metadata ["Raven-Python-Type" ]
331345 return None
@@ -355,7 +369,7 @@ def range_field_name(field_name, type_name):
355369
356370 return field_name
357371
358- def __assert_not_frozen (self ) -> None :
372+ def _assert_not_frozen (self ) -> None :
359373 if self ._frozen :
360374 raise RuntimeError (
361375 "Conventions has been frozen after documentStore.initialize()" " and no changes can be applied to them"
@@ -370,7 +384,7 @@ def clone(self) -> DocumentConventions:
370384 cloned ._save_enums_as_integers = self ._save_enums_as_integers
371385 cloned .identity_parts_separator = self .identity_parts_separator
372386 cloned .disable_topology_updates = self .disable_topology_updates
373- cloned ._find_identity_property = self ._find_identity_property
387+ cloned ._find_identity_property_name = self ._find_identity_property_name
374388
375389 cloned .document_id_generator = self .document_id_generator
376390
@@ -384,6 +398,19 @@ def clone(self) -> DocumentConventions:
384398 cloned ._read_balance_behavior = self ._read_balance_behavior
385399 cloned ._load_balance_behavior = self ._load_balance_behavior
386400 self ._max_http_cache_size = self ._max_http_cache_size
401+ return cloned
402+
403+ def get_identity_property_name (self , object_type : Type [Any ]) -> Optional [str ]:
404+ # Check the cache first
405+ if object_type in self ._id_property_name_cache :
406+ return self ._id_property_name_cache [object_type ]
407+
408+ id_property_name = self .find_identity_property_name (object_type )
409+
410+ # Cache the result
411+ self ._id_property_name_cache [object_type ] = id_property_name
412+
413+ return id_property_name
387414
388415 def update_from (self , configuration : ClientConfiguration ):
389416 if configuration .disabled and self ._original_configuration is None :
@@ -479,7 +506,7 @@ def update_from(self, configuration: ClientConfiguration):
479506
480507 @staticmethod
481508 def default_transform_collection_name_to_document_id_prefix (collection_name : str ) -> str :
482- upper_count = len (list (filter (str .isupper , collection_name )))
509+ upper_count = len (list (filter (str .isupper , [ char for char in collection_name ] )))
483510 if upper_count <= 1 :
484511 return collection_name .lower ()
485512
0 commit comments