CMIP7-data-request-api 1.2b2__tar.gz → 1.2.1__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 (146) hide show
  1. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/PKG-INFO +20 -11
  2. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/README.md +19 -10
  3. cmip7_data_request_api-1.2.1/binder/environment.yml +13 -0
  4. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/CMIP7_data_request_api.egg-info/PKG-INFO +20 -11
  5. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/CMIP7_data_request_api.egg-info/SOURCES.txt +5 -2
  6. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/command_line/config.py +4 -3
  7. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/command_line/estimate_dreq_volume.py +33 -11
  8. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/command_line/export_dreq_lists_json.py +4 -3
  9. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/content/consolidate_export.py +70 -8
  10. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/content/dreq_content.py +15 -12
  11. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/content/dump_transformation.py +6 -5
  12. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/content/mapping_table.py +61 -16
  13. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/content/transform.json +32 -0
  14. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/query/data_request.py +86 -56
  15. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/query/dreq_query.py +109 -28
  16. cmip7_data_request_api-1.2.1/data_request_api/data_request_api/query/filtering.json +24 -0
  17. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/query/vocabulary_server.py +1 -0
  18. cmip7_data_request_api-1.2.1/data_request_api/data_request_api/tests/test_cli.py +501 -0
  19. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_data_request.py +7 -7
  20. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_decorator.py +26 -0
  21. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_dreq_content.py +14 -4
  22. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/utilities/config.py +44 -3
  23. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/utilities/decorators.py +3 -0
  24. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/version.py +2 -2
  25. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/command_line/config.html +4 -3
  26. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/command_line/estimate_dreq_volume.html +33 -11
  27. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/command_line/export_dreq_lists_json.html +4 -3
  28. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/content/consolidate_export.html +8 -1
  29. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/content/dreq_content.html +10 -11
  30. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/content/dump_transformation.html +6 -5
  31. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/content/mapping_table.html +11 -0
  32. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/query/data_request.html +157 -105
  33. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/query/dreq_query.html +110 -29
  34. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/query/vocabulary_server.html +2 -0
  35. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/tests/test_cli.html +572 -70
  36. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/tests/test_data_request.html +14 -14
  37. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/tests/test_decorator.html +27 -1
  38. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/tests/test_dreq_content.html +31 -8
  39. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/utilities/config.html +49 -0
  40. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/utilities/decorators.html +3 -0
  41. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/launch_test_with_coverage.sh +7 -0
  42. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/requirements.txt +0 -1
  43. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/scripts/check_consolidation.py +8 -2
  44. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/scripts/check_consolidation2.py +169 -43
  45. cmip7_data_request_api-1.2.1/scripts/check_consolidation_and_transformation.py +627 -0
  46. cmip7_data_request_api-1.2b2/scripts/examples/requested_v1.2.json → cmip7_data_request_api-1.2.1/scripts/examples/requested_v1.2.1.json +3 -107
  47. cmip7_data_request_api-1.2b2/scripts/examples/variables_v1.2.json → cmip7_data_request_api-1.2.1/scripts/examples/variables_v1.2.1.json +9564 -4009
  48. cmip7_data_request_api-1.2.1/scripts/sandbox/create_brand_name.py +214 -0
  49. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/scripts/workflow_example.py +2 -2
  50. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/scripts/workflow_example_2.py +15 -1
  51. cmip7_data_request_api-1.2b2/data_request_api/data_request_api/query/filtering.json +0 -41
  52. cmip7_data_request_api-1.2b2/data_request_api/data_request_api/tests/test_cli.py +0 -290
  53. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/.DS_Store +0 -0
  54. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/.github/.DS_Store +0 -0
  55. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/.github/workflows/pip_install.yml +0 -0
  56. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/.github/workflows/publish2pypi.yml +0 -0
  57. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/.github/workflows/updates.yml +0 -0
  58. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/.gitignore +0 -0
  59. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/LICENSE +0 -0
  60. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/.DS_Store +0 -0
  61. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/CMIP7_data_request_api.egg-info/dependency_links.txt +0 -0
  62. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/CMIP7_data_request_api.egg-info/entry_points.txt +0 -0
  63. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/CMIP7_data_request_api.egg-info/requires.txt +0 -0
  64. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/CMIP7_data_request_api.egg-info/top_level.txt +0 -0
  65. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/__init__.py +0 -0
  66. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/command_line/__init__.py +0 -0
  67. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/command_line/compare_variables.py +0 -0
  68. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/command_line/get_variables_metadata.py +0 -0
  69. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/content/README.MD +0 -0
  70. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/content/__init__.py +0 -0
  71. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/query/__init__.py +0 -0
  72. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/query/dreq_classes.py +0 -0
  73. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/__init__.py +0 -0
  74. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_config.py +0 -0
  75. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_config_cli.py +0 -0
  76. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_consolidation.py +0 -0
  77. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_datasets/one_base_DR_dump.txt +0 -0
  78. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_datasets/one_base_DR_output.json +0 -0
  79. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_datasets/one_base_VS_output.json +0 -0
  80. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_datasets/one_base_input.json +0 -0
  81. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_datasets/one_base_output_format.json +0 -0
  82. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_datasets/one_base_output_transform.json +0 -0
  83. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_datasets/several_bases_DR_output.json +0 -0
  84. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_datasets/several_bases_VS_output.json +0 -0
  85. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_datasets/several_bases_input.json +0 -0
  86. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_datasets/several_bases_output_format.json +0 -0
  87. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_datasets/several_bases_output_transform.json +0 -0
  88. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_dump_transformation.py +0 -0
  89. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_optimize.py +0 -0
  90. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/tests/test_vocabulary_server.py +0 -0
  91. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/utilities/__init__.py +0 -0
  92. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/utilities/logger.py +0 -0
  93. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/utilities/parser.py +0 -0
  94. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/data_request_api/data_request_api/utilities/tools.py +0 -0
  95. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/command_line/compare_variables.html +0 -0
  96. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/command_line/get_variables_metadata.html +0 -0
  97. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/command_line/index.html +0 -0
  98. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/content/index.html +0 -0
  99. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/index.html +0 -0
  100. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/query/dreq_classes.html +0 -0
  101. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/query/index.html +0 -0
  102. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/content/consolidate_export.html +0 -0
  103. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/content/dreq_content.html +0 -0
  104. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/content/dump_transformation.html +0 -0
  105. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/content/index.html +0 -0
  106. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/content/mapping_table.html +0 -0
  107. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/index.html +0 -0
  108. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/query/data_request.html +0 -0
  109. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/query/dreq_classes.html +0 -0
  110. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/query/dreq_query.html +0 -0
  111. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/query/index.html +0 -0
  112. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/query/vocabulary_server.html +0 -0
  113. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/utilities/config.html +0 -0
  114. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/utilities/decorators.html +0 -0
  115. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/utilities/index.html +0 -0
  116. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/utilities/logger.html +0 -0
  117. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/utilities/parser.html +0 -0
  118. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/stable/utilities/tools.html +0 -0
  119. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/tests/index.html +0 -0
  120. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/tests/test_config.html +0 -0
  121. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/tests/test_config_cli.html +0 -0
  122. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/tests/test_consolidation.html +0 -0
  123. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/tests/test_dump_transformation.html +0 -0
  124. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/tests/test_optimize.html +0 -0
  125. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/tests/test_vocabulary_server.html +0 -0
  126. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/utilities/index.html +0 -0
  127. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/utilities/logger.html +0 -0
  128. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/utilities/parser.html +0 -0
  129. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/utilities/tools.html +0 -0
  130. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/docs/data_request_api/version.html +0 -0
  131. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/env.yml +0 -0
  132. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/notebooks/HowTo-00_Install_the_DR_Software.ipynb +0 -0
  133. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/notebooks/HowTo-01_Import_and_Load_the_DR.ipynb +0 -0
  134. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/notebooks/HowTo-02_Discover_What_is_in_DR.ipynb +0 -0
  135. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/notebooks/HowTo-03a_Find_Experiments_and_Variables_for_given_Opportunities.ipynb +0 -0
  136. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/notebooks/HowTo-03b_Find_Experiments_and_Variables_for_given_Opportunities.ipynb +0 -0
  137. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/notebooks/HowTo-04a_View_Attributes_of_Experiments_and_Variables.ipynb +0 -0
  138. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/notebooks/HowTo-04b_View_Attributes_of_Variables.ipynb +0 -0
  139. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/notebooks/HowTo-05_Apply_Various_Search_Critria.ipynb +0 -0
  140. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/notebooks/README.md +0 -0
  141. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/notebooks/outdir/.gitkeep +0 -0
  142. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/notebooks/workflow_example.ipynb +0 -0
  143. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/pyproject.toml +0 -0
  144. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/scripts/check_variables_attributes.py +0 -0
  145. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/scripts/database_transformation.py +0 -0
  146. {cmip7_data_request_api-1.2b2 → cmip7_data_request_api-1.2.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: CMIP7_data_request_api
3
- Version: 1.2b2
3
+ Version: 1.2.1
4
4
  Summary: A programmatic interface to the CMIP7 Data Request
5
5
  Author: James Anstey, Gaëlle Rigoudy, Martin Schupfner, Matthew Mizielinski, Daniel Ellis, Elisabeth Dingley, Marie-Pierre Moine
6
6
  License-Expression: MIT
@@ -20,6 +20,7 @@ Dynamic: license-file
20
20
 
21
21
  [![pypi](https://img.shields.io/pypi/v/CMIP7-data-request-api.svg)](https://pypi.python.org/pypi/CMIP7-data-request-api)
22
22
  [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/CMIP-Data-Request/CMIP7_DReq_Software/main?filepath=notebooks)
23
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/CMIP-Data-Request/CMIP7_DReq_Software/)
23
24
  [![NBviewer](https://raw.githubusercontent.com/jupyter/design/master/logos/Badges/nbviewer_badge.svg)](https://nbviewer.jupyter.org/github/CMIP-Data-Request/CMIP7_DReq_Software/tree/main/notebooks/)
24
25
  [![license](https://img.shields.io/github/license/CMIP-Data-Request/CMIP7_DReq_Software.svg)](https://github.com/CMIP-Data-Request/CMIP7_DReq_Software/blob/main/LICENSE)
25
26
  [![status](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
@@ -29,7 +30,7 @@ Dynamic: license-file
29
30
  Python software to interact with the [CMIP7 data request](https://wcrp-cmip.org/cmip7/cmip7-data-request/).
30
31
  It provides an API to query and utilize the information in the data request, including example scripts and notebooks showing how to use the API.
31
32
 
32
- For the **Quick Start** guide, please see below.
33
+ Please see below for the [installation guide](#installation) or how to [try it without installation](#try-it-without-installation).
33
34
 
34
35
  The Data Request Task Team encourages user feedback to help us improve the software.
35
36
  Here are some ways to provide feedback:
@@ -37,22 +38,25 @@ Here are some ways to provide feedback:
37
38
  - For more general questions or concerns, such as suggestions for new features, contribute to the Software's [github discussion forum](https://github.com/CMIP-Data-Request/CMIP7_DReq_Software/discussions).
38
39
 
39
40
 
40
- ## v1.2 Data Request release
41
+ ## v1.2.1 Data Request release
41
42
 
42
- The latest **official release** of the CMIP7 Data Request is `v1.2` (31 March 2025)
43
- Access all information about the v1.2 release [on the CMIP website](https://wcrp-cmip.org/cmip7-data-request-v1-2/).
43
+ The latest **official release** of the CMIP7 Data Request is `v1.2.1` (26 April 2025).
44
+ [Learn more about this release on the CMIP website](https://wcrp-cmip.org/cmip7-data-request-v1-2-1/).
44
45
 
45
- Please note that a technical update to the Data Request, `v1.2.1`, is planned for late April 2025.
46
- This update will affect some details such as the names of CMOR variables, without substantially changing the scientific content of the request.
47
- For further information please see the [v1.2 release page](https://wcrp-cmip.org/cmip7-data-request-v1-2/).
48
- An update of this software will follow the release of `v1.2.1`.
46
+
47
+ ## Try It Without Installation
48
+
49
+ You can launch and interact with this repository in a live environment via [Binder](https://mybinder.org/) or [Google Colab](https://colab.research.google.com/) — no installation needed, just click on one of the badges to run it in your browser:
50
+
51
+ [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/CMIP-Data-Request/CMIP7_DReq_Software/main?filepath=notebooks)
52
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/CMIP-Data-Request/CMIP7_DReq_Software/)
49
53
 
50
54
 
51
55
  ## Installation
52
56
 
53
57
  ### Quick Start
54
58
 
55
- In a python virtual environment that already has the dependencies installed, do:
59
+ In a python virtual environment or conda environment in which you want to install the package, do:
56
60
 
57
61
  ```bash
58
62
  pip install CMIP7-data-request-api
@@ -64,9 +68,14 @@ If an environment first needs to be created, you can do:
64
68
  python -m venv my_dreq_env
65
69
  source my_dreq_env/bin/activate
66
70
  pip install --upgrade pip
71
+ pip install CMIP7-data-request-api
72
+ ```
73
+
74
+ This will automatically install the dependencies, but if necessary they can be manually installed by doing:
75
+
76
+ ```bash
67
77
  wget https://raw.githubusercontent.com/CMIP-Data-Request/CMIP7_DReq_Software/refs/heads/main/requirements.txt
68
78
  pip install -r requirements.txt
69
- pip install CMIP7-data-request-api
70
79
  ```
71
80
 
72
81
  using the `requirements.txt` file from the top-level directory of this repository, which lists the package dependencies, and `my_dreq_env` can be changed to whatever environment name is preferred.
@@ -1,5 +1,6 @@
1
1
  [![pypi](https://img.shields.io/pypi/v/CMIP7-data-request-api.svg)](https://pypi.python.org/pypi/CMIP7-data-request-api)
2
2
  [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/CMIP-Data-Request/CMIP7_DReq_Software/main?filepath=notebooks)
3
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/CMIP-Data-Request/CMIP7_DReq_Software/)
3
4
  [![NBviewer](https://raw.githubusercontent.com/jupyter/design/master/logos/Badges/nbviewer_badge.svg)](https://nbviewer.jupyter.org/github/CMIP-Data-Request/CMIP7_DReq_Software/tree/main/notebooks/)
4
5
  [![license](https://img.shields.io/github/license/CMIP-Data-Request/CMIP7_DReq_Software.svg)](https://github.com/CMIP-Data-Request/CMIP7_DReq_Software/blob/main/LICENSE)
5
6
  [![status](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
@@ -9,7 +10,7 @@
9
10
  Python software to interact with the [CMIP7 data request](https://wcrp-cmip.org/cmip7/cmip7-data-request/).
10
11
  It provides an API to query and utilize the information in the data request, including example scripts and notebooks showing how to use the API.
11
12
 
12
- For the **Quick Start** guide, please see below.
13
+ Please see below for the [installation guide](#installation) or how to [try it without installation](#try-it-without-installation).
13
14
 
14
15
  The Data Request Task Team encourages user feedback to help us improve the software.
15
16
  Here are some ways to provide feedback:
@@ -17,22 +18,25 @@ Here are some ways to provide feedback:
17
18
  - For more general questions or concerns, such as suggestions for new features, contribute to the Software's [github discussion forum](https://github.com/CMIP-Data-Request/CMIP7_DReq_Software/discussions).
18
19
 
19
20
 
20
- ## v1.2 Data Request release
21
+ ## v1.2.1 Data Request release
21
22
 
22
- The latest **official release** of the CMIP7 Data Request is `v1.2` (31 March 2025)
23
- Access all information about the v1.2 release [on the CMIP website](https://wcrp-cmip.org/cmip7-data-request-v1-2/).
23
+ The latest **official release** of the CMIP7 Data Request is `v1.2.1` (26 April 2025).
24
+ [Learn more about this release on the CMIP website](https://wcrp-cmip.org/cmip7-data-request-v1-2-1/).
24
25
 
25
- Please note that a technical update to the Data Request, `v1.2.1`, is planned for late April 2025.
26
- This update will affect some details such as the names of CMOR variables, without substantially changing the scientific content of the request.
27
- For further information please see the [v1.2 release page](https://wcrp-cmip.org/cmip7-data-request-v1-2/).
28
- An update of this software will follow the release of `v1.2.1`.
26
+
27
+ ## Try It Without Installation
28
+
29
+ You can launch and interact with this repository in a live environment via [Binder](https://mybinder.org/) or [Google Colab](https://colab.research.google.com/) — no installation needed, just click on one of the badges to run it in your browser:
30
+
31
+ [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/CMIP-Data-Request/CMIP7_DReq_Software/main?filepath=notebooks)
32
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/CMIP-Data-Request/CMIP7_DReq_Software/)
29
33
 
30
34
 
31
35
  ## Installation
32
36
 
33
37
  ### Quick Start
34
38
 
35
- In a python virtual environment that already has the dependencies installed, do:
39
+ In a python virtual environment or conda environment in which you want to install the package, do:
36
40
 
37
41
  ```bash
38
42
  pip install CMIP7-data-request-api
@@ -44,9 +48,14 @@ If an environment first needs to be created, you can do:
44
48
  python -m venv my_dreq_env
45
49
  source my_dreq_env/bin/activate
46
50
  pip install --upgrade pip
51
+ pip install CMIP7-data-request-api
52
+ ```
53
+
54
+ This will automatically install the dependencies, but if necessary they can be manually installed by doing:
55
+
56
+ ```bash
47
57
  wget https://raw.githubusercontent.com/CMIP-Data-Request/CMIP7_DReq_Software/refs/heads/main/requirements.txt
48
58
  pip install -r requirements.txt
49
- pip install CMIP7-data-request-api
50
59
  ```
51
60
 
52
61
  using the `requirements.txt` file from the top-level directory of this repository, which lists the package dependencies, and `my_dreq_env` can be changed to whatever environment name is preferred.
@@ -0,0 +1,13 @@
1
+ channels:
2
+ - conda-forge
3
+ - nodefaults
4
+ dependencies:
5
+ - bs4
6
+ - coverage
7
+ - openpyxl
8
+ - pooch
9
+ - pytest
10
+ - pyyaml
11
+ - requests
12
+ - pip:
13
+ - CMIP7-data-request-api
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: CMIP7_data_request_api
3
- Version: 1.2b2
3
+ Version: 1.2.1
4
4
  Summary: A programmatic interface to the CMIP7 Data Request
5
5
  Author: James Anstey, Gaëlle Rigoudy, Martin Schupfner, Matthew Mizielinski, Daniel Ellis, Elisabeth Dingley, Marie-Pierre Moine
6
6
  License-Expression: MIT
@@ -20,6 +20,7 @@ Dynamic: license-file
20
20
 
21
21
  [![pypi](https://img.shields.io/pypi/v/CMIP7-data-request-api.svg)](https://pypi.python.org/pypi/CMIP7-data-request-api)
22
22
  [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/CMIP-Data-Request/CMIP7_DReq_Software/main?filepath=notebooks)
23
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/CMIP-Data-Request/CMIP7_DReq_Software/)
23
24
  [![NBviewer](https://raw.githubusercontent.com/jupyter/design/master/logos/Badges/nbviewer_badge.svg)](https://nbviewer.jupyter.org/github/CMIP-Data-Request/CMIP7_DReq_Software/tree/main/notebooks/)
24
25
  [![license](https://img.shields.io/github/license/CMIP-Data-Request/CMIP7_DReq_Software.svg)](https://github.com/CMIP-Data-Request/CMIP7_DReq_Software/blob/main/LICENSE)
25
26
  [![status](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
@@ -29,7 +30,7 @@ Dynamic: license-file
29
30
  Python software to interact with the [CMIP7 data request](https://wcrp-cmip.org/cmip7/cmip7-data-request/).
30
31
  It provides an API to query and utilize the information in the data request, including example scripts and notebooks showing how to use the API.
31
32
 
32
- For the **Quick Start** guide, please see below.
33
+ Please see below for the [installation guide](#installation) or how to [try it without installation](#try-it-without-installation).
33
34
 
34
35
  The Data Request Task Team encourages user feedback to help us improve the software.
35
36
  Here are some ways to provide feedback:
@@ -37,22 +38,25 @@ Here are some ways to provide feedback:
37
38
  - For more general questions or concerns, such as suggestions for new features, contribute to the Software's [github discussion forum](https://github.com/CMIP-Data-Request/CMIP7_DReq_Software/discussions).
38
39
 
39
40
 
40
- ## v1.2 Data Request release
41
+ ## v1.2.1 Data Request release
41
42
 
42
- The latest **official release** of the CMIP7 Data Request is `v1.2` (31 March 2025)
43
- Access all information about the v1.2 release [on the CMIP website](https://wcrp-cmip.org/cmip7-data-request-v1-2/).
43
+ The latest **official release** of the CMIP7 Data Request is `v1.2.1` (26 April 2025).
44
+ [Learn more about this release on the CMIP website](https://wcrp-cmip.org/cmip7-data-request-v1-2-1/).
44
45
 
45
- Please note that a technical update to the Data Request, `v1.2.1`, is planned for late April 2025.
46
- This update will affect some details such as the names of CMOR variables, without substantially changing the scientific content of the request.
47
- For further information please see the [v1.2 release page](https://wcrp-cmip.org/cmip7-data-request-v1-2/).
48
- An update of this software will follow the release of `v1.2.1`.
46
+
47
+ ## Try It Without Installation
48
+
49
+ You can launch and interact with this repository in a live environment via [Binder](https://mybinder.org/) or [Google Colab](https://colab.research.google.com/) — no installation needed, just click on one of the badges to run it in your browser:
50
+
51
+ [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/CMIP-Data-Request/CMIP7_DReq_Software/main?filepath=notebooks)
52
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/CMIP-Data-Request/CMIP7_DReq_Software/)
49
53
 
50
54
 
51
55
  ## Installation
52
56
 
53
57
  ### Quick Start
54
58
 
55
- In a python virtual environment that already has the dependencies installed, do:
59
+ In a python virtual environment or conda environment in which you want to install the package, do:
56
60
 
57
61
  ```bash
58
62
  pip install CMIP7-data-request-api
@@ -64,9 +68,14 @@ If an environment first needs to be created, you can do:
64
68
  python -m venv my_dreq_env
65
69
  source my_dreq_env/bin/activate
66
70
  pip install --upgrade pip
71
+ pip install CMIP7-data-request-api
72
+ ```
73
+
74
+ This will automatically install the dependencies, but if necessary they can be manually installed by doing:
75
+
76
+ ```bash
67
77
  wget https://raw.githubusercontent.com/CMIP-Data-Request/CMIP7_DReq_Software/refs/heads/main/requirements.txt
68
78
  pip install -r requirements.txt
69
- pip install CMIP7-data-request-api
70
79
  ```
71
80
 
72
81
  using the `requirements.txt` file from the top-level directory of this repository, which lists the package dependencies, and `my_dreq_env` can be changed to whatever environment name is preferred.
@@ -10,6 +10,7 @@ requirements.txt
10
10
  .github/workflows/pip_install.yml
11
11
  .github/workflows/publish2pypi.yml
12
12
  .github/workflows/updates.yml
13
+ binder/environment.yml
13
14
  data_request_api/.DS_Store
14
15
  data_request_api/CMIP7_data_request_api.egg-info/PKG-INFO
15
16
  data_request_api/CMIP7_data_request_api.egg-info/SOURCES.txt
@@ -131,9 +132,11 @@ notebooks/workflow_example.ipynb
131
132
  notebooks/outdir/.gitkeep
132
133
  scripts/check_consolidation.py
133
134
  scripts/check_consolidation2.py
135
+ scripts/check_consolidation_and_transformation.py
134
136
  scripts/check_variables_attributes.py
135
137
  scripts/database_transformation.py
136
138
  scripts/workflow_example.py
137
139
  scripts/workflow_example_2.py
138
- scripts/examples/requested_v1.2.json
139
- scripts/examples/variables_v1.2.json
140
+ scripts/examples/requested_v1.2.1.json
141
+ scripts/examples/variables_v1.2.1.json
142
+ scripts/sandbox/create_brand_name.py
@@ -8,6 +8,7 @@ from data_request_api.utilities import config as dreqcfg
8
8
  def main():
9
9
  parser = argparse.ArgumentParser(
10
10
  description="Config CLI",
11
+ formatter_class=argparse.RawTextHelpFormatter,
11
12
  epilog="""Arguments:
12
13
  init (or no arguments): Initialize the config file,
13
14
  i.e. create a config file with default values if it does not exist.
@@ -17,8 +18,8 @@ def main():
17
18
  help: print this help message.
18
19
 
19
20
  Examples:
20
- python -m utilities.config offline true
21
- python -m utilities.config reset""",
21
+ CMIP7_data_request_api_config offline true
22
+ CMIP7_data_request_api_config reset""",
22
23
  )
23
24
 
24
25
  if parser.prog.startswith("config"):
@@ -38,7 +39,7 @@ Examples:
38
39
  dreqcfg.CONFIG_FILE = args.cfgfile
39
40
 
40
41
  if len(args.command) == 0 or args.command[0] == "init":
41
- print("Initializing config file:")
42
+ print(f"Initializing config file: '{dreqcfg.CONFIG_FILE}'")
42
43
  dreqcfg.load_config()
43
44
  elif args.command[0] == "reset":
44
45
  print("Resetting config with defaults:")
@@ -64,7 +64,7 @@ def get_variable_size(var_info, dreq_dim_sizes, time_dims, freq_times_per_year,
64
64
  n = 24 * 12
65
65
  else:
66
66
  n = freq_times_per_year[frequency]
67
- temporal_shape = dim
67
+ temporal_shape = time_dims[dim]
68
68
  elif dim in config['dimensions']:
69
69
  # Use model-specific dimension size
70
70
  n = config['dimensions'][dim]
@@ -74,7 +74,7 @@ def get_variable_size(var_info, dreq_dim_sizes, time_dims, freq_times_per_year,
74
74
  n = dreq_dim_sizes[dim]
75
75
 
76
76
  if n is None:
77
- raise ValueError(f'No size found for dimension {dim}')
77
+ raise ValueError(f'No size found for dimension: {dim}')
78
78
 
79
79
  dim_sizes[dim] = n
80
80
 
@@ -101,7 +101,7 @@ def parse_args():
101
101
  parser.add_argument('request', type=str,
102
102
  help='json file specifying variables requested by experiment' +
103
103
  ' (output from export_dreq_lists_json, which specifies the data request version)' +
104
- ' OR can be a data request version (e.g. "v1.2") if using ')
104
+ ' OR can be a data request version (e.g. "v1.2")')
105
105
  # Optional arguments
106
106
  parser.add_argument('-v', '--variables', nargs='+', type=str,
107
107
  help='include only the specified variables in the estimate')
@@ -167,12 +167,13 @@ years: 1
167
167
  config = yaml.safe_load(f)
168
168
  print('Loaded ' + config_file)
169
169
 
170
- warning_msg = '\n * * * WARNING * * *'
171
- warning_msg += '\n These volumes are an initial estimate, to be improved in the next software version.'
172
- warning_msg += '\n They should be used with caution and verified against known data volumes.\n'
170
+ warning_msg = '\n * * * * * * * * * * * * * * * WARNING * * * * * * * * * * * * * * *'
171
+ warning_msg += '\n These volumes are an initial estimate.'
172
+ warning_msg += '\n They should be used with caution and verified against known data volumes.'
173
+ warning_msg += '\n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n'
173
174
 
174
175
  request_from_input_file = None
175
- if os.path.exists(args.request):
176
+ if os.path.isfile(args.request):
176
177
  # Argument is a file that lists requested variables
177
178
  filepath = args.request
178
179
  with open(filepath, 'r') as f:
@@ -232,8 +233,20 @@ years: 1
232
233
  if set(freq_times_per_year.keys()) != set(freqs):
233
234
  raise Exception('Times per year must be defined for all available frequencies')
234
235
 
235
- # Get available time dimensions ('time-intv', 'time-point', etc)
236
- time_dims = [rec.name for rec in dreq_tables['temporal shape'].records.values()]
236
+ # Get mapping from time dimension name to temporal shape name
237
+ # {'time1': 'time-point', 'time': 'time-intv', ... etc}
238
+ time_dims = {}
239
+ for rec in dreq_tables['temporal shape'].records.values():
240
+ shape_name = rec.name
241
+ if hasattr(rec, 'dimensions'):
242
+ assert len(rec.dimensions) == 1
243
+ link = rec.dimensions[0]
244
+ dim_rec = dreq_tables['coordinates and dimensions'].get_record(link)
245
+ dim_name = dim_rec.name
246
+ else:
247
+ dim_name = 'None'
248
+ assert dim_name not in time_dims, 'time dimension names are not unique'
249
+ time_dims[dim_name] = shape_name
237
250
 
238
251
  # Get metadata for variables
239
252
  variables = dq.get_variables_metadata(
@@ -307,7 +320,11 @@ years: 1
307
320
  for expt in expts:
308
321
  expt_rec = expt_records[expt]
309
322
 
310
- num_years = expt_rec.size_years_minimum
323
+ if hasattr(expt_rec, 'size_years_minimum'):
324
+ num_years = expt_rec.size_years_minimum
325
+ else:
326
+ num_years = 100
327
+ print(f'Warning: number of years not found for experiment {expt}, assuming size_years_minimum = {num_years}')
311
328
  num_ensem = 1
312
329
 
313
330
  # Loop over priority levels of requeste variables
@@ -339,7 +356,12 @@ years: 1
339
356
  # Assume this is a climatology, so don't multiply by number of years
340
357
  pass
341
358
  else:
342
- assert temporal_shape in ['time-intv', 'time-point', 'monthly-mean-daily-stat'], \
359
+ valid_shapes = ['time-intv', 'time-point', 'monthly-mean-daily-stat']
360
+ version_tuple = dq.get_dreq_version_tuple(use_dreq_version)
361
+ if version_tuple[:2] < (1, 2):
362
+ # Prior to v1.2, monthly-mean-daily-stat was called monthly-mean-stat
363
+ valid_shapes.append('monthly-mean-stat')
364
+ assert temporal_shape in valid_shapes, \
343
365
  'Unknown temporal shape: ' + str(temporal_shape)
344
366
  # Multiply the 1-year size by the minimum number of request years for this experiment
345
367
  size *= num_years
@@ -149,18 +149,19 @@ def main():
149
149
 
150
150
  # Get metadata for variables
151
151
  all_var_info = dq.get_variables_metadata(
152
- base,
152
+ base, use_dreq_version,
153
153
  compound_names=all_var_names,
154
- use_dreq_version=use_dreq_version # TO DEPRECATE
154
+ # use_dreq_version=use_dreq_version # TO DEPRECATE
155
155
  )
156
156
 
157
157
  # Write output file(s)
158
158
  for filepath in args.variables_metadata:
159
159
  dq.write_variables_metadata(
160
160
  all_var_info,
161
+ use_dreq_version,
161
162
  filepath,
162
163
  api_version=data_request_api.version,
163
- use_dreq_version=use_dreq_version,
164
+ # use_dreq_version=use_dreq_version,
164
165
  content_path=dc._dreq_content_loaded['json_path']
165
166
  )
166
167
 
@@ -122,7 +122,7 @@ def _apply_hard_fixes(data):
122
122
  return data
123
123
 
124
124
 
125
- def _filter_references(val, key, table, rid):
125
+ def _filter_references(val, key, table, rid, dtype=None):
126
126
  """
127
127
  Filters lists of or strings with comma-separated references to other records.
128
128
  """
@@ -142,8 +142,8 @@ def _filter_references(val, key, table, rid):
142
142
  f"'{table}': Filtered {len(val) - len(filtered)} of {len(val)}"
143
143
  f" references for '{key}' of record '{rid}'."
144
144
  )
145
- return filtered
146
- elif isinstance(val, str) and "rec" in val:
145
+ return _fix_dtype(key, filtered, dtype)
146
+ elif isinstance(val, str) and val.startswith("rec"):
147
147
  if "," in val:
148
148
  vallist = [v.strip() for v in val.split(",")]
149
149
  filtered = [v for v in vallist if v not in filtered_records]
@@ -157,14 +157,14 @@ def _filter_references(val, key, table, rid):
157
157
  f"'{table}': Filtered {len(vallist) - len(filtered)} of"
158
158
  f" {len(vallist)} references for '{key}' of record '{rid}'."
159
159
  )
160
- return ",".join(filtered)
160
+ return _fix_dtype(key, ",".join(filtered), dtype)
161
161
  elif val.strip() in filtered_records:
162
162
  logger.warning(f"'{table}': Filtered the only reference for '{key}' of record '{rid}'.")
163
- return ""
163
+ return _fix_dtype(key, "", dtype)
164
164
  else:
165
- return val.strip()
165
+ return _fix_dtype(key, _fix_str(val), dtype)
166
166
  else:
167
- return val
167
+ return _fix_dtype(key, _fix_str(val), dtype)
168
168
 
169
169
 
170
170
  def _gen_rid_uid_map(data):
@@ -194,6 +194,61 @@ def _gen_rid_uid_map(data):
194
194
  return rid_uid_map
195
195
 
196
196
 
197
+ def _fix_str(var):
198
+ """Adds missing space after commas and strips whitespace from strings."""
199
+ if isinstance(var, str):
200
+ return re.sub(r",(?=\S)", ", ", var).strip()
201
+ else:
202
+ return var
203
+
204
+
205
+ def _fix_str_nested(data):
206
+ """Adds missing space after commas and strips whitespace from strings in nested dictionary."""
207
+ sub = re.sub
208
+ pattern = r",(?=\S)"
209
+ for table in data.values():
210
+ for record in table["records"].values():
211
+ record.update({k: sub(pattern, ", ", v).strip() if isinstance(v, str) else v for k, v in record.items()})
212
+
213
+
214
+ def _fix_dtype(fkey, fval, dtype=None):
215
+ """Fixes data types for record fields."""
216
+ logger = get_logger()
217
+
218
+ if dtype is None:
219
+ return fval
220
+ elif dtype == "str":
221
+ logger.debug(f"Consolidate export: Converting field '{fkey}' ('{fval}') to string.")
222
+ return str(fval)
223
+ elif dtype == "int":
224
+ logger.debug(f"Consolidate export: Converting field '{fkey}' ('{fval}') to int.")
225
+ return int(fval)
226
+ elif dtype == "float":
227
+ logger.debug(f"Consolidate export: Converting field '{fkey}' ('{fval}') to float.")
228
+ return float(fval)
229
+ elif dtype == "listofstr":
230
+ logger.debug(f"Consolidate export: Converting field '{fkey}' to a list of strings.")
231
+ if isinstance(fval, list):
232
+ return [str(v) for v in fval]
233
+ else:
234
+ return [str(fval)]
235
+ elif dtype == "listofint":
236
+ logger.debug(f"Consolidate export: Converting field '{fkey}' to a list of ints.")
237
+ if isinstance(fval, list):
238
+ return [int(v) for v in fval]
239
+ else:
240
+ return [int(fval)]
241
+ elif dtype == "listoffloat":
242
+ logger.debug(f"Consolidate export: Converting field '{fkey}' to a list of floats.")
243
+ if isinstance(fval, list):
244
+ return [float(v) for v in fval]
245
+ else:
246
+ return [float(fval)]
247
+ else:
248
+ logger.warning(f"Consolidate export: Unsupported data type '{dtype}' for field '{fkey}'.")
249
+ return fval
250
+
251
+
197
252
  def map_data(data, mapping_table, version, **kwargs):
198
253
  """
199
254
  Maps the data to the one-base structure using the mapping table.
@@ -310,7 +365,11 @@ def map_data(data, mapping_table, version, **kwargs):
310
365
  "records": {
311
366
  record_id: {
312
367
  mapinfo["internal_consistency"].get(reckey, reckey): _filter_references(
313
- recvalue, reckey, table, record_id
368
+ recvalue,
369
+ reckey,
370
+ table,
371
+ record_id,
372
+ mapinfo["field_dtypes"].get(mapinfo["internal_consistency"].get(reckey, reckey), None),
314
373
  )
315
374
  for reckey, recvalue in record.items()
316
375
  if reckey not in mapinfo["drop_keys"]
@@ -525,6 +584,9 @@ def map_data(data, mapping_table, version, **kwargs):
525
584
  # Consistency fixes
526
585
  mapped_data = next(iter(data.values()))
527
586
  mapped_data = _apply_consistency_fixes(mapped_data)
587
+ # String fixes
588
+ logger.debug("Consolidation: Removing / Adding (un)necessary whitespace to strings.")
589
+ _fix_str_nested(mapped_data)
528
590
  mapped_data["version"] = version
529
591
  return {"Data Request": mapped_data}
530
592
  else:
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python
2
2
 
3
-
3
+ import atexit
4
4
  import json
5
5
  import os
6
6
  import re
@@ -65,6 +65,10 @@ except KeyError:
65
65
 
66
66
  _dreq_content_loaded = {}
67
67
 
68
+ # Internal flag used to determine whether a warning on API version can be issued
69
+ # (Purpose is to prevent the warning being issued more than once per session)
70
+ _CHECK_API_VERSION = True
71
+
68
72
 
69
73
  def _parse_version(version):
70
74
  """Parse a version tag and return a tuple for sorting.
@@ -121,9 +125,6 @@ def get_cached(**kwargs):
121
125
  json_export = _json_raw
122
126
  elif kwargs["export"] == "release":
123
127
  json_export = _json_release
124
- else:
125
- warnings.warn(f"Unknown export type '{kwargs['export']}'. Defaulting to 'release'.")
126
- json_export = _json_release
127
128
  local_versions = [
128
129
  name for name in os.listdir(_dreq_res) if os.path.isfile(os.path.join(_dreq_res, name, json_export))
129
130
  ]
@@ -293,6 +294,7 @@ def get_versions(target="tags", **kwargs):
293
294
  """
294
295
  global versions
295
296
  global _versions_retrieved_last
297
+ global _CHECK_API_VERSION
296
298
 
297
299
  if target not in ["tags", "branches"]:
298
300
  raise ValueError("target must be 'tags' or 'branches'.")
@@ -314,7 +316,14 @@ def get_versions(target="tags", **kwargs):
314
316
  if target == "tags" and "dev" not in versions[target]:
315
317
  versions[target].append("dev")
316
318
 
317
- # List tags hosted on GitHub
319
+ if kwargs['check_api_version'] and not kwargs["offline"]:
320
+ # Warn user if the API version is not the latest one available on PyPI
321
+ if _CHECK_API_VERSION:
322
+ atexit.register(dreqcfg.check_api_version)
323
+ # Set flag to prevent the same warning being shown more than once
324
+ _CHECK_API_VERSION = False
325
+
326
+ # List tags of dreq versions hosted on GitHub
318
327
  return versions[target]
319
328
 
320
329
 
@@ -393,7 +402,7 @@ def retrieve(version="latest_stable", **kwargs):
393
402
  if versions == [None] or not versions:
394
403
  raise ValueError(f"Version '{version}' not found.")
395
404
  elif version in ["v1.0alpha"] and "export" in kwargs and kwargs["export"] == "raw":
396
- warnings.warn(f"For version '{version}' no raw export exists.")
405
+ warnings.warn(f"For version '{version}' no raw export exists. Defaulting to release export.")
397
406
 
398
407
  json_paths = dict()
399
408
  for version in versions:
@@ -406,8 +415,6 @@ def retrieve(version="latest_stable", **kwargs):
406
415
  json_export = _json_release
407
416
  elif kwargs["export"] == "raw":
408
417
  json_export = _json_raw
409
- else:
410
- warnings.warn(f"Unknown export type '{kwargs['export']}'.")
411
418
  elif _version_pattern.match(version):
412
419
  json_export = _json_release
413
420
  else:
@@ -544,10 +551,6 @@ def delete(version="all", keep_latest=False, **kwargs):
544
551
  cached_files = [os.path.join(_dreq_res, v, _json_raw) for v in local_versions]
545
552
  elif kwargs["export"] == "release":
546
553
  cached_files = [os.path.join(_dreq_res, v, _json_release) for v in local_versions]
547
- else:
548
- # Since files are to be deleted, not defaulting to "release" but rather
549
- # raising a ValueError
550
- raise ValueError(f"Unknown export type '{kwargs['export']}'.")
551
554
 
552
555
  # Delete files
553
556
  for f in cached_files:
@@ -290,11 +290,12 @@ def tidy_content(content, record_to_uid_index):
290
290
  to_remove_entries[subelt][(record_id, uid)] += 1
291
291
  content_string = tmp_content_string
292
292
  content[content_subelt] = json.loads(content_string)
293
- if "opportunities" in to_remove_entries:
294
- to_remove = [elt for (elt, nb) in to_remove_entries["opportunities"].items() if nb == len_list_content]
295
- for record_id, _ in to_remove:
296
- del record_to_uid_index["opportunities"][record_id]
297
- del to_remove_entries["opportunities"]
293
+ for content_subelt in ["opportunities", "coordinates_and_dimensions"]:
294
+ if content_subelt in to_remove_entries:
295
+ to_remove = [elt for (elt, nb) in to_remove_entries[content_subelt].items() if nb == len_list_content]
296
+ for record_id, _ in to_remove:
297
+ del record_to_uid_index[content_subelt][record_id]
298
+ del to_remove_entries[content_subelt]
298
299
  for (subelt, to_remove) in to_remove_entries.items():
299
300
  to_remove = [elt for (elt, nb) in to_remove.items() if nb == len_list_content]
300
301
  for (record_id, uid) in to_remove: