hdx-python-api 6.4.0__tar.gz → 6.4.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.
Files changed (135) hide show
  1. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/PKG-INFO +1 -1
  2. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/documentation/index.md +15 -0
  3. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/requirements.txt +1 -1
  4. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/api/_version.py +2 -2
  5. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/data/hdxobject.py +1 -1
  6. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/data/user.py +68 -4
  7. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/facades/simple.py +2 -2
  8. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/api/test_ckan.py +2 -0
  9. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/data/test_user.py +90 -0
  10. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/.coveragerc +0 -0
  11. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/.github/workflows/publish.yaml +0 -0
  12. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/.github/workflows/run-python-tests.yaml +0 -0
  13. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/.gitignore +0 -0
  14. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/.pre-commit-config.yaml +0 -0
  15. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/CONTRIBUTING.md +0 -0
  16. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/LICENSE +0 -0
  17. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/README.md +0 -0
  18. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/documentation/.readthedocs.yaml +0 -0
  19. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/documentation/mkdocs.yaml +0 -0
  20. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/hatch.toml +0 -0
  21. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/pyproject.toml +0 -0
  22. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/pytest.ini +0 -0
  23. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/ruff.toml +0 -0
  24. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/api/__init__.py +0 -0
  25. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/api/configuration.py +0 -0
  26. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/api/hdx_base_configuration.yaml +0 -0
  27. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/api/locations.py +0 -0
  28. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/api/remotehdx.py +0 -0
  29. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/api/utilities/__init__.py +0 -0
  30. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/api/utilities/dataset_title_helper.py +0 -0
  31. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/api/utilities/date_helper.py +0 -0
  32. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/api/utilities/filestore_helper.py +0 -0
  33. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/api/utilities/hdx_error_handler.py +0 -0
  34. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/data/__init__.py +0 -0
  35. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/data/dataset.py +0 -0
  36. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/data/hdx_datasource_topline.yaml +0 -0
  37. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/data/indicator_resource_view_template.yaml +0 -0
  38. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/data/organization.py +0 -0
  39. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/data/resource.py +0 -0
  40. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/data/resource_matcher.py +0 -0
  41. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/data/resource_view.py +0 -0
  42. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/data/showcase.py +0 -0
  43. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/data/vocabulary.py +0 -0
  44. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/facades/__init__.py +0 -0
  45. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/facades/infer_arguments.py +0 -0
  46. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/src/hdx/facades/keyword_arguments.py +0 -0
  47. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/Accepted_Tags.csv +0 -0
  48. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/CKAN/hdx_dataset_static.yaml +0 -0
  49. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/Tag_Mapping.csv +0 -0
  50. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/Tag_Mapping_ChainRuleError.csv +0 -0
  51. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/empty.yaml +0 -0
  52. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_base_config.json +0 -0
  53. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_base_config.yaml +0 -0
  54. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_config.json +0 -0
  55. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_config.yaml +0 -0
  56. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_dataset_static.json +0 -0
  57. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_dataset_static.yaml +0 -0
  58. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_datasource_topline.json +0 -0
  59. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_datasource_topline.yaml +0 -0
  60. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_email_configuration.json +0 -0
  61. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_email_configuration.yaml +0 -0
  62. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_missing_site_config.json +0 -0
  63. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_organization_static.json +0 -0
  64. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_organization_static.yaml +0 -0
  65. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_resource_static.json +0 -0
  66. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_resource_static.yaml +0 -0
  67. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_resource_view_static.json +0 -0
  68. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_resource_view_static.yaml +0 -0
  69. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_showcase_static.json +0 -0
  70. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_showcase_static.yaml +0 -0
  71. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_user_static.json +0 -0
  72. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_user_static.yaml +0 -0
  73. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_vocabulary_static.json +0 -0
  74. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/hdx_vocabulary_static.yaml +0 -0
  75. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/project_configuration.json +0 -0
  76. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/project_configuration.yaml +0 -0
  77. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/user_agent_config.yaml +0 -0
  78. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/user_agent_config2.yaml +0 -0
  79. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/user_agent_config3.yaml +0 -0
  80. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/config/user_agent_config_wrong.yaml +0 -0
  81. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/dataset_search_results.yaml +0 -0
  82. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/datastore/ACLED-All-Africa-File_20170101-to-20170708.xlsx +0 -0
  83. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/empty.csv +0 -0
  84. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/gen_resource/conflict_data_alg.csv +0 -0
  85. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/gen_resource/min_qc_conflict_data_alg.csv +0 -0
  86. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/gen_resource/qc_conflict_data_alg.csv +0 -0
  87. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/gen_resource/test_data_no_data.csv +0 -0
  88. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/gen_resource/test_data_no_years.csv +0 -0
  89. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/organization_show_results.yaml +0 -0
  90. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/qc_from_rows/qc_conflict_data_alg.csv +0 -0
  91. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/qc_from_rows/qc_conflict_data_alg_one_col.csv +0 -0
  92. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/resource_formats.json +0 -0
  93. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/showcase_all_search_results.yaml +0 -0
  94. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/test_data.csv +0 -0
  95. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/test_data.zip +0 -0
  96. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_dataset_resources/dem_data_zwe.csv +0 -0
  97. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_dataset_resources/dem_indicatorlist_zwe.csv +0 -0
  98. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_dataset_resources/expected_resources_to_update.json +0 -0
  99. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_dataset_resources/opri_data_zwe.csv +0 -0
  100. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_dataset_resources/opri_indicatorlist_zwe.csv +0 -0
  101. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_dataset_resources/opri_metadata_zwe.csv +0 -0
  102. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_dataset_resources/qc_sdg_data_zwe.csv +0 -0
  103. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_dataset_resources/sdg_data_zwe.csv +0 -0
  104. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_dataset_resources/sdg_indicatorlist_zwe.csv +0 -0
  105. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_dataset_resources/sdg_metadata_zwe.csv +0 -0
  106. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_dataset_resources/unesco_dataset.json +0 -0
  107. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_dataset_resources/unesco_update_dataset.json +0 -0
  108. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_logic/update_logic_resources.yaml +0 -0
  109. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/fixtures/update_logic/update_logic_resources_new.yaml +0 -0
  110. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/api/test_configuration.py +0 -0
  111. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/api/test_locations.py +0 -0
  112. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/conftest.py +0 -0
  113. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/data/__init__.py +0 -0
  114. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/data/test_dataset_add_hapi_error.py +0 -0
  115. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/data/test_dataset_core.py +0 -0
  116. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/data/test_dataset_noncore.py +0 -0
  117. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/data/test_dataset_resource_generation.py +0 -0
  118. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/data/test_organization.py +0 -0
  119. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/data/test_resource.py +0 -0
  120. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/data/test_resource_view.py +0 -0
  121. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/data/test_showcase.py +0 -0
  122. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/data/test_update_dataset_resources.py +0 -0
  123. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/data/test_update_logic.py +0 -0
  124. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/data/test_vocabulary.py +0 -0
  125. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/facades/__init__.py +0 -0
  126. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/facades/test_infer_arguments.py +0 -0
  127. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/facades/test_keyword_arguments.py +0 -0
  128. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/facades/test_simple.py +0 -0
  129. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/utilities/test_dataset_title_helper.py +0 -0
  130. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/utilities/test_filestore_helper.py +0 -0
  131. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/tests/hdx/utilities/test_hdx_error_handler.py +0 -0
  132. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/workingexample/my_code.py +0 -0
  133. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/workingexample/my_resource.csv +0 -0
  134. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/workingexample/my_resource.xlsx +0 -0
  135. {hdx_python_api-6.4.0 → hdx_python_api-6.4.2}/workingexample/run.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hdx-python-api
