Skip to content

Commit 6ef3069

Browse files
committed
RDBC-839 changing the semantic - find_identity_property to get_identity_property_name, fixes in EntityToJson
1 parent 40b1baf commit 6ef3069

5 files changed

Lines changed: 214 additions & 189 deletions

File tree

ravendb/documents/conventions.py

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from abc import abstractmethod, ABC
66
from datetime import timedelta, datetime
77
from 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

1010
import inflect
1111

@@ -25,6 +25,11 @@
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

2934
class 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._get_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,7 +222,7 @@ 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

222228
@staticmethod
@@ -355,7 +361,7 @@ def range_field_name(field_name, type_name):
355361

356362
return field_name
357363

358-
def __assert_not_frozen(self) -> None:
364+
def _assert_not_frozen(self) -> None:
359365
if self._frozen:
360366
raise RuntimeError(
361367
"Conventions has been frozen after documentStore.initialize()" " and no changes can be applied to them"
@@ -370,7 +376,7 @@ def clone(self) -> DocumentConventions:
370376
cloned._save_enums_as_integers = self._save_enums_as_integers
371377
cloned.identity_parts_separator = self.identity_parts_separator
372378
cloned.disable_topology_updates = self.disable_topology_updates
373-
cloned._find_identity_property = self._find_identity_property
379+
cloned._get_identity_property_name = self._get_identity_property_name
374380

375381
cloned.document_id_generator = self.document_id_generator
376382

@@ -384,6 +390,19 @@ def clone(self) -> DocumentConventions:
384390
cloned._read_balance_behavior = self._read_balance_behavior
385391
cloned._load_balance_behavior = self._load_balance_behavior
386392
self._max_http_cache_size = self._max_http_cache_size
393+
return cloned
394+
395+
def get_identity_property_name(self, object_type: Type[Any]) -> Optional[str]:
396+
# Check the cache first
397+
if object_type in self._id_property_name_cache:
398+
return self._id_property_name_cache[object_type]
399+
400+
id_property_name = self._get_identity_property_name(object_type)
401+
402+
# Cache the result
403+
self._id_property_name_cache[object_type] = id_property_name
404+
405+
return id_property_name
387406

388407
def update_from(self, configuration: ClientConfiguration):
389408
if configuration.disabled and self._original_configuration is None:
@@ -479,7 +498,7 @@ def update_from(self, configuration: ClientConfiguration):
479498

480499
@staticmethod
481500
def default_transform_collection_name_to_document_id_prefix(collection_name: str) -> str:
482-
upper_count = len(list(filter(str.isupper, collection_name)))
501+
upper_count = len(list(filter(str.isupper, [char for char in collection_name])))
483502
if upper_count <= 1:
484503
return collection_name.lower()
485504

ravendb/documents/identity/hilo.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22
import datetime
33
from threading import Lock
4-
from typing import Any, Union, Optional, Iterable, Dict, Tuple, Callable
4+
from typing import Any, Union, Optional, Iterable, Dict, Tuple, Callable, Type
55

66
from typing import TYPE_CHECKING
77

@@ -15,22 +15,27 @@
1515

1616
class GenerateEntityIdOnTheClient:
1717
def __init__(self, conventions: "DocumentConventions", generate_id: Callable[[Any], str]):
18-
self.__conventions = conventions
19-
self.__generate_id = generate_id
18+
self._conventions = conventions
19+
self._generate_id = generate_id
20+
21+
def get_identity_property_name(self, object_type: Type[Any]) -> str:
22+
return self._conventions.get_identity_property_name(object_type)
2023

2124
def try_get_id_from_instance(self, entity: Union[object, dict]) -> Tuple[bool, Union[str, None]]:
2225
if not entity:
2326
raise ValueError("Entity cannot be None")
24-
identity_property = "Id" # todo: make sure it's ok, create get_identity_property within conventions if not
27+
28+
identity_property = self.get_identity_property_name(entity.__class__)
29+
2530
value = (entity if isinstance(entity, dict) else entity.__dict__).get(identity_property, None)
2631
if isinstance(value, str):
2732
return True, value
2833
return False, None
2934

3035
def get_or_generate_document_id(self, entity) -> str:
31-
key = self.try_get_id_from_instance(entity)[1]
32-
if key is None:
33-
key = self.__generate_id(entity)
36+
success, key = self.try_get_id_from_instance(entity)
37+
if not success:
38+
key = self._generate_id(entity)
3439

3540
if key and key.startswith("/"):
3641
raise ValueError(f"Cannot use value '{key}' as a document id because it begins with a '/'")
@@ -43,22 +48,22 @@ def generate_document_key_for_storage(self, entity: object) -> str:
4348
return key
4449

4550
def try_set_identity(self, entity: object, key: str, is_projection: bool = False) -> None:
46-
self.__try_set_identity_internal(entity, key, is_projection)
51+
self._try_set_identity_internal(entity, key, is_projection)
4752

48-
def __try_set_identity_internal(self, entity: Union[object, dict], key: str, is_projection: bool = False) -> None:
49-
identity_property = "Id" # todo: get_identity_property...
53+
def _try_set_identity_internal(self, entity: Union[object, dict], key: str, is_projection: bool = False) -> None:
54+
identity_property_name = self._conventions.get_identity_property_name(entity.__class__)
5055

51-
if identity_property is None:
56+
if identity_property_name is None:
5257
return
5358

54-
if is_projection and entity.__getattribute__(identity_property):
59+
if is_projection and entity.__getattribute__(identity_property_name):
5560
# identity property was already set
5661
return
5762

5863
if isinstance(entity, dict):
59-
entity[identity_property] = key
64+
entity[identity_property_name] = key
6065
return
61-
entity.__setattr__(identity_property, key)
66+
entity.__setattr__(identity_property_name, key)
6267

6368

6469
class MultiDatabaseHiLoGenerator:

0 commit comments

Comments
 (0)