contentgrid-application-client 0.2.9__tar.gz → 0.2.11__tar.gz
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.
- {contentgrid_application_client-0.2.9/src/contentgrid_application_client.egg-info → contentgrid_application_client-0.2.11}/PKG-INFO +4 -2
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/pyproject.toml +6 -2
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/src/contentgrid_application_client/application.py +54 -40
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11/src/contentgrid_application_client.egg-info}/PKG-INFO +4 -2
- contentgrid_application_client-0.2.11/src/contentgrid_application_client.egg-info/requires.txt +1 -0
- contentgrid_application_client-0.2.11/src/contentgrid_application_client.egg-info/scm_version.json +8 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_profile.py +34 -34
- contentgrid_application_client-0.2.9/src/contentgrid_application_client.egg-info/requires.txt +0 -1
- contentgrid_application_client-0.2.9/src/contentgrid_application_client.egg-info/scm_version.json +0 -8
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/LICENSE +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/README.md +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/pytest.ini +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/requirements.txt +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/setup.cfg +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/setup.py +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/src/contentgrid_application_client/__init__.py +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/src/contentgrid_application_client/py.typed +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/src/contentgrid_application_client.egg-info/SOURCES.txt +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/src/contentgrid_application_client.egg-info/dependency_links.txt +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/src/contentgrid_application_client.egg-info/scm_file_list.json +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/src/contentgrid_application_client.egg-info/top_level.txt +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/example-docs/document.jpg +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/example-docs/resume.pdf +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/fixtures.py +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_collection.py +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_content.py +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_curies.py +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_entity_creation.py +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_hal_form_type_check.py +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_openapi.py +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_prompting.py +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_relations.py +0 -0
- {contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_search.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: contentgrid-application-client
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.11
|
|
4
4
|
Summary: Python Client for interacting with ContentGrid Applications
|
|
5
5
|
Author-email: Ranec Belpaire <ranec.belpaire@xenit.eu>
|
|
6
6
|
License: Copyright 2024 Xenit Solutions
|
|
@@ -16,13 +16,15 @@ License: Copyright 2024 Xenit Solutions
|
|
|
16
16
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
17
|
See the License for the specific language governing permissions and
|
|
18
18
|
limitations under the License.
|
|
19
|
+
Project-URL: Homepage, https://github.com/xenit-eu/contentgrid-python-client
|
|
20
|
+
Project-URL: Source, https://github.com/xenit-eu/contentgrid-python-client
|
|
19
21
|
Classifier: Development Status :: 4 - Beta
|
|
20
22
|
Classifier: Operating System :: OS Independent
|
|
21
23
|
Classifier: Programming Language :: Python :: 3
|
|
22
24
|
Requires-Python: >=3.5
|
|
23
25
|
Description-Content-Type: text/markdown
|
|
24
26
|
License-File: LICENSE
|
|
25
|
-
Requires-Dist: contentgrid-hal-client==0.2.
|
|
27
|
+
Requires-Dist: contentgrid-hal-client==0.2.11
|
|
26
28
|
Dynamic: license-file
|
|
27
29
|
Dynamic: requires-dist
|
|
28
30
|
|
{contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/pyproject.toml
RENAMED
|
@@ -9,7 +9,7 @@ description = "Python Client for interacting with ContentGrid Applications"
|
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Ranec Belpaire", email = "ranec.belpaire@xenit.eu" }]
|
|
11
11
|
license = { file = "LICENSE" }
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
classifiers = [
|
|
14
14
|
"Development Status :: 4 - Beta",
|
|
15
15
|
"Operating System :: OS Independent",
|
|
@@ -18,6 +18,10 @@ classifiers = [
|
|
|
18
18
|
|
|
19
19
|
requires-python = ">=3.5"
|
|
20
20
|
|
|
21
|
+
[project.urls]
|
|
22
|
+
Homepage = "https://github.com/xenit-eu/contentgrid-python-client"
|
|
23
|
+
Source = "https://github.com/xenit-eu/contentgrid-python-client"
|
|
24
|
+
|
|
21
25
|
[tool.setuptools_scm]
|
|
22
|
-
write_to = "_version.txt"
|
|
26
|
+
write_to = "_version.txt"
|
|
23
27
|
root = "../"
|
|
@@ -25,6 +25,7 @@ hal_form_type_check = {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ"
|
|
28
|
+
MULTI_VALUED_ATTRIBUTE_TYPES = ["string_set"]
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
def is_valid_date_format(date_string):
|
|
@@ -59,6 +60,7 @@ class InteractiveApplicationResponse(InteractiveHALResponse):
|
|
|
59
60
|
class SearchType(Enum):
|
|
60
61
|
EXACT_MATCH = "exact-match"
|
|
61
62
|
PREFIX_MATCH = "prefix-match"
|
|
63
|
+
CONTAINS = "contains"
|
|
62
64
|
FULL_TEXT_MATCH = "full-text"
|
|
63
65
|
LESS_THAN = "less-than"
|
|
64
66
|
LESS_THAN_OR_EQUAL = "less-than-or-equal"
|
|
@@ -258,11 +260,11 @@ class EntityObject(InteractiveApplicationResponse):
|
|
|
258
260
|
params = self.client._add_page_and_size_to_params(size=size, params=params)
|
|
259
261
|
relation_link = self.get_relation_link(relation_name=relation_name)
|
|
260
262
|
return self.client.follow_link(relation_link, infer_type=EntityCollection, params=params)
|
|
261
|
-
|
|
263
|
+
|
|
262
264
|
def get_related_entity(self, relation_name: str) -> "EntityObject":
|
|
263
265
|
relation_link = self.get_relation_link(relation_name=relation_name)
|
|
264
266
|
return self.client.follow_link(relation_link, infer_type=EntityObject)
|
|
265
|
-
|
|
267
|
+
|
|
266
268
|
def set_related_entity(self, relation_name: str, related_entity : "EntityObject") -> None:
|
|
267
269
|
self.put_relation(relation_name=relation_name, related_entity_links=[related_entity], prefix_client_endpoint=True)
|
|
268
270
|
|
|
@@ -481,6 +483,7 @@ class AttributeProfile(InteractiveApplicationResponse):
|
|
|
481
483
|
self.__prefix_search_option: Optional[SearchOption] = None
|
|
482
484
|
self.__exact_search_option: Optional[SearchOption] = None
|
|
483
485
|
self.__full_text_search_option: Optional[SearchOption] = None
|
|
486
|
+
self.__contains_search_option: Optional[SearchOption] = None
|
|
484
487
|
self.__less_than_search_option: Optional[SearchOption] = None
|
|
485
488
|
self.__less_than_or_equal_search_option: Optional[SearchOption] = None
|
|
486
489
|
self.__greater_than_search_option: Optional[SearchOption] = None
|
|
@@ -489,9 +492,21 @@ class AttributeProfile(InteractiveApplicationResponse):
|
|
|
489
492
|
def get_nested_attributes(self) -> List["AttributeProfile"]:
|
|
490
493
|
return self.nested_attributes
|
|
491
494
|
|
|
495
|
+
@property
|
|
492
496
|
def is_content_attribute(self) -> bool:
|
|
493
497
|
return self.type == "object" and any(attr.name in ["length", "mimetype", "filename"] for attr in self.nested_attributes)
|
|
494
498
|
|
|
499
|
+
@property
|
|
500
|
+
def is_audit_attribute(self) -> bool:
|
|
501
|
+
return self.has_created_by_constraint() or \
|
|
502
|
+
self.has_created_date_constraint() or \
|
|
503
|
+
self.has_modified_by_constraint() or \
|
|
504
|
+
self.has_modified_date_constraint()
|
|
505
|
+
|
|
506
|
+
@property
|
|
507
|
+
def is_multi_valued_attribute(self) -> bool:
|
|
508
|
+
return self.type in MULTI_VALUED_ATTRIBUTE_TYPES
|
|
509
|
+
|
|
495
510
|
def get_constraints(self) -> List[AttributeConstraint]:
|
|
496
511
|
return self.constraints
|
|
497
512
|
|
|
@@ -506,32 +521,25 @@ class AttributeProfile(InteractiveApplicationResponse):
|
|
|
506
521
|
|
|
507
522
|
def has_constrained_values(self) -> bool:
|
|
508
523
|
return self.get_constraint("allowed-values") is not None
|
|
509
|
-
|
|
524
|
+
|
|
510
525
|
def has_allowed_values_constraint(self) -> bool:
|
|
511
526
|
return self.has_constrained_values()
|
|
512
|
-
|
|
527
|
+
|
|
513
528
|
def has_unique_constraint(self) -> bool:
|
|
514
529
|
return self.get_constraint("unique") is not None
|
|
515
|
-
|
|
530
|
+
|
|
516
531
|
def has_created_by_constraint(self) -> bool:
|
|
517
532
|
return self.get_constraint("created-by") is not None
|
|
518
|
-
|
|
533
|
+
|
|
519
534
|
def has_created_date_constraint(self) -> bool:
|
|
520
535
|
return self.get_constraint("created-date") is not None
|
|
521
|
-
|
|
536
|
+
|
|
522
537
|
def has_modified_by_constraint(self) -> bool:
|
|
523
538
|
return self.get_constraint("modified-by") is not None
|
|
524
|
-
|
|
539
|
+
|
|
525
540
|
def has_modified_date_constraint(self) -> bool:
|
|
526
541
|
return self.get_constraint("modified-date") is not None
|
|
527
|
-
|
|
528
|
-
@property
|
|
529
|
-
def is_audit_attribute(self) -> bool:
|
|
530
|
-
return self.has_created_by_constraint() or \
|
|
531
|
-
self.has_created_date_constraint() or \
|
|
532
|
-
self.has_modified_by_constraint() or \
|
|
533
|
-
self.has_modified_date_constraint()
|
|
534
|
-
|
|
542
|
+
|
|
535
543
|
def get_allowed_values(self) -> Optional[List[str]]:
|
|
536
544
|
if self.has_constrained_values():
|
|
537
545
|
return self.get_constraint("allowed-values").values # type: ignore
|
|
@@ -557,7 +565,7 @@ class AttributeProfile(InteractiveApplicationResponse):
|
|
|
557
565
|
if self.__prefix_search_option is None:
|
|
558
566
|
self.__prefix_search_option = self.get_search_option(search_type=SearchType.PREFIX_MATCH)
|
|
559
567
|
return self.__prefix_search_option
|
|
560
|
-
|
|
568
|
+
|
|
561
569
|
@property
|
|
562
570
|
def _full_text_search_option(self) -> Optional[SearchOption]:
|
|
563
571
|
if self.__full_text_search_option is None:
|
|
@@ -575,6 +583,12 @@ class AttributeProfile(InteractiveApplicationResponse):
|
|
|
575
583
|
self.__exact_search_option = case_insensitive_match
|
|
576
584
|
return self.__exact_search_option
|
|
577
585
|
|
|
586
|
+
@property
|
|
587
|
+
def _contains_search_option(self) -> Optional[SearchOption]:
|
|
588
|
+
if self.__contains_search_option is None:
|
|
589
|
+
self.__contains_search_option = self.get_search_option(search_type=SearchType.CONTAINS)
|
|
590
|
+
return self.__contains_search_option
|
|
591
|
+
|
|
578
592
|
@property
|
|
579
593
|
def _less_than_search_option(self) -> Optional[SearchOption]:
|
|
580
594
|
if self.__less_than_search_option is None:
|
|
@@ -710,18 +724,18 @@ _search_form_relation_delimiter = "."
|
|
|
710
724
|
|
|
711
725
|
class AttributeSearch(ABC):
|
|
712
726
|
"""Abstract base class for attribute search implementations."""
|
|
713
|
-
|
|
727
|
+
|
|
714
728
|
def __init__(self, attribute_name: str, ignore_errors: bool = False) -> None:
|
|
715
729
|
self.attribute_name: str = attribute_name
|
|
716
730
|
self.ignore_errors: bool = ignore_errors
|
|
717
|
-
|
|
731
|
+
|
|
718
732
|
@abstractmethod
|
|
719
733
|
def get_search_params(self, attribute_profile: AttributeProfile) -> List[SearchParam]:
|
|
720
734
|
"""Convert this search specification into search parameters.
|
|
721
|
-
|
|
735
|
+
|
|
722
736
|
Args:
|
|
723
737
|
attribute_profile: The attribute profile to validate against and extract search options from.
|
|
724
|
-
|
|
738
|
+
|
|
725
739
|
Returns:
|
|
726
740
|
List of SearchParam objects representing the search criteria.
|
|
727
741
|
"""
|
|
@@ -730,11 +744,11 @@ class AttributeSearch(ABC):
|
|
|
730
744
|
|
|
731
745
|
class AttributeMatchSearch(AttributeSearch):
|
|
732
746
|
def __init__(
|
|
733
|
-
self,
|
|
734
|
-
attribute_name: str,
|
|
735
|
-
value: Union[float | int | date | datetime | bool | str],
|
|
736
|
-
use_prefix: bool = False,
|
|
737
|
-
use_full_text: bool = False,
|
|
747
|
+
self,
|
|
748
|
+
attribute_name: str,
|
|
749
|
+
value: Union[float | int | date | datetime | bool | str],
|
|
750
|
+
use_prefix: bool = False,
|
|
751
|
+
use_full_text: bool = False,
|
|
738
752
|
use_exact: bool = False,
|
|
739
753
|
ignore_errors: bool = False
|
|
740
754
|
) -> None:
|
|
@@ -753,7 +767,7 @@ class AttributeMatchSearch(AttributeSearch):
|
|
|
753
767
|
or (not attribute_profile._exact_search_option
|
|
754
768
|
and not attribute_profile._prefix_search_option
|
|
755
769
|
and not attribute_profile._full_text_search_option)
|
|
756
|
-
):
|
|
770
|
+
):
|
|
757
771
|
raise BadRequest(f"Attribute {self.attribute_name} does not support search. Available options: {attribute_profile.search_options}")
|
|
758
772
|
|
|
759
773
|
# Extract available search options
|
|
@@ -762,10 +776,10 @@ class AttributeMatchSearch(AttributeSearch):
|
|
|
762
776
|
exact_option = attribute_profile._exact_search_option
|
|
763
777
|
|
|
764
778
|
selected_option = None
|
|
765
|
-
|
|
779
|
+
|
|
766
780
|
# Check if any specific search type is explicitly requested
|
|
767
781
|
any_use_flag_set = self.use_prefix or self.use_full_text or self.use_exact
|
|
768
|
-
|
|
782
|
+
|
|
769
783
|
if any_use_flag_set:
|
|
770
784
|
# Use explicitly requested search types (in priority order)
|
|
771
785
|
if self.use_full_text and full_text_option:
|
|
@@ -788,7 +802,7 @@ class AttributeMatchSearch(AttributeSearch):
|
|
|
788
802
|
selected_option = exact_option
|
|
789
803
|
elif attribute_profile.has_search_capability():
|
|
790
804
|
selected_option = attribute_profile.search_options[0]
|
|
791
|
-
|
|
805
|
+
|
|
792
806
|
if selected_option:
|
|
793
807
|
search_params.append(SearchParam(value=self.value, option=selected_option))
|
|
794
808
|
|
|
@@ -943,12 +957,12 @@ class ContentGridApplicationClient(HALFormsClient):
|
|
|
943
957
|
self.attribute_validation = attribute_validation
|
|
944
958
|
self.use_profile_cache = use_profile_cache
|
|
945
959
|
self.profile_cache: dict[str, dict[str, Any]] = {}
|
|
946
|
-
|
|
960
|
+
|
|
947
961
|
# PROFILE CACHING
|
|
948
962
|
def load_profile_cache(self, url: str, json_data: dict | str) -> None:
|
|
949
963
|
"""
|
|
950
964
|
Load JSON data into the profile cache.
|
|
951
|
-
|
|
965
|
+
|
|
952
966
|
Args:
|
|
953
967
|
url: The URL to cache the response for (relative to client_endpoint)
|
|
954
968
|
json_data: The JSON data to cache (as dict or JSON string)
|
|
@@ -958,11 +972,11 @@ class ContentGridApplicationClient(HALFormsClient):
|
|
|
958
972
|
|
|
959
973
|
self.profile_cache[url] = cast(dict, json_data)
|
|
960
974
|
logging.info(f"Loaded JSON data into profile cache for {url}")
|
|
961
|
-
|
|
975
|
+
|
|
962
976
|
def clear_profile_cache(self):
|
|
963
977
|
logging.info(f"Clearing profile cache... clearing {len(self.profile_cache.keys())} entries")
|
|
964
|
-
self.profile_cache = {}
|
|
965
|
-
|
|
978
|
+
self.profile_cache = {}
|
|
979
|
+
|
|
966
980
|
def get_profile(self) -> Profile:
|
|
967
981
|
if self.use_profile_cache:
|
|
968
982
|
profile_cache_key = self.client_endpoint.click("/profile").normalize().to_text()
|
|
@@ -982,7 +996,7 @@ class ContentGridApplicationClient(HALFormsClient):
|
|
|
982
996
|
|
|
983
997
|
def get_entity_profiles(self) -> List[EntityProfile]:
|
|
984
998
|
return [entity_profile for entity_profile in self.get_profile().get_entity_profiles_generator()]
|
|
985
|
-
|
|
999
|
+
|
|
986
1000
|
def load_or_fetch_entity_profile(self, profile_link : HALLink, params: dict={}) -> EntityProfile:
|
|
987
1001
|
if self.use_profile_cache:
|
|
988
1002
|
if profile_link.uri in self.profile_cache:
|
|
@@ -1158,12 +1172,12 @@ class ContentGridApplicationClient(HALFormsClient):
|
|
|
1158
1172
|
|
|
1159
1173
|
def _prefix_url_in_form_payload(self, template: HALFormsTemplate, payload: dict) -> None:
|
|
1160
1174
|
"""Prefix URL properties in the payload with the client_endpoint if needed.
|
|
1161
|
-
|
|
1162
|
-
Modifies the payload in-place, prefixing any URL-type properties with the
|
|
1175
|
+
|
|
1176
|
+
Modifies the payload in-place, prefixing any URL-type properties with the
|
|
1163
1177
|
client_endpoint if they don't already start with it.
|
|
1164
1178
|
"""
|
|
1165
1179
|
client_endpoint = self.client_endpoint
|
|
1166
|
-
|
|
1180
|
+
|
|
1167
1181
|
for key, value in payload.items():
|
|
1168
1182
|
try:
|
|
1169
1183
|
hal_property = None
|
|
@@ -1171,7 +1185,7 @@ class ContentGridApplicationClient(HALFormsClient):
|
|
|
1171
1185
|
if prop.name == key:
|
|
1172
1186
|
hal_property = prop
|
|
1173
1187
|
break
|
|
1174
|
-
|
|
1188
|
+
|
|
1175
1189
|
if hal_property and hal_property.type == HALFormsPropertyType.url:
|
|
1176
1190
|
if isinstance(value, list):
|
|
1177
1191
|
payload[key] = [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: contentgrid-application-client
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.11
|
|
4
4
|
Summary: Python Client for interacting with ContentGrid Applications
|
|
5
5
|
Author-email: Ranec Belpaire <ranec.belpaire@xenit.eu>
|
|
6
6
|
License: Copyright 2024 Xenit Solutions
|
|
@@ -16,13 +16,15 @@ License: Copyright 2024 Xenit Solutions
|
|
|
16
16
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
17
|
See the License for the specific language governing permissions and
|
|
18
18
|
limitations under the License.
|
|
19
|
+
Project-URL: Homepage, https://github.com/xenit-eu/contentgrid-python-client
|
|
20
|
+
Project-URL: Source, https://github.com/xenit-eu/contentgrid-python-client
|
|
19
21
|
Classifier: Development Status :: 4 - Beta
|
|
20
22
|
Classifier: Operating System :: OS Independent
|
|
21
23
|
Classifier: Programming Language :: Python :: 3
|
|
22
24
|
Requires-Python: >=3.5
|
|
23
25
|
Description-Content-Type: text/markdown
|
|
24
26
|
License-File: LICENSE
|
|
25
|
-
Requires-Dist: contentgrid-hal-client==0.2.
|
|
27
|
+
Requires-Dist: contentgrid-hal-client==0.2.11
|
|
26
28
|
Dynamic: license-file
|
|
27
29
|
Dynamic: requires-dist
|
|
28
30
|
|
contentgrid_application_client-0.2.11/src/contentgrid_application_client.egg-info/requires.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
contentgrid-hal-client==0.2.11
|
{contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_profile.py
RENAMED
|
@@ -61,7 +61,7 @@ def test_content_attribute_detection(cg_client: ContentGridApplicationClient):
|
|
|
61
61
|
entity_profile = cg_client.get_entity_profile(profile.get_entity_links()[0].name)
|
|
62
62
|
|
|
63
63
|
for attribute in entity_profile.get_attribute_profiles():
|
|
64
|
-
if attribute.is_content_attribute
|
|
64
|
+
if attribute.is_content_attribute:
|
|
65
65
|
nested_attrs = attribute.get_nested_attributes()
|
|
66
66
|
assert any(attr.name in ["length", "mimetype", "filename"] for attr in nested_attrs)
|
|
67
67
|
|
|
@@ -111,9 +111,9 @@ def test_load_profile_cache_with_dict(cg_client: ContentGridApplicationClient):
|
|
|
111
111
|
"name": "test-entity",
|
|
112
112
|
"description": "Test entity"
|
|
113
113
|
}
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
cg_client.load_profile_cache("/profile/test-entity", test_data)
|
|
116
|
-
|
|
116
|
+
|
|
117
117
|
# Verify it's in the cache
|
|
118
118
|
assert "/profile/test-entity" in cg_client.profile_cache
|
|
119
119
|
cached_data = cg_client.profile_cache["/profile/test-entity"]
|
|
@@ -129,9 +129,9 @@ def test_load_profile_cache_with_json_string(cg_client: ContentGridApplicationCl
|
|
|
129
129
|
"name": "test-entity2"
|
|
130
130
|
}
|
|
131
131
|
json_string = json.dumps(test_data)
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
cg_client.load_profile_cache("/profile/test-entity2", json_string)
|
|
134
|
-
|
|
134
|
+
|
|
135
135
|
# Verify it's in the cache
|
|
136
136
|
assert "/profile/test-entity2" in cg_client.profile_cache
|
|
137
137
|
cached_data = cg_client.profile_cache["/profile/test-entity2"]
|
|
@@ -142,65 +142,65 @@ def test_profile_cache_hit_returns_cached_response(cg_client: ContentGridApplica
|
|
|
142
142
|
# First request to populate cache
|
|
143
143
|
profile1 = cg_client.get_profile()
|
|
144
144
|
initial_cache_size = len(cg_client.profile_cache)
|
|
145
|
-
|
|
145
|
+
|
|
146
146
|
# Second request should use cache
|
|
147
147
|
profile2 = cg_client.get_profile()
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
# Cache size should not have increased
|
|
150
150
|
assert len(cg_client.profile_cache) == initial_cache_size
|
|
151
|
-
|
|
151
|
+
|
|
152
152
|
# Both profiles should have the same data
|
|
153
153
|
assert profile1.data == profile2.data
|
|
154
154
|
|
|
155
155
|
def test_profile_cache_only_affects_profile_endpoints(cg_client: ContentGridApplicationClient):
|
|
156
156
|
"""Test that cache only affects profile endpoints"""
|
|
157
157
|
initial_cache_size = len(cg_client.profile_cache)
|
|
158
|
-
|
|
158
|
+
|
|
159
159
|
# Get profile - should be cached
|
|
160
160
|
cg_client.get_profile()
|
|
161
|
-
|
|
161
|
+
|
|
162
162
|
# Cache should have grown
|
|
163
163
|
assert len(cg_client.profile_cache) > initial_cache_size
|
|
164
|
-
|
|
164
|
+
|
|
165
165
|
# Getting entity collection should not add to profile cache
|
|
166
166
|
profile = cg_client.get_profile()
|
|
167
167
|
if profile.get_entity_links():
|
|
168
168
|
entity_name = profile.get_entity_links()[0].name
|
|
169
169
|
entity_profile = cg_client.get_entity_profile(entity_name)
|
|
170
170
|
cache_size_after_entity_profile = len(cg_client.profile_cache)
|
|
171
|
-
|
|
171
|
+
|
|
172
172
|
# Getting the entity collection should not be cached
|
|
173
173
|
try:
|
|
174
174
|
cg_client.get_entity_collection(entity_name, size=1)
|
|
175
175
|
except Exception:
|
|
176
176
|
pass # We don't care if this fails, just testing cache behavior
|
|
177
|
-
|
|
177
|
+
|
|
178
178
|
# Profile cache size should not change from non-profile requests
|
|
179
179
|
assert len(cg_client.profile_cache) >= cache_size_after_entity_profile
|
|
180
180
|
|
|
181
181
|
def test_profile_cache_caches_entity_profiles(cg_client: ContentGridApplicationClient):
|
|
182
182
|
"""Test that entity profile requests are also cached"""
|
|
183
183
|
profile = cg_client.get_profile()
|
|
184
|
-
|
|
184
|
+
|
|
185
185
|
if not profile.get_entity_links():
|
|
186
186
|
pytest.skip("No entity profiles available to test caching")
|
|
187
|
-
|
|
187
|
+
|
|
188
188
|
entity_name = profile.get_entity_links()[0].name
|
|
189
189
|
initial_cache_size = len(cg_client.profile_cache)
|
|
190
|
-
|
|
190
|
+
|
|
191
191
|
# First request
|
|
192
192
|
entity_profile1 = cg_client.get_entity_profile(entity_name)
|
|
193
193
|
cache_size_after_first = len(cg_client.profile_cache)
|
|
194
|
-
|
|
194
|
+
|
|
195
195
|
# Cache should have grown (at least entity profile URL)
|
|
196
196
|
assert cache_size_after_first > initial_cache_size
|
|
197
|
-
|
|
197
|
+
|
|
198
198
|
# Second request - should hit cache
|
|
199
199
|
entity_profile2 = cg_client.get_entity_profile(entity_name)
|
|
200
|
-
|
|
200
|
+
|
|
201
201
|
# Cache size should not change
|
|
202
202
|
assert len(cg_client.profile_cache) == cache_size_after_first
|
|
203
|
-
|
|
203
|
+
|
|
204
204
|
# Data should be the same
|
|
205
205
|
assert entity_profile1.name == entity_profile2.name
|
|
206
206
|
|
|
@@ -208,7 +208,7 @@ def test_clear_empty_profile_cache(cg_client: ContentGridApplicationClient):
|
|
|
208
208
|
"""Test clearing an empty cache doesn't cause issues"""
|
|
209
209
|
# Clear empty cache
|
|
210
210
|
cg_client.clear_profile_cache()
|
|
211
|
-
|
|
211
|
+
|
|
212
212
|
# Verify cache is still empty
|
|
213
213
|
assert len(cg_client.profile_cache) == 0
|
|
214
214
|
assert cg_client.profile_cache == {}
|
|
@@ -218,16 +218,16 @@ def test_clear_profile_cache_removes_all_entries(cg_client: ContentGridApplicati
|
|
|
218
218
|
# Populate cache with some data
|
|
219
219
|
test_data1 = {"_links": {"self": {"href": "/profile/entity1"}}, "name": "entity1"}
|
|
220
220
|
test_data2 = {"_links": {"self": {"href": "/profile/entity2"}}, "name": "entity2"}
|
|
221
|
-
|
|
221
|
+
|
|
222
222
|
cg_client.load_profile_cache("/profile/entity1", test_data1)
|
|
223
223
|
cg_client.load_profile_cache("/profile/entity2", test_data2)
|
|
224
|
-
|
|
224
|
+
|
|
225
225
|
# Verify entries are in cache
|
|
226
226
|
assert len(cg_client.profile_cache) >= 2
|
|
227
|
-
|
|
227
|
+
|
|
228
228
|
# Clear cache
|
|
229
229
|
cg_client.clear_profile_cache()
|
|
230
|
-
|
|
230
|
+
|
|
231
231
|
# Verify cache is empty
|
|
232
232
|
assert len(cg_client.profile_cache) == 0
|
|
233
233
|
assert "/profile/entity1" not in cg_client.profile_cache
|
|
@@ -238,15 +238,15 @@ def test_clear_profile_cache_allows_repopulation(cg_client: ContentGridApplicati
|
|
|
238
238
|
# Populate cache
|
|
239
239
|
profile1 = cg_client.get_profile()
|
|
240
240
|
assert len(cg_client.profile_cache) > 0
|
|
241
|
-
|
|
241
|
+
|
|
242
242
|
# Clear cache
|
|
243
243
|
cg_client.clear_profile_cache()
|
|
244
244
|
assert len(cg_client.profile_cache) == 0
|
|
245
|
-
|
|
245
|
+
|
|
246
246
|
# Repopulate cache - should work normally
|
|
247
247
|
profile2 = cg_client.get_profile()
|
|
248
248
|
assert len(cg_client.profile_cache) > 0
|
|
249
|
-
|
|
249
|
+
|
|
250
250
|
# Data should be consistent
|
|
251
251
|
assert profile1.data == profile2.data
|
|
252
252
|
|
|
@@ -254,14 +254,14 @@ def test_clear_profile_cache_doesnt_affect_caching_flag(cg_client: ContentGridAp
|
|
|
254
254
|
"""Test that clearing cache doesn't disable caching"""
|
|
255
255
|
# Check caching is enabled
|
|
256
256
|
assert cg_client.use_profile_cache is True
|
|
257
|
-
|
|
257
|
+
|
|
258
258
|
# Load and clear cache
|
|
259
259
|
cg_client.load_profile_cache("/profile/test", {"name": "test"})
|
|
260
260
|
cg_client.clear_profile_cache()
|
|
261
|
-
|
|
261
|
+
|
|
262
262
|
# Caching should still be enabled
|
|
263
263
|
assert cg_client.use_profile_cache is True
|
|
264
|
-
|
|
264
|
+
|
|
265
265
|
# Cache should still work
|
|
266
266
|
cg_client.get_profile()
|
|
267
267
|
assert len(cg_client.profile_cache) > 0
|
|
@@ -272,14 +272,14 @@ def test_clear_profile_cache_forces_fresh_request(cg_client: ContentGridApplicat
|
|
|
272
272
|
cg_client.get_profile()
|
|
273
273
|
cache_size_after_first = len(cg_client.profile_cache)
|
|
274
274
|
assert cache_size_after_first > 0
|
|
275
|
-
|
|
275
|
+
|
|
276
276
|
# Clear cache
|
|
277
277
|
cg_client.clear_profile_cache()
|
|
278
278
|
assert len(cg_client.profile_cache) == 0
|
|
279
|
-
|
|
279
|
+
|
|
280
280
|
# Next request should repopulate cache (new request made)
|
|
281
281
|
cg_client.get_profile()
|
|
282
282
|
cache_size_after_clear = len(cg_client.profile_cache)
|
|
283
|
-
|
|
283
|
+
|
|
284
284
|
# Cache should be populated again
|
|
285
285
|
assert cache_size_after_clear > 0
|
contentgrid_application_client-0.2.9/src/contentgrid_application_client.egg-info/requires.txt
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
contentgrid-hal-client==0.2.9
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/requirements.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/fixtures.py
RENAMED
|
File without changes
|
|
File without changes
|
{contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_content.py
RENAMED
|
File without changes
|
{contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_curies.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_openapi.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{contentgrid_application_client-0.2.9 → contentgrid_application_client-0.2.11}/tests/test_search.py
RENAMED
|
File without changes
|