hdx-python-api 6.6.7__py3-none-any.whl → 6.6.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 +2 -2
- hdx/data/resource.py +104 -0
- {hdx_python_api-6.6.7.dist-info → hdx_python_api-6.6.9.dist-info}/METADATA +5 -5
- {hdx_python_api-6.6.7.dist-info → hdx_python_api-6.6.9.dist-info}/RECORD +6 -6
- {hdx_python_api-6.6.7.dist-info → hdx_python_api-6.6.9.dist-info}/WHEEL +1 -1
- {hdx_python_api-6.6.7.dist-info → hdx_python_api-6.6.9.dist-info}/licenses/LICENSE +0 -0
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.6.
|
|
22
|
-
__version_tuple__ = version_tuple = (6, 6,
|
|
21
|
+
__version__ = version = '6.6.9'
|
|
22
|
+
__version_tuple__ = version_tuple = (6, 6, 9)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
hdx/data/resource.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Resource class containing all logic for creating, checking, and updating resources."""
|
|
2
2
|
|
|
3
|
+
import json
|
|
3
4
|
import logging
|
|
4
5
|
from collections.abc import Sequence
|
|
5
6
|
from datetime import datetime
|
|
@@ -33,6 +34,9 @@ class Resource(HDXObject):
|
|
|
33
34
|
"""
|
|
34
35
|
|
|
35
36
|
_formats_dict = None
|
|
37
|
+
_valid_data_dictionary_types = frozenset(
|
|
38
|
+
{"text", "numeric", "date", "timestamp without time zone"}
|
|
39
|
+
)
|
|
36
40
|
|
|
37
41
|
def __init__(
|
|
38
42
|
self,
|
|
@@ -62,6 +66,9 @@ class Resource(HDXObject):
|
|
|
62
66
|
"search": "resource_search",
|
|
63
67
|
"broken": "hdx_mark_broken_link_in_resource",
|
|
64
68
|
"datastore_delete": "datastore_delete",
|
|
69
|
+
"datastore_create": "datastore_create",
|
|
70
|
+
"datastore_insert": "datastore_insert",
|
|
71
|
+
"datastore_upsert": "datastore_upsert",
|
|
65
72
|
"datastore_search": "datastore_search",
|
|
66
73
|
}
|
|
67
74
|
|
|
@@ -260,6 +267,56 @@ class Resource(HDXObject):
|
|
|
260
267
|
self.data["format"] = file_format
|
|
261
268
|
return file_format
|
|
262
269
|
|
|
270
|
+
def get_hdx_data_dictionary(self) -> list[dict] | None:
|
|
271
|
+
"""Get the resource's data dictionary (column definitions)
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
List of column definition dictionaries or None if not set
|
|
275
|
+
"""
|
|
276
|
+
data_dictionary = self.data.get("hdx_data_dictionary")
|
|
277
|
+
if data_dictionary is None:
|
|
278
|
+
return None
|
|
279
|
+
if isinstance(data_dictionary, str):
|
|
280
|
+
return json.loads(data_dictionary)
|
|
281
|
+
return data_dictionary
|
|
282
|
+
|
|
283
|
+
def set_hdx_data_dictionary(self, data_dictionary: Sequence[dict]) -> None:
|
|
284
|
+
"""Set the resource's data dictionary (column definitions). Each column
|
|
285
|
+
definition must be a dict with non-empty string values for field
|
|
286
|
+
(column name in the CSV file), label (human-readable column label) and
|
|
287
|
+
description (human-readable description of the column). If present,
|
|
288
|
+
data_type must be one of the PostgreSQL types produced by DataPusher+
|
|
289
|
+
(text, numeric, date, timestamp without time zone).
|
|
290
|
+
|
|
291
|
+
Args:
|
|
292
|
+
data_dictionary: Sequence of column definition dictionaries
|
|
293
|
+
|
|
294
|
+
Returns:
|
|
295
|
+
None
|
|
296
|
+
"""
|
|
297
|
+
if not data_dictionary:
|
|
298
|
+
raise HDXError("hdx_data_dictionary must be a non-empty list!")
|
|
299
|
+
for i, column in enumerate(data_dictionary):
|
|
300
|
+
if not isinstance(column, dict):
|
|
301
|
+
raise HDXError(f"hdx_data_dictionary[{i}] must be a dict!")
|
|
302
|
+
for required_key in ("field", "label", "description"):
|
|
303
|
+
value = column.get(required_key)
|
|
304
|
+
if not isinstance(value, str) or not value.strip():
|
|
305
|
+
raise HDXError(
|
|
306
|
+
f"hdx_data_dictionary[{i}] is missing a non-empty '{required_key}'!"
|
|
307
|
+
)
|
|
308
|
+
if "data_type" in column:
|
|
309
|
+
data_type = column["data_type"]
|
|
310
|
+
if data_type not in self._valid_data_dictionary_types:
|
|
311
|
+
valid_types = ", ".join(sorted(self._valid_data_dictionary_types))
|
|
312
|
+
raise HDXError(
|
|
313
|
+
f"hdx_data_dictionary[{i}] has invalid 'data_type' "
|
|
314
|
+
f"'{data_type}'! Must be one of: {valid_types}"
|
|
315
|
+
)
|
|
316
|
+
self.data["hdx_data_dictionary"] = json.dumps(
|
|
317
|
+
data_dictionary, separators=(",", ":")
|
|
318
|
+
)
|
|
319
|
+
|
|
263
320
|
def clean_format(self) -> str:
|
|
264
321
|
"""Clean the resource's format, setting it to None if it is invalid and
|
|
265
322
|
cannot be mapped
|
|
@@ -701,6 +758,53 @@ class Resource(HDXObject):
|
|
|
701
758
|
return True
|
|
702
759
|
return False
|
|
703
760
|
|
|
761
|
+
def create_datastore(
|
|
762
|
+
self,
|
|
763
|
+
schema: Sequence[dict],
|
|
764
|
+
primary_key: str | Sequence[str] | None = None,
|
|
765
|
+
) -> None:
|
|
766
|
+
"""Create a datastore for the resource with the given schema.
|
|
767
|
+
|
|
768
|
+
Args:
|
|
769
|
+
schema: Sequence of field definitions, each a dict with 'id' and 'type' keys.
|
|
770
|
+
primary_key: Primary key field name(s). Defaults to None.
|
|
771
|
+
|
|
772
|
+
Returns:
|
|
773
|
+
None
|
|
774
|
+
"""
|
|
775
|
+
data: dict = {
|
|
776
|
+
"resource_id": self.data["id"],
|
|
777
|
+
"force": True,
|
|
778
|
+
"fields": schema,
|
|
779
|
+
}
|
|
780
|
+
if primary_key is not None:
|
|
781
|
+
if not isinstance(primary_key, str):
|
|
782
|
+
primary_key = ",".join(primary_key)
|
|
783
|
+
data["primary_key"] = primary_key
|
|
784
|
+
self._write_to_hdx("datastore_create", data, "resource_id")
|
|
785
|
+
|
|
786
|
+
def update_datastore(
|
|
787
|
+
self,
|
|
788
|
+
records: Sequence[dict],
|
|
789
|
+
method: str = "upsert",
|
|
790
|
+
) -> None:
|
|
791
|
+
"""Update (upsert) records into the resource datastore.
|
|
792
|
+
|
|
793
|
+
Args:
|
|
794
|
+
records: Sequence of record dicts to insert or update.
|
|
795
|
+
method: Datastore update method ('upsert', 'insert', or 'update'). Defaults to 'upsert'.
|
|
796
|
+
|
|
797
|
+
Returns:
|
|
798
|
+
None
|
|
799
|
+
"""
|
|
800
|
+
data = {
|
|
801
|
+
"resource_id": self.data["id"],
|
|
802
|
+
"force": True,
|
|
803
|
+
"method": method,
|
|
804
|
+
"records": records,
|
|
805
|
+
}
|
|
806
|
+
self._write_to_hdx("datastore_upsert", data, "resource_id")
|
|
807
|
+
|
|
704
808
|
def delete_datastore(self) -> None:
|
|
705
809
|
"""Delete a resource from the HDX datastore
|
|
706
810
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: hdx-python-api
|
|
3
|
-
Version: 6.6.
|
|
3
|
+
Version: 6.6.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
|
|
@@ -25,11 +25,11 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
25
25
|
Classifier: Programming Language :: Python :: 3.14
|
|
26
26
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
27
|
Requires-Python: >=3.10
|
|
28
|
-
Requires-Dist: ckanapi>=4.
|
|
28
|
+
Requires-Dist: ckanapi>=4.11
|
|
29
29
|
Requires-Dist: defopt>=7.0.0
|
|
30
30
|
Requires-Dist: email-validator
|
|
31
|
-
Requires-Dist: hdx-python-country>=4.1.
|
|
32
|
-
Requires-Dist: hdx-python-utilities>=4.
|
|
31
|
+
Requires-Dist: hdx-python-country>=4.1.3
|
|
32
|
+
Requires-Dist: hdx-python-utilities>=4.1.2
|
|
33
33
|
Requires-Dist: makefun
|
|
34
34
|
Requires-Dist: requests
|
|
35
35
|
Provides-Extra: docs
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
hdx/api/__init__.py,sha256=11ozJKiUsqDCZ3_mcAHhGYUyGK_Unl54djVSBBExFB4,59
|
|
2
|
-
hdx/api/_version.py,sha256=
|
|
2
|
+
hdx/api/_version.py,sha256=DZ0RWsb-nM4U2OMHNx7xq0IT_NuQKLA1g5wIx_XHwr4,520
|
|
3
3
|
hdx/api/configuration.py,sha256=9WvuVI-3th2Dv70_t_4VoyrlJwB_9qUSN5_zUKbp4sQ,23805
|
|
4
4
|
hdx/api/hdx_base_configuration.yaml,sha256=9yJYroZwoyMQo6tcxGfWHWvYahnTma7Szx0J5Z378z4,2173
|
|
5
5
|
hdx/api/locations.py,sha256=blnqOjEASvh0mWgmo2iEE7ES_xOuRwQo3fOMqTPV_P0,4139
|
|
@@ -14,7 +14,7 @@ hdx/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
14
14
|
hdx/data/dataset.py,sha256=0gS7tQSswTgG0g8YeXg0FL8pFVkocBQSRPFpQAurN00,99455
|
|
15
15
|
hdx/data/hdxobject.py,sha256=_jlwYjb_CcjaXsTXObknMfq-OiNOcpJfLJ9b1vKV1Zo,27494
|
|
16
16
|
hdx/data/organization.py,sha256=HGopFsCYOWrR7sUtZzZSXq6wLFw4djus2gzg6yNXOqc,12296
|
|
17
|
-
hdx/data/resource.py,sha256=
|
|
17
|
+
hdx/data/resource.py,sha256=SBAEou9Fj5sgpfoDmQ6j33W0srMMmhlsj00hiTuW86Y,38097
|
|
18
18
|
hdx/data/resource_matcher.py,sha256=Yzk9pWa4zk1p09m6zcZMj0XZf5Y16Pa3KToOdUt7rP8,4247
|
|
19
19
|
hdx/data/resource_view.py,sha256=GcYkh0iDAe6_m2ErY_A6i3Z7ZFX949eGt1TLnLZv_8s,7346
|
|
20
20
|
hdx/data/showcase.py,sha256=vnRZ45xd9Ct65eFQkWZtMIJPFifZfKOrH4obO5D5Pvc,14062
|
|
@@ -24,7 +24,7 @@ hdx/facades/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
24
24
|
hdx/facades/infer_arguments.py,sha256=DvyDuozfOPmoaV7HjhQySojGIrMWW9nos31auQBVVl8,4032
|
|
25
25
|
hdx/facades/keyword_arguments.py,sha256=aVapHCfqBO6H7xxBgTdK9ISdgrBFsNypPDWihfQ3edU,1125
|
|
26
26
|
hdx/facades/simple.py,sha256=QWsBkaHG_UM6X3Zu2u3LWVOQzeR24q-EUClrfsL_mkM,1064
|
|
27
|
-
hdx_python_api-6.6.
|
|
28
|
-
hdx_python_api-6.6.
|
|
29
|
-
hdx_python_api-6.6.
|
|
30
|
-
hdx_python_api-6.6.
|
|
27
|
+
hdx_python_api-6.6.9.dist-info/METADATA,sha256=H29ZAlNGFdS46-ucNToWqy68nIrHQkcjULochC1Ijao,4946
|
|
28
|
+
hdx_python_api-6.6.9.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
29
|
+
hdx_python_api-6.6.9.dist-info/licenses/LICENSE,sha256=wc-4GpMn-ODs-U_bTe1YCiPVgvcjzrpYOx2wPuyAeII,1079
|
|
30
|
+
hdx_python_api-6.6.9.dist-info/RECORD,,
|
|
File without changes
|