3
- Version: 6.4.0
3
+ Version: 6.4.2
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
@@ -1003,6 +1003,21 @@ If you want to add a list of tags, you do it as follows:
1003
1003
  The **User** class enables you to manage users, creating, deleting and updating (as for
1004
1004
  other HDX objects) according to your permissions.
1005
1005
 
1006
+ You can obtain the currently logged in user (which is based on the API token used in the
1007
+ configuration):
1008
+
1009
+ user = User.get_current_user()
1010
+
1011
+ You can check that the current user has a particular permission to a specific
1012
+ organization:
1013
+
1014
+ result = User.check_current_user_organization_access("hdx", "read")
1015
+
1016
+ For a general access check to use before running a script that creates or updates
1017
+ datasets:
1018
+
1019
+ username = User.check_current_user_write_access("hdx")
1020
+
1006
1021
  You can email a user. First you need to set up an email server using a dictionary or
1007
1022
  file:
1008
1023
 
@@ -258,7 +258,7 @@ rsa==4.9.1
258
258
  # via google-auth
259
259
  ruamel-yaml==0.18.10
260
260
  # via hdx-python-utilities
261
- setuptools==80.7.1
261
+ setuptools==80.8.0
262
262
  # via ckanapi
263
263
  shellingham==1.5.4
