hdx-python-api 6.7.8__py3-none-any.whl → 6.7.9__py3-none-any.whl

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.
hdx/api/_version.py CHANGED
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '6.7.8'
22
- __version_tuple__ = version_tuple = (6, 7, 8)
21
+ __version__ = version = '6.7.9'
22
+ __version_tuple__ = version_tuple = (6, 7, 9)
23
23
 
24
24
  __commit_id__ = commit_id = None
hdx/data/dataset.py CHANGED
@@ -667,21 +667,90 @@ class Dataset(HDXObject):
667
667
  if "batch_mode" not in kwargs:
668
668
  kwargs["batch_mode"] = "DONT_GROUP"
669
669
 
670
+ def _merge_list_fields(self, dataset_data_to_update: dict) -> list[str]:
671
+ """Merges each non-resource list in dataset_data_to_update with the
672
+ existing list of the same key (see _merge_list) in place.
673
+
674
+ Args:
675
+ dataset_data_to_update: Dataset data to be updated
676
+
677
+ Returns:
678
+ Keys whose merged list differs from the existing one
679
+ """
680
+ changed_keys = []
681
+ for key, value in dataset_data_to_update.items():
682
+ if (
683
+ key == "resources"
684
+ or not isinstance(value, list)
685
+ or key not in self._old_data
686
+ ):
687
+ continue
688
+ orig_list = self._old_data[key]
689
+ if not isinstance(orig_list, list):
690
+ orig_list = []
691
+ merged_list = self._merge_list(orig_list, value)
692
+ dataset_data_to_update[key] = merged_list
693
+ if merged_list != orig_list:
694
+ changed_keys.append(key)
695
+ return changed_keys
696
+
697
+ @staticmethod
698
+ def _merge_list(orig_list: list, new_list: list) -> list:
699
+ """Merges each dict in new_list that has an id or name with the dict in
700
+ orig_list with the same id (or failing that, name) so that fields not
701
+ given in new_list are kept. Other elements of new_list are kept as is.
702
+ Elements of orig_list that are not matched are dropped.
703
+
704
+ Args:
705
+ orig_list: Existing list
706
+ new_list: Updated list
707
+
708
+ Returns:
709
+ Merged list
710
+ """
711
+ merged_list = []
712
+ for new_value in new_list:
713
+ if not isinstance(new_value, dict):
714
+ merged_list.append(new_value)
715
+ continue
716
+ match = {}
717
+ for field in ("id", "name"):
718
+ field_value = new_value.get(field)
719
+ if not field_value:
720
+ continue
721
+ match = next(
722
+ (
723
+ orig_value
724
+ for orig_value in orig_list
725
+ if isinstance(orig_value, dict)
726
+ and orig_value.get(field) == field_value
727
+ ),
728
+ {},
729
+ )
730
+ if match:
731
+ break
732
+ merged_list.append(match | new_value)
733
+ return merged_list
734
+
670
735
  def _revise_filter(
671
736
  self,
672
- dataset_data_to_update: dict,
673
737
  keys_to_delete: Sequence[str],
674
738
  resources_to_delete: Sequence[int],
675
- ):
739
+ changed_list_keys: Sequence[str],
740
+ ) -> list[str]:
676
741
  """Returns the revise filter parameter adding to it any keys in the
677
- dataset metadata and resources that are specified to be deleted. Also compare
678
- lists in original and updated metadata to see if any have had elements
679
- removed in which case these should be added to the filter
742
+ dataset metadata and resources that are specified to be deleted. Keys
743
+ of changed lists are also added so that package_revise replaces those
744
+ lists rather than merging them by position (which keeps the existing
745
+ elements' ids eg. for groups).
680
746
 
681
747
  Args:
682
- dataset_data_to_update: Dataset data to be updated
683
748
  keys_to_delete: List of top level metadata keys to delete
684
749
  resources_to_delete: List of indexes of resources to delete
750
+ changed_list_keys: Keys of lists that differ from the existing ones
751
+
752
+ Returns:
753
+ Revise filter
685
754
  """
686
755
  revise_filter = []
687
756
  for key in keys_to_delete:
@@ -689,46 +758,9 @@ class Dataset(HDXObject):
689
758
  if not self.is_requestable():
690
759
  for resource_index in resources_to_delete:
691
760
  revise_filter.append(f"-resources__{resource_index}")
692
- for key, value in dataset_data_to_update.items():
693
- if not isinstance(value, list):
694
- continue
695
- if key not in self._old_data:
696
- continue
697
- orig_list = self._old_data[key]
698
- elements_to_remove = []
699
- for i, orig_value in enumerate(orig_list):
700
- if isinstance(orig_value, dict) and any(
701
- x in orig_value for x in ("id", "name")
702
- ):
703
- # Where lists have an id or name, we use one of those to
704
- # match elements and work out what needs to be deleted
705
- # ie. any elements in the original list that don't exist
706
- # in the updated list
707
- el_id = orig_value.get("id")
708
- el_name = orig_value.get("name")
709
- present = False
710
- for value_dict in value:
711
- if el_id and "id" in value_dict and value_dict["id"] == el_id:
712
- present = True
713
- break
714
- if (
715
- el_name
716
- and "name" in value_dict
717
- and value_dict["name"] == el_name
718
- ):
719
- present = True
720
- break
721
- if not present:
722
- elements_to_remove.append(i)
723
- elif orig_value not in value:
724
- # Otherwise we do a simple exact match of list elements
725
- # and delete any elements that are in the original list but
726
- # not in the updated list
727
- elements_to_remove.append(i)
728
- for element_index in reversed(elements_to_remove):
729
- del orig_list[element_index]
730
- if element_index == len(orig_list):
731
- revise_filter.append(f"-{key}__{element_index}")
761
+ for key in changed_list_keys:
762
+ if key not in keys_to_delete:
763
+ revise_filter.append(f"-{key}")
732
764
  return revise_filter
733
765
 
734
766
  def _revise_files_to_upload_resource_deletions(
@@ -806,8 +838,9 @@ class Dataset(HDXObject):
806
838
  ): # Whether or not CKAN should perform validation steps (checking fields present)
807
839
  dataset_data_to_update["skip_validation"] = kwargs["skip_validation"]
808
840
  dataset_data_to_update["state"] = "active"
841
+ changed_list_keys = self._merge_list_fields(dataset_data_to_update)
809
842
  revise_filter = self._revise_filter(
810
- dataset_data_to_update, keys_to_delete, resources_to_delete
843
+ keys_to_delete, resources_to_delete, changed_list_keys
811
844
  )
812
845
  files_to_upload = self._revise_files_to_upload_resource_deletions(
813
846
  resources_to_update,
@@ -1048,8 +1081,8 @@ class Dataset(HDXObject):
1048
1081
  **kwargs,
1049
1082
  )
1050
1083
  keep_crisis_tags = kwargs.get("keep_crisis_tags", True)
1051
- if keep_crisis_tags:
1052
- old_tags = self._old_data.get("tags", [])
1084
+ if keep_crisis_tags and "tags" in self._old_data:
1085
+ old_tags = self._old_data["tags"]
1053
1086
  for tag in self.data.get("tags", []):
1054
1087
  tag_name = tag["name"]
1055
1088
  if tag_name[:7] != "crisis-":
@@ -1061,7 +1094,6 @@ class Dataset(HDXObject):
1061
1094
  break
1062
1095
  if not found:
1063
1096
  old_tags.append(tag)
1064
- self._old_data["tags"] = old_tags
1065
1097
  self._prepare_hdx_call(self._old_data, kwargs)
