oplnk-python-utils 1.2.1__tar.gz → 1.2.2__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.
- {oplnk_python_utils-1.2.1/oplnk_python_utils.egg-info → oplnk_python_utils-1.2.2}/PKG-INFO +31 -11
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/README.md +30 -10
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/__init__.py +1 -1
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/query/query_builder.py +44 -47
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2/oplnk_python_utils.egg-info}/PKG-INFO +31 -11
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/setup.py +1 -1
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/LICENSE +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/MANIFEST.in +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/cache/__init__.py +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/cache/cache_utils.py +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/core/__init__.py +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/core/data.py +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/core/parsing.py +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/core/serialization.py +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/query/__init__.py +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/reports/__init__.py +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/SOURCES.txt +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/dependency_links.txt +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/not-zip-safe +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/requires.txt +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/top_level.txt +0 -0
- {oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oplnk-python-utils
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: Reusable utilities for caching, data manipulation, parsing, and MongoDB query building
|
|
5
5
|
Home-page: https://github.com/openlinkspa/oplnk-python-utils
|
|
6
6
|
Author: OpenLink SpA
|
|
@@ -664,42 +664,62 @@ These fields are only populated when explicitly requested via the `populate` par
|
|
|
664
664
|
|
|
665
665
|
### Populate Field Sanitization (v1.2.1)
|
|
666
666
|
|
|
667
|
-
|
|
667
|
+
The behavior of original ID fields depends on whether they are being populated:
|
|
668
|
+
|
|
669
|
+
#### Without populate - ID field shown as-is:
|
|
670
|
+
|
|
671
|
+
```python
|
|
672
|
+
# No populate - field shown normally
|
|
673
|
+
query = {
|
|
674
|
+
"fields": ["name", "establishment_id"]
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
# Response:
|
|
678
|
+
# {
|
|
679
|
+
# "data": [{
|
|
680
|
+
# "_id": "123",
|
|
681
|
+
# "name": "Product",
|
|
682
|
+
# "establishment_id": "est_123" // Shown normally
|
|
683
|
+
# }]
|
|
684
|
+
# }
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
#### With populate - ID field removed by default:
|
|
668
688
|
|
|
669
689
|
```python
|
|
670
|
-
#
|
|
690
|
+
# With populate but no explicit fields request
|
|
671
691
|
query = {
|
|
672
692
|
"populate": ["establishment"]
|
|
673
693
|
}
|
|
674
694
|
|
|
675
|
-
# Response - establishment_id
|
|
695
|
+
# Response - establishment_id automatically excluded:
|
|
676
696
|
# {
|
|
677
697
|
# "data": [{
|
|
678
698
|
# "_id": "123",
|
|
679
699
|
# "name": "Product",
|
|
680
|
-
# "establishment": { // Populated object
|
|
700
|
+
# "establishment": { // Populated object
|
|
681
701
|
# "_id": "est_123",
|
|
682
702
|
# "name": "Main Office"
|
|
683
703
|
# }
|
|
684
|
-
# // establishment_id is NOT here
|
|
685
704
|
# }]
|
|
686
705
|
# }
|
|
687
706
|
```
|
|
688
707
|
|
|
689
|
-
|
|
708
|
+
#### With populate AND explicit fields request - show both:
|
|
690
709
|
|
|
691
710
|
```python
|
|
711
|
+
# Request both populate and the original ID field explicitly
|
|
692
712
|
query = {
|
|
693
713
|
"populate": ["establishment"],
|
|
694
|
-
"fields": ["name", "establishment_id"] #
|
|
714
|
+
"fields": ["name", "establishment_id"] # Explicitly request the ID
|
|
695
715
|
}
|
|
696
716
|
|
|
697
|
-
# Response - both
|
|
717
|
+
# Response - both are present:
|
|
698
718
|
# {
|
|
699
719
|
# "data": [{
|
|
700
720
|
# "_id": "123",
|
|
701
721
|
# "name": "Product",
|
|
702
|
-
# "establishment_id": "est_123", //
|
|
722
|
+
# "establishment_id": "est_123", // Shown because explicitly requested
|
|
703
723
|
# "establishment": {
|
|
704
724
|
# "_id": "est_123",
|
|
705
725
|
# "name": "Main Office"
|
|
@@ -708,7 +728,7 @@ query = {
|
|
|
708
728
|
# }
|
|
709
729
|
```
|
|
710
730
|
|
|
711
|
-
**For audit fields:** The original ID is always excluded
|
|
731
|
+
**For audit fields:** The original ID is always excluded and never shown (no `creation_user_id` field exists to request).
|
|
712
732
|
|
|
713
733
|
### Custom Pipelines
|
|
714
734
|
|
|
@@ -622,42 +622,62 @@ These fields are only populated when explicitly requested via the `populate` par
|
|
|
622
622
|
|
|
623
623
|
### Populate Field Sanitization (v1.2.1)
|
|
624
624
|
|
|
625
|
-
|
|
625
|
+
The behavior of original ID fields depends on whether they are being populated:
|
|
626
|
+
|
|
627
|
+
#### Without populate - ID field shown as-is:
|
|
628
|
+
|
|
629
|
+
```python
|
|
630
|
+
# No populate - field shown normally
|
|
631
|
+
query = {
|
|
632
|
+
"fields": ["name", "establishment_id"]
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
# Response:
|
|
636
|
+
# {
|
|
637
|
+
# "data": [{
|
|
638
|
+
# "_id": "123",
|
|
639
|
+
# "name": "Product",
|
|
640
|
+
# "establishment_id": "est_123" // Shown normally
|
|
641
|
+
# }]
|
|
642
|
+
# }
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
#### With populate - ID field removed by default:
|
|
626
646
|
|
|
627
647
|
```python
|
|
628
|
-
#
|
|
648
|
+
# With populate but no explicit fields request
|
|
629
649
|
query = {
|
|
630
650
|
"populate": ["establishment"]
|
|
631
651
|
}
|
|
632
652
|
|
|
633
|
-
# Response - establishment_id
|
|
653
|
+
# Response - establishment_id automatically excluded:
|
|
634
654
|
# {
|
|
635
655
|
# "data": [{
|
|
636
656
|
# "_id": "123",
|
|
637
657
|
# "name": "Product",
|
|
638
|
-
# "establishment": { // Populated object
|
|
658
|
+
# "establishment": { // Populated object
|
|
639
659
|
# "_id": "est_123",
|
|
640
660
|
# "name": "Main Office"
|
|
641
661
|
# }
|
|
642
|
-
# // establishment_id is NOT here
|
|
643
662
|
# }]
|
|
644
663
|
# }
|
|
645
664
|
```
|
|
646
665
|
|
|
647
|
-
|
|
666
|
+
#### With populate AND explicit fields request - show both:
|
|
648
667
|
|
|
649
668
|
```python
|
|
669
|
+
# Request both populate and the original ID field explicitly
|
|
650
670
|
query = {
|
|
651
671
|
"populate": ["establishment"],
|
|
652
|
-
"fields": ["name", "establishment_id"] #
|
|
672
|
+
"fields": ["name", "establishment_id"] # Explicitly request the ID
|
|
653
673
|
}
|
|
654
674
|
|
|
655
|
-
# Response - both
|
|
675
|
+
# Response - both are present:
|
|
656
676
|
# {
|
|
657
677
|
# "data": [{
|
|
658
678
|
# "_id": "123",
|
|
659
679
|
# "name": "Product",
|
|
660
|
-
# "establishment_id": "est_123", //
|
|
680
|
+
# "establishment_id": "est_123", // Shown because explicitly requested
|
|
661
681
|
# "establishment": {
|
|
662
682
|
# "_id": "est_123",
|
|
663
683
|
# "name": "Main Office"
|
|
@@ -666,7 +686,7 @@ query = {
|
|
|
666
686
|
# }
|
|
667
687
|
```
|
|
668
688
|
|
|
669
|
-
**For audit fields:** The original ID is always excluded
|
|
689
|
+
**For audit fields:** The original ID is always excluded and never shown (no `creation_user_id` field exists to request).
|
|
670
690
|
|
|
671
691
|
### Custom Pipelines
|
|
672
692
|
|
{oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/query/query_builder.py
RENAMED
|
@@ -778,47 +778,46 @@ class QueryBuilder:
|
|
|
778
778
|
|
|
779
779
|
return pipeline_copy
|
|
780
780
|
|
|
781
|
-
def
|
|
781
|
+
def _get_populated_fields_list(self, query_populate: Any) -> List[str]:
|
|
782
782
|
"""
|
|
783
|
-
|
|
783
|
+
Get list of field names that are being populated.
|
|
784
784
|
|
|
785
|
-
For example:
|
|
785
|
+
For example: ["establishment", "creation_user"]
|
|
786
786
|
|
|
787
787
|
Args:
|
|
788
788
|
query_populate: The populate parameter (list or dict)
|
|
789
789
|
|
|
790
790
|
Returns:
|
|
791
|
-
|
|
791
|
+
List of field names being populated
|
|
792
792
|
"""
|
|
793
|
-
|
|
793
|
+
populated = []
|
|
794
794
|
|
|
795
795
|
if isinstance(query_populate, list):
|
|
796
|
-
|
|
797
|
-
if field in RESERVED_AUDIT_FIELDS:
|
|
798
|
-
# Audit fields: map to the temporary original field
|
|
799
|
-
mappings[field] = f"_original_{field}"
|
|
800
|
-
else:
|
|
801
|
-
# Normal relations: try to find the ID field
|
|
802
|
-
for relation in self.relations:
|
|
803
|
-
relation_name = relation[1]
|
|
804
|
-
# Remove _id or _ids suffix to get base name
|
|
805
|
-
base_name = relation_name.replace("_ids", "").replace("_id", "")
|
|
806
|
-
if base_name == field:
|
|
807
|
-
mappings[field] = relation_name
|
|
808
|
-
break
|
|
796
|
+
populated = query_populate
|
|
809
797
|
elif isinstance(query_populate, dict):
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
break
|
|
798
|
+
populated = list(query_populate.keys())
|
|
799
|
+
|
|
800
|
+
return populated
|
|
801
|
+
|
|
802
|
+
def _get_id_field_for_relation(self, relation_name: str) -> Optional[str]:
|
|
803
|
+
"""
|
|
804
|
+
Get the ID field name for a given relation.
|
|
805
|
+
|
|
806
|
+
For example: "establishment" -> "establishment_id"
|
|
820
807
|
|
|
821
|
-
|
|
808
|
+
Args:
|
|
809
|
+
relation_name: The relation name (e.g., "establishment")
|
|
810
|
+
|
|
811
|
+
Returns:
|
|
812
|
+
The ID field name (e.g., "establishment_id") or None if not found
|
|
813
|
+
"""
|
|
814
|
+
for relation in self.relations:
|
|
815
|
+
field_name = relation[1]
|
|
816
|
+
# Remove _id or _ids suffix to get base name
|
|
817
|
+
base_name = field_name.replace("_ids", "").replace("_id", "")
|
|
818
|
+
if base_name == relation_name:
|
|
819
|
+
return field_name
|
|
820
|
+
return None
|
|
822
821
|
|
|
823
822
|
def sanitize_result(
|
|
824
823
|
self, query: Dict[str, Any], data_result: Any, meta_result: Any
|
|
@@ -842,22 +841,26 @@ class QueryBuilder:
|
|
|
842
841
|
if not meta_result or "totalCount" not in meta_result:
|
|
843
842
|
meta_result = {"totalCount": 0}
|
|
844
843
|
|
|
845
|
-
# Sanitize populate fields: remove original ID fields when populated
|
|
844
|
+
# Sanitize populate fields: remove original ID fields when populated (unless requested in fields)
|
|
846
845
|
if "populate" in query and isinstance(data_result, list):
|
|
847
846
|
fields_requested = query.get("fields", [])
|
|
848
|
-
|
|
847
|
+
populated_fields = self._get_populated_fields_list(query["populate"])
|
|
849
848
|
|
|
850
849
|
for doc in data_result:
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
850
|
+
# Always remove temporary audit field copies
|
|
851
|
+
for field in RESERVED_AUDIT_FIELDS.keys():
|
|
852
|
+
temp_field = f"_original_{field}"
|
|
853
|
+
if temp_field in doc:
|
|
854
|
+
del doc[temp_field]
|
|
855
|
+
|
|
856
|
+
# For normal relations: remove original ID unless explicitly requested in fields
|
|
857
|
+
for populated_field in populated_fields:
|
|
858
|
+
if populated_field not in RESERVED_AUDIT_FIELDS:
|
|
859
|
+
# Try to find the ID field for this relation
|
|
860
|
+
id_field = self._get_id_field_for_relation(populated_field)
|
|
861
|
+
if id_field and id_field not in fields_requested:
|
|
862
|
+
if id_field in doc:
|
|
863
|
+
del doc[id_field]
|
|
861
864
|
|
|
862
865
|
return {"data": data_result, "meta": meta_result}
|
|
863
866
|
|
|
@@ -943,13 +946,7 @@ class QueryBuilder:
|
|
|
943
946
|
else:
|
|
944
947
|
let_value = {"lid": f"${relation_field_name}"}
|
|
945
948
|
|
|
946
|
-
# Save the original ID field before lookup (will be sanitized unless requested in fields)
|
|
947
949
|
lookup_relation = [
|
|
948
|
-
{
|
|
949
|
-
"$addFields": {
|
|
950
|
-
f"_original_{relation_field_name}": f"${relation_field_name}"
|
|
951
|
-
}
|
|
952
|
-
},
|
|
953
950
|
{
|
|
954
951
|
"$lookup": {
|
|
955
952
|
"from": f"{_prefix}{collection_name_relation}",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oplnk-python-utils
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: Reusable utilities for caching, data manipulation, parsing, and MongoDB query building
|
|
5
5
|
Home-page: https://github.com/openlinkspa/oplnk-python-utils
|
|
6
6
|
Author: OpenLink SpA
|
|
@@ -664,42 +664,62 @@ These fields are only populated when explicitly requested via the `populate` par
|
|
|
664
664
|
|
|
665
665
|
### Populate Field Sanitization (v1.2.1)
|
|
666
666
|
|
|
667
|
-
|
|
667
|
+
The behavior of original ID fields depends on whether they are being populated:
|
|
668
|
+
|
|
669
|
+
#### Without populate - ID field shown as-is:
|
|
670
|
+
|
|
671
|
+
```python
|
|
672
|
+
# No populate - field shown normally
|
|
673
|
+
query = {
|
|
674
|
+
"fields": ["name", "establishment_id"]
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
# Response:
|
|
678
|
+
# {
|
|
679
|
+
# "data": [{
|
|
680
|
+
# "_id": "123",
|
|
681
|
+
# "name": "Product",
|
|
682
|
+
# "establishment_id": "est_123" // Shown normally
|
|
683
|
+
# }]
|
|
684
|
+
# }
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
#### With populate - ID field removed by default:
|
|
668
688
|
|
|
669
689
|
```python
|
|
670
|
-
#
|
|
690
|
+
# With populate but no explicit fields request
|
|
671
691
|
query = {
|
|
672
692
|
"populate": ["establishment"]
|
|
673
693
|
}
|
|
674
694
|
|
|
675
|
-
# Response - establishment_id
|
|
695
|
+
# Response - establishment_id automatically excluded:
|
|
676
696
|
# {
|
|
677
697
|
# "data": [{
|
|
678
698
|
# "_id": "123",
|
|
679
699
|
# "name": "Product",
|
|
680
|
-
# "establishment": { // Populated object
|
|
700
|
+
# "establishment": { // Populated object
|
|
681
701
|
# "_id": "est_123",
|
|
682
702
|
# "name": "Main Office"
|
|
683
703
|
# }
|
|
684
|
-
# // establishment_id is NOT here
|
|
685
704
|
# }]
|
|
686
705
|
# }
|
|
687
706
|
```
|
|
688
707
|
|
|
689
|
-
|
|
708
|
+
#### With populate AND explicit fields request - show both:
|
|
690
709
|
|
|
691
710
|
```python
|
|
711
|
+
# Request both populate and the original ID field explicitly
|
|
692
712
|
query = {
|
|
693
713
|
"populate": ["establishment"],
|
|
694
|
-
"fields": ["name", "establishment_id"] #
|
|
714
|
+
"fields": ["name", "establishment_id"] # Explicitly request the ID
|
|
695
715
|
}
|
|
696
716
|
|
|
697
|
-
# Response - both
|
|
717
|
+
# Response - both are present:
|
|
698
718
|
# {
|
|
699
719
|
# "data": [{
|
|
700
720
|
# "_id": "123",
|
|
701
721
|
# "name": "Product",
|
|
702
|
-
# "establishment_id": "est_123", //
|
|
722
|
+
# "establishment_id": "est_123", // Shown because explicitly requested
|
|
703
723
|
# "establishment": {
|
|
704
724
|
# "_id": "est_123",
|
|
705
725
|
# "name": "Main Office"
|
|
@@ -708,7 +728,7 @@ query = {
|
|
|
708
728
|
# }
|
|
709
729
|
```
|
|
710
730
|
|
|
711
|
-
**For audit fields:** The original ID is always excluded
|
|
731
|
+
**For audit fields:** The original ID is always excluded and never shown (no `creation_user_id` field exists to request).
|
|
712
732
|
|
|
713
733
|
### Custom Pipelines
|
|
714
734
|
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="oplnk-python-utils",
|
|
5
|
-
version="1.2.
|
|
5
|
+
version="1.2.2",
|
|
6
6
|
author="OpenLink SpA",
|
|
7
7
|
author_email="contacto@openlink.cl",
|
|
8
8
|
description="Reusable utilities for caching, data manipulation, parsing, and MongoDB query building",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/cache/cache_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/core/serialization.py
RENAMED
|
File without changes
|
|
File without changes
|
{oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils/reports/__init__.py
RENAMED
|
File without changes
|
{oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/requires.txt
RENAMED
|
File without changes
|
{oplnk_python_utils-1.2.1 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|