264
264
  # via typer
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '6.4.0'
21
- __version_tuple__ = version_tuple = (6, 4, 0)
20
+ __version__ = version = '6.4.2'
21
+ __version_tuple__ = version_tuple = (6, 4, 2)
@@ -367,7 +367,7 @@ class HDXObject(UserDict, ABC):
367
367
  self,
368
368
  action: str,
369
369
  data: Dict,
370
- id_field_name: str = None,
370
+ id_field_name: Optional[str] = None,
371
371
  files_to_upload: Dict = {},
372
372
  ) -> Union[Dict, List]:
373
373
  """Creates or updates an HDX object in HDX and return HDX object metadata dict
@@ -6,7 +6,7 @@ from typing import Any, Dict, List, Optional
6
6
 
7
7
  import hdx.data.organization
8
8
  from hdx.api.configuration import Configuration
9
- from hdx.data.hdxobject import HDXObject
9
+ from hdx.data.hdxobject import HDXError, HDXObject
10
10
  from hdx.utilities.typehint import ListTuple
11
11
 
12
12
  logger = logging.getLogger(__name__)
@@ -167,6 +167,20 @@ class User(HDXObject):
167
167
  **kwargs,
168
168
  )
169
169
 
170
+ @staticmethod
171
+ def get_current_user(configuration: Optional[Configuration] = None) -> "User":
172
+ """Get current user (based on authorisation from API token)
173
+
174
+ Args:
175
+ configuration (Optional[Configuration]): HDX configuration. Defaults to global configuration.
176
+
177
+ Returns:
178
+ User: Current user
179
+ """
180
+ user = User(configuration=configuration)
181
+ user._save_to_hdx("show", {})
182
+ return user
183
+
170
184
  @staticmethod
171
185
  def get_all_users(
172
186
  configuration: Optional[Configuration] = None, **kwargs: Any
@@ -297,7 +311,7 @@ class User(HDXObject):
297
311
  Returns:
298
312
  bool: True if the logged in user is a member of the organization.
299
313
  """
300
- for organization_dict in self.get_organization_dicts(permission=permission):
314
+ for organization_dict in self.get_organization_dicts(permission):
301
315
  if organization_dict["id"] == organization:
302
316
  return True
303
317
  if organization_dict["name"] == organization:
@@ -353,19 +367,23 @@ class User(HDXObject):
353
367
 
354
368
  @classmethod
355
369
  def check_current_user_organization_access(
356
- cls, organization: str, permission: str = "read"
370
+ cls,
371
+ organization: str,
372
+ permission: str = "read",
373
+ configuration: Optional[Configuration] = None,
357
374
  ) -> bool:
358
375
  """Check logged in user is a member of a given organization.
359
376
 
360
377
  Args:
361
378
  organization (str): Organization id or name.
362
379
  permission (str): Permission to check for. Defaults to 'read'.
380
+ configuration (Optional[Configuration]): HDX configuration. Defaults to global configuration.
363
381
 
364
382
  Returns:
365
383
  bool: True if the logged in user is a member of the organization.
366
384
  """
367
385
  for organization_dict in cls.get_current_user_organization_dicts(
368
- permission=permission
386
+ permission, configuration
369
387
  ):
370
388
  if organization_dict["id"] == organization:
371
389
  return True
@@ -373,6 +391,52 @@ class User(HDXObject):
373
391
  return True
374
392
  return False
375
393
 