1066
1098
  revise_call = self._revise_dataset(
1067
1099
  allow_no_resources,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: hdx-python-api
3
- Version: 6.7.8
3
+ Version: 6.7.9
4
4
  Summary: HDX Python API for interacting with the Humanitarian Data Exchange
5
5
  Project-URL: Homepage, https://github.com/OCHA-DAP/hdx-python-api
6
6
  Author: Michael Rans
@@ -27,8 +27,8 @@ Requires-Python: >=3.11
27
27
  Requires-Dist: ckanapi>=4.11
28
28
  Requires-Dist: defopt>=7.0.0
29
29
  Requires-Dist: email-validator
30
- Requires-Dist: hdx-python-country>=4.2.6
31
- Requires-Dist: hdx-python-utilities>=4.2.6
30
+ Requires-Dist: hdx-python-country>=4.3.1
31
+ Requires-Dist: hdx-python-utilities>=4.2.7
32
32
  Requires-Dist: makefun
33
33
  Requires-Dist: requests
34
34
  Provides-Extra: docs
@@ -1,5 +1,5 @@
1
1
  hdx/api/__init__.py,sha256=11ozJKiUsqDCZ3_mcAHhGYUyGK_Unl54djVSBBExFB4,59
2
- hdx/api/_version.py,sha256=mfER4mocGyfEDcrh-EPSwFbbBfh6B41aVSJ98S98M9U,520
2
+ hdx/api/_version.py,sha256=mqZBEZ3sW4hFzYhXwQAxPeU7oI9pRVlb2fo16Eapuxc,520
3
3
  hdx/api/configuration.py,sha256=40DTsYVCe1tQ5IVQPFdhW83CemzkEXMjNBk6WVeUkj8,23802
4
4
  hdx/api/hdx_base_configuration.yaml,sha256=jj2t5b7NnI499rHVwOjj3Q5BAjE8i7NDGVKnWZ5P5-4,2222
5
5
  hdx/api/locations.py,sha256=bFl_cKz_AEQzkE_xWOkrRlUQ0GT2LMPSk-G_LsbV-Ns,4099
@@ -13,7 +13,7 @@ hdx/api/utilities/hdx_stats.py,sha256=JlEcF9LN-OjcVeh6C0te-nAlcO7W-JIpD5JJWTiWxs
13
13
  hdx/api/utilities/url_utils.py,sha256=Pb4r-BAqIHYmeoB_i7QjutDp6nOAUh_OHvCtiNLda3Y,4534
14
14
  hdx/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  hdx/data/activity.py,sha256=YNa7hAgsMP96EIUX7UMInxAXnJ8TynE1KpecRrv8Vso,9200
16
- hdx/data/dataset.py,sha256=ze9fSvPGpg0zAS9yTuTHpqhsGdny8CSqsHmrsfccvrY,105723
16
+ hdx/data/dataset.py,sha256=wbo2ShjXjelZcLm4I8V9wx-RDf_lXf2FsUjH-74VvWU,106379
17
17
  hdx/data/hdxobject.py,sha256=SCrnmOhBtP-6-1EdKzjgV4u0aclTzDhA4QghsaQ0qN4,28379
18
18
  hdx/data/location.py,sha256=eEdHZGEYKa9qRDyYqGTwAh22TB4XBkcTu47Mz39fmEs,11171
19
19
  hdx/data/organization.py,sha256=T2lITJXEYDN5t8dYkfcQTe-x0joULTtgp3Vn9JeVh-k,13133
@@ -27,7 +27,7 @@ hdx/facades/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  hdx/facades/infer_arguments.py,sha256=3Z5vPPkni0Cgg9cUb7wDF_8TxeX1TiiffcnGqyahtiY,4015
28
28
  hdx/facades/keyword_arguments.py,sha256=aVapHCfqBO6H7xxBgTdK9ISdgrBFsNypPDWihfQ3edU,1125
29
29
  hdx/facades/simple.py,sha256=QWsBkaHG_UM6X3Zu2u3LWVOQzeR24q-EUClrfsL_mkM,1064
30
- hdx_python_api-6.7.8.dist-info/METADATA,sha256=A3h4HM4h438MTxH4dnLkqWPrK9Dyw0w59rqkd2aDNOQ,4895
31
- hdx_python_api-6.7.8.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
32
- hdx_python_api-6.7.8.dist-info/licenses/LICENSE,sha256=wc-4GpMn-ODs-U_bTe1YCiPVgvcjzrpYOx2wPuyAeII,1079
33
- hdx_python_api-6.7.8.dist-info/RECORD,,
30
+ hdx_python_api-6.7.9.dist-info/METADATA,sha256=640fkpkJHrkSRiYLy1UUP9hJ-jxQgEWMz-GIB8U5Dr0,4895
31
+ hdx_python_api-6.7.9.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
32
+ hdx_python_api-6.7.9.dist-info/licenses/LICENSE,sha256=wc-4GpMn-ODs-U_bTe1YCiPVgvcjzrpYOx2wPuyAeII,1079
33
+ hdx_python_api-6.7.9.dist-info/RECORD,,