oplnk-python-utils 1.2.0__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.0/oplnk_python_utils.egg-info → oplnk_python_utils-1.2.2}/PKG-INFO +75 -7
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/README.md +74 -6
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils/__init__.py +1 -1
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils/query/query_builder.py +70 -2
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2/oplnk_python_utils.egg-info}/PKG-INFO +75 -7
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/setup.py +1 -1
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/LICENSE +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/MANIFEST.in +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils/cache/__init__.py +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils/cache/cache_utils.py +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils/core/__init__.py +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils/core/data.py +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils/core/parsing.py +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils/core/serialization.py +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils/query/__init__.py +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils/reports/__init__.py +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/SOURCES.txt +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/dependency_links.txt +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/not-zip-safe +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/requires.txt +0 -0
- {oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/top_level.txt +0 -0
- {oplnk_python_utils-1.2.0 → 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
|
|
@@ -623,7 +623,7 @@ relations = [
|
|
|
623
623
|
]
|
|
624
624
|
```
|
|
625
625
|
|
|
626
|
-
### Reserved Audit Fields (
|
|
626
|
+
### Reserved Audit Fields (v1.2.1)
|
|
627
627
|
|
|
628
628
|
The QueryBuilder automatically handles common audit fields without requiring manual configuration:
|
|
629
629
|
|
|
@@ -642,12 +642,11 @@ query = {
|
|
|
642
642
|
"populate": ["creation_user", "modification_user"]
|
|
643
643
|
}
|
|
644
644
|
|
|
645
|
-
# Result will include:
|
|
645
|
+
# Result will include (original ID automatically removed, replaced by populated object):
|
|
646
646
|
# {
|
|
647
647
|
# "data": [{
|
|
648
648
|
# "_id": "123",
|
|
649
|
-
# "creation_user":
|
|
650
|
-
# "creation_user_info": { // Automatically populated
|
|
649
|
+
# "creation_user": { // Replaces the original ID field
|
|
651
650
|
# "_id": "user_id_string",
|
|
652
651
|
# "name": "John Doe",
|
|
653
652
|
# "person": "person_id"
|
|
@@ -657,11 +656,80 @@ query = {
|
|
|
657
656
|
```
|
|
658
657
|
|
|
659
658
|
**Reserved fields:**
|
|
660
|
-
|
|
661
|
-
-
|
|
659
|
+
|
|
660
|
+
- `creation_user` → automatically populated, original ID is excluded
|
|
661
|
+
- `modification_user` → automatically populated, original ID is excluded
|
|
662
662
|
|
|
663
663
|
These fields are only populated when explicitly requested via the `populate` parameter, following the Strapi philosophy of on-demand loading.
|
|
664
664
|
|
|
665
|
+
### Populate Field Sanitization (v1.2.1)
|
|
666
|
+
|
|
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:
|
|
688
|
+
|
|
689
|
+
```python
|
|
690
|
+
# With populate but no explicit fields request
|
|
691
|
+
query = {
|
|
692
|
+
"populate": ["establishment"]
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
# Response - establishment_id automatically excluded:
|
|
696
|
+
# {
|
|
697
|
+
# "data": [{
|
|
698
|
+
# "_id": "123",
|
|
699
|
+
# "name": "Product",
|
|
700
|
+
# "establishment": { // Populated object
|
|
701
|
+
# "_id": "est_123",
|
|
702
|
+
# "name": "Main Office"
|
|
703
|
+
# }
|
|
704
|
+
# }]
|
|
705
|
+
# }
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
#### With populate AND explicit fields request - show both:
|
|
709
|
+
|
|
710
|
+
```python
|
|
711
|
+
# Request both populate and the original ID field explicitly
|
|
712
|
+
query = {
|
|
713
|
+
"populate": ["establishment"],
|
|
714
|
+
"fields": ["name", "establishment_id"] # Explicitly request the ID
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
# Response - both are present:
|
|
718
|
+
# {
|
|
719
|
+
# "data": [{
|
|
720
|
+
# "_id": "123",
|
|
721
|
+
# "name": "Product",
|
|
722
|
+
# "establishment_id": "est_123", // Shown because explicitly requested
|
|
723
|
+
# "establishment": {
|
|
724
|
+
# "_id": "est_123",
|
|
725
|
+
# "name": "Main Office"
|
|
726
|
+
# }
|
|
727
|
+
# }]
|
|
728
|
+
# }
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
**For audit fields:** The original ID is always excluded and never shown (no `creation_user_id` field exists to request).
|
|
732
|
+
|
|
665
733
|
### Custom Pipelines
|
|
666
734
|
|
|
667
735
|
```python
|
|
@@ -581,7 +581,7 @@ relations = [
|
|
|
581
581
|
]
|
|
582
582
|
```
|
|
583
583
|
|
|
584
|
-
### Reserved Audit Fields (
|
|
584
|
+
### Reserved Audit Fields (v1.2.1)
|
|
585
585
|
|
|
586
586
|
The QueryBuilder automatically handles common audit fields without requiring manual configuration:
|
|
587
587
|
|
|
@@ -600,12 +600,11 @@ query = {
|
|
|
600
600
|
"populate": ["creation_user", "modification_user"]
|
|
601
601
|
}
|
|
602
602
|
|
|
603
|
-
# Result will include:
|
|
603
|
+
# Result will include (original ID automatically removed, replaced by populated object):
|
|
604
604
|
# {
|
|
605
605
|
# "data": [{
|
|
606
606
|
# "_id": "123",
|
|
607
|
-
# "creation_user":
|
|
608
|
-
# "creation_user_info": { // Automatically populated
|
|
607
|
+
# "creation_user": { // Replaces the original ID field
|
|
609
608
|
# "_id": "user_id_string",
|
|
610
609
|
# "name": "John Doe",
|
|
611
610
|
# "person": "person_id"
|
|
@@ -615,11 +614,80 @@ query = {
|
|
|
615
614
|
```
|
|
616
615
|
|
|
617
616
|
**Reserved fields:**
|
|
618
|
-
|
|
619
|
-
-
|
|
617
|
+
|
|
618
|
+
- `creation_user` → automatically populated, original ID is excluded
|
|
619
|
+
- `modification_user` → automatically populated, original ID is excluded
|
|
620
620
|
|
|
621
621
|
These fields are only populated when explicitly requested via the `populate` parameter, following the Strapi philosophy of on-demand loading.
|
|
622
622
|
|
|
623
|
+
### Populate Field Sanitization (v1.2.1)
|
|
624
|
+
|
|
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:
|
|
646
|
+
|
|
647
|
+
```python
|
|
648
|
+
# With populate but no explicit fields request
|
|
649
|
+
query = {
|
|
650
|
+
"populate": ["establishment"]
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
# Response - establishment_id automatically excluded:
|
|
654
|
+
# {
|
|
655
|
+
# "data": [{
|
|
656
|
+
# "_id": "123",
|
|
657
|
+
# "name": "Product",
|
|
658
|
+
# "establishment": { // Populated object
|
|
659
|
+
# "_id": "est_123",
|
|
660
|
+
# "name": "Main Office"
|
|
661
|
+
# }
|
|
662
|
+
# }]
|
|
663
|
+
# }
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
#### With populate AND explicit fields request - show both:
|
|
667
|
+
|
|
668
|
+
```python
|
|
669
|
+
# Request both populate and the original ID field explicitly
|
|
670
|
+
query = {
|
|
671
|
+
"populate": ["establishment"],
|
|
672
|
+
"fields": ["name", "establishment_id"] # Explicitly request the ID
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
# Response - both are present:
|
|
676
|
+
# {
|
|
677
|
+
# "data": [{
|
|
678
|
+
# "_id": "123",
|
|
679
|
+
# "name": "Product",
|
|
680
|
+
# "establishment_id": "est_123", // Shown because explicitly requested
|
|
681
|
+
# "establishment": {
|
|
682
|
+
# "_id": "est_123",
|
|
683
|
+
# "name": "Main Office"
|
|
684
|
+
# }
|
|
685
|
+
# }]
|
|
686
|
+
# }
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
**For audit fields:** The original ID is always excluded and never shown (no `creation_user_id` field exists to request).
|
|
690
|
+
|
|
623
691
|
### Custom Pipelines
|
|
624
692
|
|
|
625
693
|
```python
|
{oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils/query/query_builder.py
RENAMED
|
@@ -21,7 +21,7 @@ RESERVED_AUDIT_FIELDS = {
|
|
|
21
21
|
"creation_user": {
|
|
22
22
|
"collection": "users",
|
|
23
23
|
"field_name": "creation_user",
|
|
24
|
-
"alias": "
|
|
24
|
+
"alias": "creation_user",
|
|
25
25
|
"field_type": "id",
|
|
26
26
|
"project_exclude": {
|
|
27
27
|
"role": 0,
|
|
@@ -49,7 +49,7 @@ RESERVED_AUDIT_FIELDS = {
|
|
|
49
49
|
"modification_user": {
|
|
50
50
|
"collection": "users",
|
|
51
51
|
"field_name": "modification_user",
|
|
52
|
-
"alias": "
|
|
52
|
+
"alias": "modification_user",
|
|
53
53
|
"field_type": "id",
|
|
54
54
|
"project_exclude": {
|
|
55
55
|
"role": 0,
|
|
@@ -778,6 +778,47 @@ class QueryBuilder:
|
|
|
778
778
|
|
|
779
779
|
return pipeline_copy
|
|
780
780
|
|
|
781
|
+
def _get_populated_fields_list(self, query_populate: Any) -> List[str]:
|
|
782
|
+
"""
|
|
783
|
+
Get list of field names that are being populated.
|
|
784
|
+
|
|
785
|
+
For example: ["establishment", "creation_user"]
|
|
786
|
+
|
|
787
|
+
Args:
|
|
788
|
+
query_populate: The populate parameter (list or dict)
|
|
789
|
+
|
|
790
|
+
Returns:
|
|
791
|
+
List of field names being populated
|
|
792
|
+
"""
|
|
793
|
+
populated = []
|
|
794
|
+
|
|
795
|
+
if isinstance(query_populate, list):
|
|
796
|
+
populated = query_populate
|
|
797
|
+
elif isinstance(query_populate, dict):
|
|
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"
|
|
807
|
+
|
|
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
|
|
821
|
+
|
|
781
822
|
def sanitize_result(
|
|
782
823
|
self, query: Dict[str, Any], data_result: Any, meta_result: Any
|
|
783
824
|
) -> Dict[str, Any]:
|
|
@@ -800,6 +841,27 @@ class QueryBuilder:
|
|
|
800
841
|
if not meta_result or "totalCount" not in meta_result:
|
|
801
842
|
meta_result = {"totalCount": 0}
|
|
802
843
|
|
|
844
|
+
# Sanitize populate fields: remove original ID fields when populated (unless requested in fields)
|
|
845
|
+
if "populate" in query and isinstance(data_result, list):
|
|
846
|
+
fields_requested = query.get("fields", [])
|
|
847
|
+
populated_fields = self._get_populated_fields_list(query["populate"])
|
|
848
|
+
|
|
849
|
+
for doc in data_result:
|
|
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]
|
|
864
|
+
|
|
803
865
|
return {"data": data_result, "meta": meta_result}
|
|
804
866
|
|
|
805
867
|
def get_reserved_field_lookup(self, field_name: str) -> List[Dict[str, Any]]:
|
|
@@ -821,6 +883,12 @@ class QueryBuilder:
|
|
|
821
883
|
field_config = RESERVED_AUDIT_FIELDS[field_name]
|
|
822
884
|
|
|
823
885
|
lookup_pipeline = [
|
|
886
|
+
# Save the original ID before lookup (will be removed during sanitization)
|
|
887
|
+
{
|
|
888
|
+
"$addFields": {
|
|
889
|
+
f"_original_{field_config['field_name']}": f"${field_config['field_name']}"
|
|
890
|
+
}
|
|
891
|
+
},
|
|
824
892
|
{
|
|
825
893
|
"$lookup": {
|
|
826
894
|
"from": field_config["collection"],
|
|
@@ -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
|
|
@@ -623,7 +623,7 @@ relations = [
|
|
|
623
623
|
]
|
|
624
624
|
```
|
|
625
625
|
|
|
626
|
-
### Reserved Audit Fields (
|
|
626
|
+
### Reserved Audit Fields (v1.2.1)
|
|
627
627
|
|
|
628
628
|
The QueryBuilder automatically handles common audit fields without requiring manual configuration:
|
|
629
629
|
|
|
@@ -642,12 +642,11 @@ query = {
|
|
|
642
642
|
"populate": ["creation_user", "modification_user"]
|
|
643
643
|
}
|
|
644
644
|
|
|
645
|
-
# Result will include:
|
|
645
|
+
# Result will include (original ID automatically removed, replaced by populated object):
|
|
646
646
|
# {
|
|
647
647
|
# "data": [{
|
|
648
648
|
# "_id": "123",
|
|
649
|
-
# "creation_user":
|
|
650
|
-
# "creation_user_info": { // Automatically populated
|
|
649
|
+
# "creation_user": { // Replaces the original ID field
|
|
651
650
|
# "_id": "user_id_string",
|
|
652
651
|
# "name": "John Doe",
|
|
653
652
|
# "person": "person_id"
|
|
@@ -657,11 +656,80 @@ query = {
|
|
|
657
656
|
```
|
|
658
657
|
|
|
659
658
|
**Reserved fields:**
|
|
660
|
-
|
|
661
|
-
-
|
|
659
|
+
|
|
660
|
+
- `creation_user` → automatically populated, original ID is excluded
|
|
661
|
+
- `modification_user` → automatically populated, original ID is excluded
|
|
662
662
|
|
|
663
663
|
These fields are only populated when explicitly requested via the `populate` parameter, following the Strapi philosophy of on-demand loading.
|
|
664
664
|
|
|
665
|
+
### Populate Field Sanitization (v1.2.1)
|
|
666
|
+
|
|
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:
|
|
688
|
+
|
|
689
|
+
```python
|
|
690
|
+
# With populate but no explicit fields request
|
|
691
|
+
query = {
|
|
692
|
+
"populate": ["establishment"]
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
# Response - establishment_id automatically excluded:
|
|
696
|
+
# {
|
|
697
|
+
# "data": [{
|
|
698
|
+
# "_id": "123",
|
|
699
|
+
# "name": "Product",
|
|
700
|
+
# "establishment": { // Populated object
|
|
701
|
+
# "_id": "est_123",
|
|
702
|
+
# "name": "Main Office"
|
|
703
|
+
# }
|
|
704
|
+
# }]
|
|
705
|
+
# }
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
#### With populate AND explicit fields request - show both:
|
|
709
|
+
|
|
710
|
+
```python
|
|
711
|
+
# Request both populate and the original ID field explicitly
|
|
712
|
+
query = {
|
|
713
|
+
"populate": ["establishment"],
|
|
714
|
+
"fields": ["name", "establishment_id"] # Explicitly request the ID
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
# Response - both are present:
|
|
718
|
+
# {
|
|
719
|
+
# "data": [{
|
|
720
|
+
# "_id": "123",
|
|
721
|
+
# "name": "Product",
|
|
722
|
+
# "establishment_id": "est_123", // Shown because explicitly requested
|
|
723
|
+
# "establishment": {
|
|
724
|
+
# "_id": "est_123",
|
|
725
|
+
# "name": "Main Office"
|
|
726
|
+
# }
|
|
727
|
+
# }]
|
|
728
|
+
# }
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
**For audit fields:** The original ID is always excluded and never shown (no `creation_user_id` field exists to request).
|
|
732
|
+
|
|
665
733
|
### Custom Pipelines
|
|
666
734
|
|
|
667
735
|
```python
|
|
@@ -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.0 → 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.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils/core/serialization.py
RENAMED
|
File without changes
|
|
File without changes
|
{oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils/reports/__init__.py
RENAMED
|
File without changes
|
{oplnk_python_utils-1.2.0 → 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.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/requires.txt
RENAMED
|
File without changes
|
{oplnk_python_utils-1.2.0 → oplnk_python_utils-1.2.2}/oplnk_python_utils.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|