hdx-python-api 6.7.6__tar.gz → 6.7.7__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.
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/.gitignore +3 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/CLAUDE.md +1 -1
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/PKG-INFO +4 -5
- hdx_python_api-6.7.7/documentation/explanation/facades.md +14 -0
- hdx_python_api-6.7.7/documentation/explanation/history.md +18 -0
- hdx_python_api-6.7.7/documentation/explanation/information.md +11 -0
- hdx_python_api-6.7.7/documentation/how-to/activity-streams.md +33 -0
- hdx_python_api-6.7.7/documentation/how-to/api-key.md +24 -0
- hdx_python_api-6.7.7/documentation/how-to/customisation.md +60 -0
- hdx_python_api-6.7.7/documentation/how-to/docker.md +6 -0
- hdx_python_api-6.7.7/documentation/how-to/facades.md +42 -0
- hdx_python_api-6.7.7/documentation/how-to/framework.md +57 -0
- hdx_python_api-6.7.7/documentation/how-to/idmc-example.md +14 -0
- hdx_python_api-6.7.7/documentation/how-to/install.md +18 -0
- hdx_python_api-6.7.7/documentation/how-to/locations.md +52 -0
- hdx_python_api-6.7.7/documentation/how-to/logging.md +26 -0
- hdx_python_api-6.7.7/documentation/how-to/objects.md +102 -0
- hdx_python_api-6.7.7/documentation/how-to/operate-datasets/dataset-resources.md +109 -0
- hdx_python_api-6.7.7/documentation/how-to/operate-datasets/location.md +41 -0
- hdx_python_api-6.7.7/documentation/how-to/operate-datasets/maintainer.md +13 -0
- hdx_python_api-6.7.7/documentation/how-to/operate-datasets/organization.md +14 -0
- hdx_python_api-6.7.7/documentation/how-to/operate-datasets/resource-generation.md +57 -0
- hdx_python_api-6.7.7/documentation/how-to/operate-datasets/tags.md +24 -0
- hdx_python_api-6.7.7/documentation/how-to/operate-datasets/time-period.md +31 -0
- hdx_python_api-6.7.7/documentation/how-to/operate-datasets/update-frequency.md +41 -0
- hdx_python_api-6.7.7/documentation/how-to/operate-datasets/visualization.md +14 -0
- hdx_python_api-6.7.7/documentation/how-to/operate-resources/data-dictionary.md +47 -0
- hdx_python_api-6.7.7/documentation/how-to/operate-resources/datastore.md +74 -0
- hdx_python_api-6.7.7/documentation/how-to/operate-resources/resource-operations.md +98 -0
- hdx_python_api-6.7.7/documentation/how-to/organizations.md +31 -0
- hdx_python_api-6.7.7/documentation/how-to/pipeline-state.md +43 -0
- hdx_python_api-6.7.7/documentation/how-to/showcases.md +30 -0
- hdx_python_api-6.7.7/documentation/how-to/statistics.md +21 -0
- hdx_python_api-6.7.7/documentation/how-to/users.md +40 -0
- hdx_python_api-6.7.7/documentation/how-to/vocabularies.md +21 -0
- hdx_python_api-6.7.7/documentation/how-to/working-examples.md +7 -0
- hdx_python_api-6.7.7/documentation/index.md +64 -0
- hdx_python_api-6.7.7/documentation/mkdocs.yaml +71 -0
- hdx_python_api-6.7.7/documentation/reference/changelog.md +73 -0
- hdx_python_api-6.7.7/documentation/tutorials/getting-started.md +133 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/pyproject.toml +4 -5
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/api/_version.py +2 -2
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/api/utilities/date_helper.py +5 -5
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/api/utilities/test_hdx_state.py +3 -3
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_dataset_noncore.py +9 -9
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_dataset_resource_generation.py +7 -9
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_resource.py +5 -5
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/uv.lock +54 -748
- hdx_python_api-6.7.6/documentation/index.md +0 -1524
- hdx_python_api-6.7.6/documentation/mkdocs.yaml +0 -25
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/.github/workflows/publish.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/.github/workflows/run-python-tests.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/.pre-commit-config.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/LICENSE +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/README.md +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/documentation/.readthedocs.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/api/__init__.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/api/configuration.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/api/hdx_base_configuration.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/api/locations.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/api/remotehdx.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/api/utilities/__init__.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/api/utilities/filestore_helper.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/api/utilities/hdx_error_handler.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/api/utilities/hdx_state.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/api/utilities/hdx_stats.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/api/utilities/url_utils.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/data/__init__.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/data/activity.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/data/dataset.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/data/hdxobject.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/data/location.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/data/organization.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/data/resource.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/data/resource_matcher.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/data/resource_view.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/data/showcase.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/data/user.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/data/vocabulary.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/facades/__init__.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/facades/infer_arguments.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/facades/keyword_arguments.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/src/hdx/facades/simple.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/__init__.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/Accepted_Tags.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/CKAN/hdx_dataset_static.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/Tag_Mapping.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/Tag_Mapping_ChainRuleError.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/empty.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_base_config.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_base_config.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_config.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_config.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_dataset_static.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_dataset_static.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_datasource_topline.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_datasource_topline.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_email_configuration.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_email_configuration.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_missing_site_config.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_organization_static.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_organization_static.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_resource_static.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_resource_static.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_resource_view_static.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_resource_view_static.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_showcase_static.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_showcase_static.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_user_static.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_user_static.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_vocabulary_static.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/hdx_vocabulary_static.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/project_configuration.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/project_configuration.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/user_agent_config.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/user_agent_config2.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/user_agent_config3.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/config/user_agent_config_wrong.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/dataset_search_results.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/download_gen_resource/conflict_data_alg.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/download_gen_resource/min_qc_conflict_data_alg.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/download_gen_resource/qc_conflict_data_alg.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/download_gen_resource/test_data_no_data.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/download_gen_resource/test_data_no_years.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/empty.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/gen_resource/conflict_data_alg.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/gen_resource/min_qc_conflict_data_alg.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/gen_resource/qc_conflict_data_alg.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/gen_resource/test_data_no_data.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/gen_resource/test_data_no_years.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/location/location_list_all_fields.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/location/location_show_results.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/organization/organization_list_all_fields.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/organization/organization_show_results.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/qc_from_rows/qc_conflict_data_alg.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/qc_from_rows/qc_conflict_data_alg_one_col.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/resource_formats.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/showcase_all_search_results.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/size_hash/ACLED-All-Africa-File_20170101-to-20170708.xlsx +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/state/analysis_dates.txt +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/state/last_build_date.txt +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/test_data.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/test_data.zip +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_dataset_resources/dem_data_zwe.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_dataset_resources/dem_indicatorlist_zwe.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_dataset_resources/expected_resources_to_update.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_dataset_resources/opri_data_zwe.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_dataset_resources/opri_indicatorlist_zwe.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_dataset_resources/opri_metadata_zwe.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_dataset_resources/qc_sdg_data_zwe.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_dataset_resources/sdg_data_zwe.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_dataset_resources/sdg_indicatorlist_zwe.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_dataset_resources/sdg_metadata_zwe.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_dataset_resources/unesco_dataset.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_dataset_resources/unesco_update_dataset.json +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_logic/update_logic_resources.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/fixtures/update_logic/update_logic_resources_new.yaml +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/__init__.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/api/__init__.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/api/test_ckan.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/api/test_configuration.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/api/test_locations.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/api/utilities/__init__.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/api/utilities/test_filestore_helper.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/api/utilities/test_hdx_error_handler.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/api/utilities/test_hdx_stats.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/api/utilities/test_url_utils.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/conftest.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/__init__.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_activity.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_dataset_add_hapi_error.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_dataset_core.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_location.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_organization.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_resource_view.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_showcase.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_update_dataset_resources.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_update_logic.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_user.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/data/test_vocabulary.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/facades/__init__.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/facades/test_infer_arguments.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/facades/test_keyword_arguments.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/tests/hdx/facades/test_simple.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/workingexample/my_code.py +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/workingexample/my_resource.csv +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/workingexample/my_resource.xlsx +0 -0
- {hdx_python_api-6.7.6 → hdx_python_api-6.7.7}/workingexample/run.py +0 -0
|
@@ -33,7 +33,7 @@ Formatted and linted with `ruff` (rules: E, F, I, UP; line-length not enforced).
|
|
|
33
33
|
pre-commit run --all-files
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
- Python ≥ 3.
|
|
36
|
+
- Python ≥ 3.11
|
|
37
37
|
- Type hints throughout; use `X | Y` union syntax (PEP 604), not `Optional`/`Union`
|
|
38
38
|
- Google-style docstrings with `Args:` and `Returns:` sections
|
|
39
39
|
- No inline comments unless the *why* is non-obvious
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: hdx-python-api
|
|
3
|
-
Version: 6.7.
|
|
3
|
+
Version: 6.7.7
|
|
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
|
|
@@ -18,18 +18,17 @@ Classifier: Operating System :: Unix
|
|
|
18
18
|
Classifier: Programming Language :: Python
|
|
19
19
|
Classifier: Programming Language :: Python :: 3
|
|
20
20
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
22
21
|
Classifier: Programming Language :: Python :: 3.11
|
|
23
22
|
Classifier: Programming Language :: Python :: 3.12
|
|
24
23
|
Classifier: Programming Language :: Python :: 3.13
|
|
25
24
|
Classifier: Programming Language :: Python :: 3.14
|
|
26
25
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
|
-
Requires-Python: >=3.
|
|
26
|
+
Requires-Python: >=3.11
|
|
28
27
|
Requires-Dist: ckanapi>=4.11
|
|
29
28
|
Requires-Dist: defopt>=7.0.0
|
|
30
29
|
Requires-Dist: email-validator
|
|
31
|
-
Requires-Dist: hdx-python-country>=4.2.
|
|
32
|
-
Requires-Dist: hdx-python-utilities>=4.2.
|
|
30
|
+
Requires-Dist: hdx-python-country>=4.2.6
|
|
31
|
+
Requires-Dist: hdx-python-utilities>=4.2.5
|
|
33
32
|
Requires-Dist: makefun
|
|
34
33
|
Requires-Dist: requests
|
|
35
34
|
Provides-Extra: docs
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Default Configuration for Facades
|
|
2
|
+
|
|
3
|
+
The easiest way to get started is to use the facades and configuration defaults. The
|
|
4
|
+
facades set up both logging and HDX configuration.
|
|
5
|
+
|
|
6
|
+
The default configuration loads an internal HDX configuration located within the
|
|
7
|
+
library, and assumes that there is an API key file called **.hdxkey** in the current
|
|
8
|
+
user's home directory **\~** and a YAML project configuration located relative to your
|
|
9
|
+
working directory at **config/project_configuration.yaml** which you must create. The
|
|
10
|
+
project configuration is used for any configuration specific to your project.
|
|
11
|
+
|
|
12
|
+
The default logging configuration reads a configuration file internal to the library
|
|
13
|
+
that sets up an coloured console handler outputting at INFO level and a file handler
|
|
14
|
+
writing to errors.log at ERROR level.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Brief History
|
|
2
|
+
|
|
3
|
+
The first iteration of a scraper for ACLED was written without the HDX Python library
|
|
4
|
+
and it became clear looking at this and previous work by others that there are operations
|
|
5
|
+
that are frequently required and which add unnecessary complexity to the task of coding
|
|
6
|
+
against HDX. Simplifying the interface to HDX drove the development of the Python
|
|
7
|
+
library and the second iteration of the scraper was built using it. ACLED went from
|
|
8
|
+
producing files to creating an API, so a third iteration was developed.
|
|
9
|
+
|
|
10
|
+
With the interface using HDX terminology and mapping directly on to datasets, resources
|
|
11
|
+
and showcases, the ACLED scraper was faster to develop and was much easier to understand
|
|
12
|
+
for someone inexperienced in how it works and what it is doing. The extensive logging
|
|
13
|
+
and transparent communication of errors is invaluable and enables action to be taken to
|
|
14
|
+
resolve issues as quickly as possible. Static metadata can be held in human readable
|
|
15
|
+
files so if it needs to be modified, it is straightforward.
|
|
16
|
+
|
|
17
|
+
The HDX Python library has expanded over time as needs have arisen and is used for a
|
|
18
|
+
range of tasks involving interaction with the HDX platform.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Information
|
|
2
|
+
|
|
3
|
+
For more about the purpose and design philosophy, please visit
|
|
4
|
+
[HDX Python Library](https://humanitarian.atlassian.net/wiki/display/HDX/HDX+Python+Library).
|
|
5
|
+
|
|
6
|
+
This library is part of the [Humanitarian Data Exchange](https://data.humdata.org/)
|
|
7
|
+
(HDX) project. If you have humanitarian related data, please upload your datasets to
|
|
8
|
+
HDX.
|
|
9
|
+
|
|
10
|
+
The code for the library is [here](https://github.com/OCHA-DAP/hdx-python-api).
|
|
11
|
+
The library has detailed API documentation which can be found in the menu at the top.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Use Activity Streams
|
|
2
|
+
|
|
3
|
+
The **Activity** class wraps CKAN activities, which record who changed what and when.
|
|
4
|
+
Activities are read only. You can get the activity stream of a dataset, organization,
|
|
5
|
+
location or user:
|
|
6
|
+
|
|
7
|
+
activities = dataset.get_activities(**kwargs)
|
|
8
|
+
activities = organization.get_activities(**kwargs)
|
|
9
|
+
activities = location.get_activities(**kwargs)
|
|
10
|
+
activities = user.get_activities(**kwargs)
|
|
11
|
+
|
|
12
|
+
These return a list of **Activity** objects, each with fields like `timestamp`,
|
|
13
|
+
`user_id`, `object_id` and `activity_type` (eg. "changed package"). One page of results
|
|
14
|
+
is returned. Its size is set by `limit` (default 31, HDX maximum 100) and where it starts
|
|
15
|
+
by `offset`. Passing `all_pages=True` gets every page. Other arguments (`**kwargs`) like
|
|
16
|
+
`after`, `before` and `activity_types` depend on the object type and are detailed in the
|
|
17
|
+
API documentation. Getting a user's activity stream requires authorisation to view the
|
|
18
|
+
user's profile.
|
|
19
|
+
|
|
20
|
+
You can get the activity stream of all recently added or changed datasets:
|
|
21
|
+
|
|
22
|
+
activities = Activity.get_recently_changed_packages(limit=10)
|
|
23
|
+
|
|
24
|
+
With `all_pages=True`, this stream covers the whole history of HDX so it is capped by
|
|
25
|
+
`max_activities` (default 1000). Pass `max_activities=None` to remove the cap.
|
|
26
|
+
|
|
27
|
+
You can read a single activity, get its data (including a snapshot of the object at the
|
|
28
|
+
time of the activity) or get a diff against the object's previous version. HDX requires
|
|
29
|
+
permission to edit the object the activity relates to for these:
|
|
30
|
+
|
|
31
|
+
activity = Activity.read_from_hdx("ACTIVITY_ID")
|
|
32
|
+
data = activity.get_data()
|
|
33
|
+
diff = activity.get_diff(diff_type="unified") # or "context" or "html"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Obtain your API Key
|
|
2
|
+
|
|
3
|
+
If you just want to read data from HDX, then an API key is not necessary and you can
|
|
4
|
+
ignore the 6 steps below. However, if you want to write data to HDX, then you need to
|
|
5
|
+
register on the website to obtain an API key. You can supply this key as an argument or
|
|
6
|
+
create an API key file. If you create an API key file, by default this is assumed to be
|
|
7
|
+
called **.hdxkey** and is located in the current user's home directory **\~**. Assuming
|
|
8
|
+
you are using a desktop browser, the API key is obtained by:
|
|
9
|
+
|
|
10
|
+
1. Browse to the [HDX website](https://data.humdata.org/)
|
|
11
|
+
2. Left click on LOG IN in the top right of the web page if not logged in and log in
|
|
12
|
+
3. Left click on your username in the top right of the web page and select PROFILE from
|
|
13
|
+
the drop down menu
|
|
14
|
+
4. Scroll down to the bottom of the profile page
|
|
15
|
+
5. Copy the API key which will be of the form: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
16
|
+
6. You can either:
|
|
17
|
+
|
|
18
|
+
a. Pass this key as a parameter or within a dictionary
|
|
19
|
+
|
|
20
|
+
b. Create a JSON or YAML file. The default path is
|
|
21
|
+
**.hdx_configuration.yaml** in the current user's home
|
|
22
|
+
directory. Then put in the YAML file:
|
|
23
|
+
|
|
24
|
+
hdx_key: "HDX API KEY"
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Customise the Configuration
|
|
2
|
+
|
|
3
|
+
It is necessary to pass configuration parameters in the facade call eg.
|
|
4
|
+
|
|
5
|
+
facade(main, user_agent=USER_AGENT, hdx_site = HDX_SITE_TO_USE, hdx_read_only = ONLY_READ_NOT_WRITE, hdx_key_file = LOCATION_OF_HDX_KEY_FILE, hdx_config_yaml=PATH_TO_HDX_YAML_CONFIGURATION, project_config_dict = {"MY_PARAMETER", "MY_VALUE"})
|
|
6
|
+
|
|
7
|
+
If you do not use the facade, you can use the **create** method of the **Configuration** class directly, passing in
|
|
8
|
+
appropriate keyword arguments ie.
|
|
9
|
+
|
|
10
|
+
from hdx.api.configuration import Configuration
|
|
11
|
+
...
|
|
12
|
+
Configuration.create([configuration], [user_agent], [user_agent_config_yaml], [remoteckan], KEYWORD ARGUMENTS)
|
|
13
|
+
|
|
14
|
+
You must supply a user agent using one of the following approaches:
|
|
15
|
+
|
|
16
|
+
1. Populate parameter **user_agent** (which should be the name of your
|
|
17
|
+
organisation and project)
|
|
18
|
+
2. Supply **user_agent_config_yaml** which should point to a YAML file which
|
|
19
|
+
contains a parameter **user_agent**
|
|
20
|
+
3. Supply **user_agent_config_yaml** which should point to a YAML file and populate
|
|
21
|
+
**user_agent_lookup** which is a key to look up in the YAML file which should
|
|
22
|
+
be of form:
|
|
23
|
+
|
|
24
|
+
myproject:
|
|
25
|
+
user_agent: test
|
|
26
|
+
myproject2:
|
|
27
|
+
user_agent: test2
|
|
28
|
+
|
|
29
|
+
4. Include **user_agent** in one of the configuration dictionaries or files outlined in
|
|
30
|
+
the table below eg.
|
|
31
|
+
**hdx_config_json** or **project_config_dict**.
|
|
32
|
+
|
|
33
|
+
**KEYWORD ARGUMENTS** can be:
|
|
34
|
+
|
|
35
|
+
|Choose|Argument|Type|Value|Default|
|
|
36
|
+
|---|---|---|---|---|
|
|
37
|
+
| |hdx_site|Optional\[str\]|HDX site to use eg. prod, feature|test|
|
|
38
|
+
| |hdx_read_only|bool|Read only or read/write access to HDX|False|
|
|
39
|
+
| |hdx_key|Optional\[str\]|HDX key (not needed for read only)||
|
|
40
|
+
|Above or one of:|hdx_config_dict|dict|Dictionary with hdx_site, hdx_read_only, hdx_key||
|
|
41
|
+
|or|hdx_config_json|str|Path to JSON configuration with values as above||
|
|
42
|
+
|or|hdx_config_yaml|str|Path to YAML configuration with values as above||
|
|
43
|
+
|Zero or one of:|project_config_dict|dict|Project specific configuration dictionary||
|
|
44
|
+
|or|project_config_json|str|Path to JSON Project||
|
|
45
|
+
|
|
46
|
+
To access the configuration, you use the **read** method of the **Configuration** class as follows:
|
|
47
|
+
|
|
48
|
+
Configuration.read()
|
|
49
|
+
|
|
50
|
+
For more advanced users, there are methods to allow you to pass in your own
|
|
51
|
+
configuration object, remote CKAN object and list of valid locations. See the API
|
|
52
|
+
documentation for more information.
|
|
53
|
+
|
|
54
|
+
This global configuration is used by default by the library but can be replaced by
|
|
55
|
+
Configuration instances passed to the constructors of HDX objects like Dataset eg.
|
|
56
|
+
|
|
57
|
+
configuration = Configuration(KEYWORD ARGUMENTS)
|
|
58
|
+
configuration.setup_remoteckan(REMOTE CKAN OBJECT)
|
|
59
|
+
configuration.setup_validlocations(LIST OF VALID LOCATIONS)
|
|
60
|
+
dataset = Dataset(configuration=configuration)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Use Facades
|
|
2
|
+
|
|
3
|
+
The simple facade makes it easier to get up and running:
|
|
4
|
+
|
|
5
|
+
from hdx.facades.simple import facade
|
|
6
|
+
|
|
7
|
+
def main():
|
|
8
|
+
***YOUR CODE HERE***
|
|
9
|
+
|
|
10
|
+
if __name__ == "__main__":
|
|
11
|
+
facade(main, CONFIGURATION_KWARGS)
|
|
12
|
+
|
|
13
|
+
The keyword arguments facade is similar but passes through keyword arguments:
|
|
14
|
+
|
|
15
|
+
from hdx.facades.keyword_arguments import facade
|
|
16
|
+
|
|
17
|
+
def main(kwparam1, kwparam2, ...,**ignore):
|
|
18
|
+
***YOUR CODE HERE***
|
|
19
|
+
|
|
20
|
+
if __name__ == "__main__":
|
|
21
|
+
facade(main, CONFIGURATION_AND_OTHER_KWARGS)
|
|
22
|
+
|
|
23
|
+
The infer arguments facade infers the possible command line from the type hints and
|
|
24
|
+
docstring describing the parameters of the function you give (such as main). It is
|
|
25
|
+
possible to pass additional parameters to the facade which will be overridden by any
|
|
26
|
+
parameters provided on the command line with the same name.
|
|
27
|
+
|
|
28
|
+
from hdx.facades.infer_arguments import facade
|
|
29
|
+
|
|
30
|
+
def main(kwparam1: bool, kwparam2: str):
|
|
31
|
+
"""Generate dataset and create it in HDX
|
|
32
|
+
Args:
|
|
33
|
+
kwparam1 (bool): Help text for this command line argument
|
|
34
|
+
kwparam2 (str): Help text for this command line argument
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
None
|
|
38
|
+
"""
|
|
39
|
+
***YOUR CODE HERE***
|
|
40
|
+
|
|
41
|
+
if __name__ == "__main__":
|
|
42
|
+
facade(main, kwparam3="lala")
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Build a project Framework
|
|
2
|
+
|
|
3
|
+
Once you understand how to create a dataset on HDX, it is important to think
|
|
4
|
+
about a good structure. Below is framework for starting a project to interact
|
|
5
|
+
with HDX that should work well.
|
|
6
|
+
|
|
7
|
+
First, pip install the library or alternatively add it to a requirements.txt
|
|
8
|
+
file if you are comfortable with doing so as described in [Install the Library](install.md).
|
|
9
|
+
|
|
10
|
+
Next create a file called **run.py** and copy into it the code below.
|
|
11
|
+
|
|
12
|
+
#!/usr/bin/python
|
|
13
|
+
# -*- coding: utf-8 -*-
|
|
14
|
+
"""
|
|
15
|
+
Calls a function that generates a dataset and creates it in HDX.
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
import logging
|
|
19
|
+
from hdx.facades.simple import facade
|
|
20
|
+
from .my_code import generate_dataset
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def main():
|
|
26
|
+
"""Generate dataset and create it in HDX"""
|
|
27
|
+
|
|
28
|
+
dataset = generate_dataset()
|
|
29
|
+
dataset.create_in_hdx()
|
|
30
|
+
|
|
31
|
+
if __name__ == "__main__":
|
|
32
|
+
facade(main, hdx_site="test")
|
|
33
|
+
|
|
34
|
+
The above file will create in HDX a dataset generated by a function called
|
|
35
|
+
**generate_dataset** that can be found in the file **my_code.py** which we will now
|
|
36
|
+
write.
|
|
37
|
+
|
|
38
|
+
Create a file **my_code.py** and copy into it the code below:
|
|
39
|
+
|
|
40
|
+
#!/usr/bin/python
|
|
41
|
+
# -*- coding: utf-8 -*-
|
|
42
|
+
"""
|
|
43
|
+
Generate a dataset
|
|
44
|
+
|
|
45
|
+
"""
|
|
46
|
+
import logging
|
|
47
|
+
from hdx.data.dataset import Dataset
|
|
48
|
+
|
|
49
|
+
logger = logging.getLogger(__name__)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def generate_dataset():
|
|
53
|
+
"""Create a dataset
|
|
54
|
+
"""
|
|
55
|
+
logger.debug("Generating dataset!")
|
|
56
|
+
|
|
57
|
+
You can then fill out the function **generate_dataset** as required.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# IDMC Example
|
|
2
|
+
|
|
3
|
+
A complete example can be found here: <https://github.com/OCHA-DAP/hdx-scraper-idmc>
|
|
4
|
+
|
|
5
|
+
The IDMC scraper creates a dataset per country in HDX, populating all the
|
|
6
|
+
required metadata. It then creates resources with files held on the HDX
|
|
7
|
+
filestore.
|
|
8
|
+
|
|
9
|
+
In particular, take a look at the files **run.py**, **idmc.py** and the
|
|
10
|
+
**config** folder. Do not run it unchanged as it may overwrite the existing
|
|
11
|
+
datasets in the IDMC organisation (although it will most probably fail as you
|
|
12
|
+
will not have permissions to modify anything in that organisation). You can use
|
|
13
|
+
it as a basis for your code renaming and modifying **idmc.py** as needed and
|
|
14
|
+
updating metadata in **config/hdx_dataset_static.yaml** appropriately.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Install the Library
|
|
2
|
+
|
|
3
|
+
To include the HDX Python library in your project, you must **pip install** or add to
|
|
4
|
+
your **requirements.txt** file the following line:
|
|
5
|
+
|
|
6
|
+
hdx-python-api==VERSION
|
|
7
|
+
|
|
8
|
+
Replace **VERSION** with the latest tag available from
|
|
9
|
+
<https://github.com/OCHA-DAP/hdx-python-api/tags>.
|
|
10
|
+
|
|
11
|
+
If you get dependency errors, it is probably the dependencies of the cryptography
|
|
12
|
+
package that are missing eg. for Ubuntu: python-dev, libffi-dev and libssl-dev. See
|
|
13
|
+
[cryptography dependencies](https://cryptography.io/en/latest/installation/#building-cryptography-on-linux).
|
|
14
|
+
|
|
15
|
+
If you get import or other errors, then please either recreate your virtualenv if you
|
|
16
|
+
are using one or uninstall hdx-python-api, hdx-python-country and hdx-python-utilities
|
|
17
|
+
using **pip uninstall**, then install hdx-python-api (which will pull in the other
|
|
18
|
+
dependencies).
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Manage Locations
|
|
2
|
+
|
|
3
|
+
The **Location** class wraps HDX locations (CKAN groups eg. countries, "world"). Reading
|
|
4
|
+
locations does not require any special permissions, so these are the operations you will
|
|
5
|
+
typically use. Creating, updating and deleting locations is restricted to HDX sysadmins
|
|
6
|
+
and works the same way as for other HDX objects (see
|
|
7
|
+
[Use HDX Objects](objects.md)).
|
|
8
|
+
|
|
9
|
+
You can read a single location:
|
|
10
|
+
|
|
11
|
+
location = Location.read_from_hdx("LOCATION_ID_OR_NAME")
|
|
12
|
+
|
|
13
|
+
You can get all location names in HDX:
|
|
14
|
+
|
|
15
|
+
location_names = Location.get_all_location_names(**kwargs)
|
|
16
|
+
|
|
17
|
+
Passing `all_fields=True` (plus optionally `include_extras=True` etc.) returns the full
|
|
18
|
+
location dictionaries instead of just names. Various additional arguments (`**kwargs`)
|
|
19
|
+
can be supplied and are detailed in the API documentation.
|
|
20
|
+
|
|
21
|
+
You can fetch the countries that are currently active on HDX's Data Grid (a live lookup,
|
|
22
|
+
since Data Grid membership changes over time, rather than a fixed list):
|
|
23
|
+
|
|
24
|
+
country_codes = Location.get_data_grid_countries()
|
|
25
|
+
|
|
26
|
+
This returns a sorted list of 3-letter location codes.
|
|
27
|
+
|
|
28
|
+
HDX sysadmins can get the Data Grid of a country and clear HDX's cached copy of
|
|
29
|
+
it:
|
|
30
|
+
|
|
31
|
+
data_grid = Location.get_data_grid("AFG")
|
|
32
|
+
Location.invalidate_data_grid("AFG")
|
|
33
|
+
|
|
34
|
+
**get_data_grid** returns a dictionary with keys including `title`, `date`,
|
|
35
|
+
`stats` and `categories` (or None if not found). Each category has
|
|
36
|
+
`subcategories`, each with a list of `datasets`. Complementary datasets have
|
|
37
|
+
`is_complementary` set to True.
|
|
38
|
+
|
|
39
|
+
You can get the datasets belonging to a location as follows:
|
|
40
|
+
|
|
41
|
+
datasets = location.get_datasets(**kwargs)
|
|
42
|
+
|
|
43
|
+
Various additional arguments (`**kwargs`) can be supplied. These are detailed in the API
|
|
44
|
+
documentation.
|
|
45
|
+
|
|
46
|
+
You can autocomplete a location name:
|
|
47
|
+
|
|
48
|
+
matches = Location.autocomplete("NAME")
|
|
49
|
+
|
|
50
|
+
For simple name/code lookups against a cached list of valid locations (eg. converting
|
|
51
|
+
between a country name and its HDX code) rather than the full **Location** object, see
|
|
52
|
+
the **Locations** helper class instead.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Configure Logging
|
|
2
|
+
|
|
3
|
+
If you use a facade from **hdx.facades**, then logging will go to console and errors to
|
|
4
|
+
file. If you are not using a facade, you can call **setup_logging** which takes
|
|
5
|
+
an argument error_file which is False by default. If set to True, errors will be written
|
|
6
|
+
to a file.
|
|
7
|
+
|
|
8
|
+
If not using facade:
|
|
9
|
+
|
|
10
|
+
from hdx.utilities.easy_logging import setup_logging
|
|
11
|
+
...
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
setup_logging(console_log_level="DEBUG", log_file="output.log",
|
|
14
|
+
file_log_level="INFO")
|
|
15
|
+
|
|
16
|
+
To use logging in your files, simply add the line below to the top of each Python file:
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
Then use the logger like this:
|
|
21
|
+
|
|
22
|
+
logger.debug("DEBUG message")
|
|
23
|
+
logger.info("INFORMATION message")
|
|
24
|
+
logger.warning("WARNING message")
|
|
25
|
+
logger.error("ERROR message")
|
|
26
|
+
logger.critical("CRITICAL error message")
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Use HDX Objects
|
|
2
|
+
|
|
3
|
+
You can read an existing HDX object with the static **read_from_hdx** method
|
|
4
|
+
which takes an identifier parameter and returns the an object of the appropriate HDX
|
|
5
|
+
object type eg. **Dataset** or **None** depending upon whether the object was read eg.
|
|
6
|
+
|
|
7
|
+
dataset = Dataset.read_from_hdx("DATASET_ID_OR_NAME")
|
|
8
|
+
|
|
9
|
+
You can search for datasets and resources in HDX using the **search_in_hdx** method
|
|
10
|
+
which takes a query parameter and returns the a list of objects of the appropriate HDX
|
|
11
|
+
object type eg. **list[Dataset]**. Here is an example:
|
|
12
|
+
|
|
13
|
+
datasets = Dataset.search_in_hdx("QUERY", **kwargs)
|
|
14
|
+
|
|
15
|
+
The query parameter takes a different format depending upon whether it is for a
|
|
16
|
+
[dataset](https://docs.ckan.org/en/latest/api/index.html#ckan.logic.action.get.package_search)
|
|
17
|
+
or a
|
|
18
|
+
[resource](https://docs.ckan.org/en/latest/api/index.html#ckan.logic.action.get.resource_search).
|
|
19
|
+
The resource level search is limited to fields in the resource, so in most cases, it is
|
|
20
|
+
preferable to search for datasets and then get their resources.
|
|
21
|
+
|
|
22
|
+
Various additional arguments (`**kwargs`) can be supplied. These are detailed in the API
|
|
23
|
+
documentation. The rows parameter for datasets (limit for resources) is the maximum
|
|
24
|
+
number of matches returned and is by default everything.
|
|
25
|
+
|
|
26
|
+
You can create an HDX Object, such as a dataset, resource, showcase, organization or
|
|
27
|
+
user by calling the constructor with an optional dictionary containing metadata. For
|
|
28
|
+
example:
|
|
29
|
+
|
|
30
|
+
from hdx.data.dataset import Dataset
|
|
31
|
+
|
|
32
|
+
dataset = Dataset({
|
|
33
|
+
"name": slugified_name,
|
|
34
|
+
"title": title
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
The dataset name should not contain special characters and hence if there is any chance
|
|
38
|
+
of that, then it needs to be slugified. Slugifying is way of making a string valid
|
|
39
|
+
within a URL (eg. **ae** replaces **ä**). There are various packages that can do this
|
|
40
|
+
eg. [python-slugify](https://pypi.python.org/pypi/python-slugify).
|
|
41
|
+
|
|
42
|
+
You can add metadata using the standard Python dictionary square brackets eg.
|
|
43
|
+
|
|
44
|
+
dataset["name"] = "My Dataset"
|
|
45
|
+
|
|
46
|
+
You can also do so by the standard dictionary **update** method, which takes a
|
|
47
|
+
dictionary eg.
|
|
48
|
+
|
|
49
|
+
dataset.update({"name": "My Dataset"})
|
|
50
|
+
|
|
51
|
+
Larger amounts of static metadata are best added from files. YAML is very human readable
|
|
52
|
+
and recommended, while JSON is also accepted eg.
|
|
53
|
+
|
|
54
|
+
dataset.update_from_yaml([path])
|
|
55
|
+
|
|
56
|
+
dataset.update_from_json([path])
|
|
57
|
+
|
|
58
|
+
The default path if unspecified is **config/hdx_TYPE_static.yaml** for YAML and
|
|
59
|
+
**config/hdx_TYPE_static.json** for JSON where TYPE is an HDX object's type like
|
|
60
|
+
dataset or resource eg. **config/hdx_showcase_static.json**. The YAML file takes the
|
|
61
|
+
following form:
|
|
62
|
+
|
|
63
|
+
owner_org: "acled"
|
|
64
|
+
maintainer: "acled"
|
|
65
|
+
...
|
|
66
|
+
tags:
|
|
67
|
+
- name: "violence and conflict"
|
|
68
|
+
resources:
|
|
69
|
+
-
|
|
70
|
+
description: "Resource1"
|
|
71
|
+
url: "http://resource1.xlsx"
|
|
72
|
+
format: "xlsx"
|
|
73
|
+
...
|
|
74
|
+
|
|
75
|
+
Notice how you can define resources (each resource starts with a dash "-") within the
|
|
76
|
+
file as shown above.
|
|
77
|
+
|
|
78
|
+
You can check if all the fields required by HDX are populated by
|
|
79
|
+
calling **check_required_fields**. This will throw an exception if any fields are
|
|
80
|
+
missing. Before the library posts data to HDX, it will call this method automatically.
|
|
81
|
+
You can provide a list of fields to ignore in the check. An example usage:
|
|
82
|
+
|
|
83
|
+
resource.check_required_fields([ignore_fields])
|
|
84
|
+
|
|
85
|
+
Once the HDX object is ready ie. it has all the required metadata, you simply
|
|
86
|
+
call **create_in_hdx** eg.
|
|
87
|
+
|
|
88
|
+
dataset.create_in_hdx(allow_no_resources, update_resources,
|
|
89
|
+
update_resources_by_name,
|
|
90
|
+
remove_additional_resources)
|
|
91
|
+
|
|
92
|
+
If the object already exists, it will be updated. You can also update
|
|
93
|
+
explicitly by calling **update_in_hdx** eg.
|
|
94
|
+
|
|
95
|
+
dataset.update_in_hdx(update_resources, update_resources_by_name,
|
|
96
|
+
remove_additional_resources)
|
|
97
|
+
|
|
98
|
+
You can delete HDX objects using **delete_from_hdx** and update an object that
|
|
99
|
+
already exists in HDX with the method **update_in_hdx**. These take various
|
|
100
|
+
boolean parameters that all have defaults and are documented in the API docs.
|
|
101
|
+
They do not return anything and they throw exceptions for failures like the
|
|
102
|
+
object to update not existing.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Manage Dataset Resources
|
|
2
|
+
|
|
3
|
+
A dataset can have resources and can be in a showcase.
|
|
4
|
+
|
|
5
|
+
If you wish to add a resource, you can create a resource dictionary and set the
|
|
6
|
+
format then call the **add_update_resource** function, for example:
|
|
7
|
+
|
|
8
|
+
resource = Resource({
|
|
9
|
+
"name": "myfile.xlsx",
|
|
10
|
+
"description": "description",
|
|
11
|
+
})
|
|
12
|
+
resource.set_format("xlsx")
|
|
13
|
+
resource.set_file_to_upload(PATH_TO_FILE)
|
|
14
|
+
dataset.add_update_resource(resource)
|
|
15
|
+
|
|
16
|
+
It is also possible to supply a resource id string or dictionary to the
|
|
17
|
+
**add_update_resource** function. A url can be given instead of uploading a
|
|
18
|
+
file to the HDX filestore (although using the filestore is preferred):
|
|
19
|
+
|
|
20
|
+
resource = Resource({
|
|
21
|
+
"name": "myfile.xlsx",
|
|
22
|
+
"description": "description",
|
|
23
|
+
"url": "https://www.blah.com/myfile.xlsx"
|
|
24
|
+
})
|
|
25
|
+
resource.set_format("xlsx")
|
|
26
|
+
dataset.add_update_resource(resource)
|
|
27
|
+
|
|
28
|
+
You can delete a Resource object from the dataset using the **delete_resource**
|
|
29
|
+
function, for example:
|
|
30
|
+
|
|
31
|
+
dataset.delete_resource(resource)
|
|
32
|
+
|
|
33
|
+
**add_update_resources** creates a list of HDX Resource objects
|
|
34
|
+
in a dataset:
|
|
35
|
+
|
|
36
|
+
dataset.add_update_resources(resources)
|
|
37
|
+
|
|
38
|
+
To see the list of resources, you use the **get_resources** function eg.
|
|
39
|
+
|
|
40
|
+
resources = dataset.get_resources()
|
|
41
|
+
|
|
42
|
+
You can get all the resources from a list of datasets as follows:
|
|
43
|
+
|
|
44
|
+
resources = Dataset.get_all_resources(datasets)
|
|
45
|
+
|
|
46
|
+
To see the list of showcases a dataset is in, you use the **get_showcases**
|
|
47
|
+
function eg.
|
|
48
|
+
|
|
49
|
+
showcases = dataset.get_showcases()
|
|
50
|
+
|
|
51
|
+
If you wish to add the dataset to a showcase, you must first create the
|
|
52
|
+
showcase in HDX if it does not already exist:
|
|
53
|
+
|
|
54
|
+
showcase = Showcase({"name": "new-showcase-1",
|
|
55
|
+
"title": "MyShowcase1",
|
|
56
|
+
"notes": "My Showcase",
|
|
57
|
+
"package_id": "6f36a41c-f126-4b18-aaaf-6c2ddfbc5d4d",
|
|
58
|
+
"image_display_url": "http://myvisual/visual.png",
|
|
59
|
+
"url": "http://visualisation/url/"})
|
|
60
|
+
showcase.create_in_hdx()
|
|
61
|
+
|
|
62
|
+
Then you can supply an id, dictionary or Showcase object and call the
|
|
63
|
+
**add_showcase** function, for example:
|
|
64
|
+
|
|
65
|
+
dataset.add_showcase(showcase)
|
|
66
|
+
|
|
67
|
+
You can remove the dataset from a showcase using the **remove_showcase**
|
|
68
|
+
function, for example:
|
|
69
|
+
|
|
70
|
+
dataset.remove_showcase(showcase)
|
|
71
|
+
|
|
72
|
+
HDX runs file structure checks on resources, recording schema changes (eg.
|
|
73
|
+
column names, order or types) and whether sheets have merged cells. You can get
|
|
74
|
+
these checks for all of a dataset's resources from HDX:
|
|
75
|
+
|
|
76
|
+
fs_check_info = dataset.get_fs_check_info()
|
|
77
|
+
|
|
78
|
+
This returns a list of dictionaries, each from a resource name to a list of
|
|
79
|
+
check events with keys such as `state`, `timestamp`, `sheet_changes` and
|
|
80
|
+
`hxl_proxy_response`.
|
|
81
|
+
|
|
82
|
+
Similarly, you can get the geopreview shape information of a dataset's
|
|
83
|
+
resources:
|
|
84
|
+
|
|
85
|
+
shape_info = dataset.get_shape_info()
|
|
86
|
+
|
|
87
|
+
HDX can recommend tags for a dataset based on its title and organization
|
|
88
|
+
(`owner_org`). Tags are ordered from most to least recommended:
|
|
89
|
+
|
|
90
|
+
tags = dataset.get_recommended_tags()
|
|
91
|
+
|
|
92
|
+
You can check if the dataset or its organization is in HDX's allowlist for
|
|
93
|
+
automatic loading of resources into the datastore:
|
|
94
|
+
|
|
95
|
+
allowed = dataset.is_allowed_for_datastore()
|
|
96
|
+
|
|
97
|
+
HDX sysadmins can submit all of a dataset's CSV resources to DataPusher+
|
|
98
|
+
(returning False if there are none):
|
|
99
|
+
|
|
100
|
+
submitted = dataset.push_to_datastore()
|
|
101
|
+
|
|
102
|
+
Users who are sysadmins or have permission to manage QA can mark QA of a
|
|
103
|
+
dataset as completed, set a QA field of all its resources or clear a file
|
|
104
|
+
structure check field (`fs_check_info` by default) of all its resources. The
|
|
105
|
+
dataset is updated from the result:
|
|
106
|
+
|
|
107
|
+
dataset.set_qa_completed(True)
|
|
108
|
+
dataset.qa_revise_resources("pii", "false")
|
|
109
|
+
dataset.reset_fs_check()
|