394
+ @classmethod
395
+ def check_current_user_write_access(
396
+ cls,
397
+ organization: str,
398
+ permission: str = "create_dataset",
399
+ configuration: Optional[Configuration] = None,
400
+ ) -> "User":
401
+ """Check logged in user has write access to a given organization. Raises
402
+ PermissionError if the user does not have access otherwise logs and returns the
403
+ current username.
404
+
405
+ Args:
406
+ organization (str): Organization id or name.
407
+ permission (str): Permission to check for. Defaults to 'create_dataset'.
408
+ configuration (Optional[Configuration]): HDX configuration. Defaults to global configuration.
409
+
410
+ Returns:
411
+ str: Username of current user
412
+ """
413
+ if configuration is None:
414
+ configuration = Configuration.read()
415
+ hdx_key = configuration.hdx_key
416
+ if not hdx_key:
417
+ raise PermissionError(
418
+ "There is no logged in user. API token is missing or blank!"
419
+ )
420
+ logger.info(f"API token is {len(hdx_key)} characters long")
421
+ try:
422
+ current_user = cls.get_current_user(configuration)
423
+ except HDXError:
424
+ raise PermissionError(
425
+ "There appears to be no logged in user. API token may be invalid!"
426
+ )
427
+ username = current_user["name"]
428
+ logger.info(f'Current user is "{username}"')
429
+ if not cls.check_current_user_organization_access(
430
+ organization, permission, configuration
431
+ ):
432
+ raise PermissionError(
433
+ f'Current user does not have "{permission}" access to "{organization}" organization!'
434
+ )
435
+ logger.info(
436
+ f'Current user has "{permission}" access to "{organization}" organization'
437
+ )
438
+ return username
439
+
376
440
  def get_token_list(self):
377
441
  """Get API tokens for user.
378
442
 
@@ -12,11 +12,11 @@ logger = logging.getLogger(__name__)
12
12
  setup_logging(log_file="errors.log")
13
13
 
14
14
 
15
- def facade(projectmainfn: Callable[[None], None], **kwargs: Any):
15
+ def facade(projectmainfn: Callable[[], None], **kwargs: Any):
16
16
  """Facade to simplify project setup that calls project main function
17
17
 
18
18
  Args:
19
- projectmainfn ((None) -> None): main function of project
19
+ projectmainfn (() -> None): main function of project
20
20
  **kwargs: configuration parameters to pass to HDX Configuration class
21
21
 
22
22
  Returns:
@@ -19,6 +19,7 @@ from hdx.api.configuration import Configuration
19
19
  from hdx.api.locations import Locations
20
20
  from hdx.data.dataset import Dataset
21
21
  from hdx.data.resource import Resource
22
+ from hdx.data.user import User
22
23
  from hdx.data.vocabulary import Vocabulary
23
24
  from hdx.location.country import Country
24
25
  from hdx.utilities.dateparse import now_utc
@@ -35,6 +36,7 @@ class TestCKAN:
35
36
  user_agent="test",
36
37
  hdx_key=hdx_key,
37
38
  )
39
+ User.check_current_user_write_access("5a63012e-6c41-420c-8c33-e84b277fdc90")
38
40
  Locations._validlocations = None
39
41
  Country.countriesdata(use_live=False)
40
42
  Vocabulary._approved_vocabulary = None
@@ -263,6 +263,25 @@ class TestUser:
263
263
 
264
264
  Configuration.read().remoteckan().session = MockSession()
265
265
 
266
+ @pytest.fixture(scope="function")
267
+ def show_current_user(self):
268
+ class MockSession:
269
+ @staticmethod
270
+ def post(url, data, headers, files, allow_redirects, auth=None):
271
+ if "show" not in url:
272
+ return MockResponse(
273
+ 404,
274
+ '{"success": false, "error": {"message": "TEST ERROR: Not show", "__type": "TEST ERROR: Not Show Error"}, "help": "http://test-data.humdata.org/api/3/action/help_show?name=user_show"}',
275
+ )
276
+ result = json.dumps(resultdict)
277
+ return MockResponse(
278
+ 200,
279
+ '{"success": true, "result": %s, "help": "http://test-data.humdata.org/api/3/action/help_show?name=user_show"}'
280
+ % result,
281
+ )
282
+
283
+ Configuration.read().remoteckan().session = MockSession()
284
+
266
285
  @pytest.fixture(scope="function")
267
286
  def post_list(self):
268
287
  class MockSession:
@@ -304,6 +323,49 @@ class TestUser:
304
323
 
305
324
  Configuration.read().remoteckan().session = MockSession()
306
325
 
326
+ @pytest.fixture(scope="function")
327
+ def post_check_current_user_write_access(self):
328
+ class MockSession:
329
+ @staticmethod
330
+ def post(url, data, headers, files, allow_redirects, auth=None):
331
+ decodedata = data.decode("utf-8")
332
+ datadict = json.loads(decodedata)
333
+ if "user" in url:
334
+ if "show" in url:
335
+ configuration = Configuration.read()
336
+ hdx_key = configuration.hdx_key
337
+ if hdx_key == "fail":
338
+ return MockResponse(
339
+ 404,
340
+ '{"success": false, "error": {"message": "Not found", "__type": "Not Found Error"}, "help": "http://test-data.humdata.org/api/3/action/help_show?name=user_show"}',
341
+ )
342
+ result = json.dumps(resultdict)
343
+ return MockResponse(
344
+ 200,
345
+ '{"success": true, "result": %s, "help": "http://test-data.humdata.org/api/3/action/help_show?name=user_show"}'
346
+ % result,
347
+ )
348
+ elif "list" in url:
349
+ return MockResponse(
350
+ 200,
351
+ '{"success": true, "result": %s, "help": "http://test-data.humdata.org/api/3/action/help_show?name=organization_list"}'
352
+ % json.dumps(orglist),
353
+ )
354
+ elif "organization" in url:
355
+ if "show" in url:
356
+ result = json.dumps(orgdict)
357
+ if (
358
+ datadict["id"] == "b67e6c74-c185-4f43-b561-0e114a736f19"
359
+ or datadict["id"] == "TEST1"
360
+ ):
361
+ return MockResponse(
362
+ 200,
363
+ '{"success": true, "result": %s, "help": "http://test-data.humdata.org/api/3/action/help_show?name=user_show"}'
364
+ % result,
365
+ )
366
+
367
+ Configuration.read().remoteckan().session = MockSession()
368
+
307
369
  @pytest.fixture(scope="function")
308
370
  def post_listorgs_invalid(self):
309
371
  class MockSession:
@@ -522,6 +584,10 @@ Content-Transfer-Encoding: 7bit
522
584
  assert user["name"] == "MyUser1"
523
585
  assert user["about"] == "other"
524
586
 
587
+ def test_get_current_user(self, configuration, show_current_user):
588
+ user = User.get_current_user()
589
+ assert user["name"] == "MyUser1"
590
+
525
591
  def test_get_all_users(self, configuration, post_list, mocksmtp):
526
592
  users = User.get_all_users()
527
593
  assert len(users) == 2
@@ -636,6 +702,30 @@ Content-Transfer-Encoding: 7bit
636
702
  assert user.get_organization_dicts() == []
637
703
  assert User.get_current_user_organization_dicts() == []
638
704
 
705
+ def test_check_current_user_write_access(
706
+ self, configuration, post_check_current_user_write_access
707
+ ):
708
+ username = User.check_current_user_write_access(
709
+ "b67e6c74-c185-4f43-b561-0e114a736f19"
710
+ )
711
+ assert username == "MyUser1"
712
+ username = User.check_current_user_write_access("acled")
713
+ assert username == "MyUser1"
714
+ with pytest.raises(PermissionError):
715
+ User.check_current_user_write_access("lala")
716
+ with pytest.raises(PermissionError):
717
+ configuration = Configuration.read()
718
+ hdx_key = configuration.hdx_key
719
+ configuration.hdx_key = "fail"
720
+ User.check_current_user_write_access("b67e6c74-c185-4f43-b561-0e114a736f19")
721
+ configuration.hdx_key = hdx_key
722
+ with pytest.raises(PermissionError):
723
+ configuration = Configuration.read()
724
+ hdx_key = configuration.hdx_key
725
+ configuration.hdx_key = None
726
+ User.check_current_user_write_access("acled", configuration=configuration)
727
+ configuration.hdx_key = hdx_key
728
+
639
729
  def test_get_token_list(self, configuration, post_tokenlist):
640
730
  user = User.read_from_hdx("9f3e9973-7dbe-4c65-8820-f48578e3ffea")
641
731
  tokens = user.get_token_list()
File without changes
File without changes
File without changes