hdx-python-utilities 4.0.4__tar.gz → 4.0.6__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_utilities-4.0.4 → hdx_python_utilities-4.0.6}/PKG-INFO +76 -1
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/README.md +75 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/_version.py +2 -2
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/base_downloader.py +5 -5
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/dictandlist.py +1 -1
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/downloader.py +17 -15
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/frictionless_wrapper.py +2 -1
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/retriever.py +6 -6
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/saver.py +19 -25
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/url.py +1 -1
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_downloader.py +12 -5
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_saver.py +24 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/uv.lock +453 -2
- hdx_python_utilities-4.0.4/CONTRIBUTING.md +0 -68
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/.github/workflows/publish-test.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/.github/workflows/publish.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/.github/workflows/run-python-tests.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/.gitignore +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/.pre-commit-config.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/LICENSE +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/documentation/.readthedocs.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/documentation/index.md +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/documentation/mkdocs.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/pyproject.toml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/__init__.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/compare.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/dateparse.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/easy_logging.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/email.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/encoding.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/error_handler.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/errors_onexit.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/file_hashing.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/html.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/loader.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/matching.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/path.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/session.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/state.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/text.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/useragent.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/uuid.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/zip_crc.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/compare/test_csv_processing.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/compare/test_csv_processing2.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/empty.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/hdx_config.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/hdx_config.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/hdx_email_configuration.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/hdx_email_configuration.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/json_csv.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/logging_config.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/logging_config.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/project_configuration.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/project_configuration.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/smtp_config.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/smtp_config.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/user_agent_config.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/user_agent_config2.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/user_agent_config3.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/config/user_agent_config_wrong.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/basicauth.txt +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/bearertoken.txt +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/extra_params.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/extra_params.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/extra_params_tree.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/test_csv_processing.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/test_csv_processing_blanks.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/test_data.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/test_data.xlsx +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/test_data1.csv/empty.txt +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/test_data2.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/test_json_processing.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/test_xls_processing.xls +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/downloader/test_xlsx_processing.xlsx +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/file_hashing/bad_header.zip +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/file_hashing/bad_index.xlsx +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/file_hashing/empty.zip +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/file_hashing/test.xlsx +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/file_hashing/test_shapefile.zip +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/file_hashing/valid_sig_invalid_body.zip +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/html/response.html +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/loader/empty.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/loader/empty.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/loader/empty_list.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/retriever/fallbacks/test.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/retriever/fallbacks/test.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/retriever/fallbacks/test.txt +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/retriever/fallbacks/test.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/retriever/retriever-test.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/retriever/test.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/retriever/test.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/retriever/test.txt +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/retriever/test.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/retriever/test_hxl.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/out.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/out.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/out2.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/out2.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/out5.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/out6.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/out7.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/out8.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/out8.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/pretty-false_sortkeys-false.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/pretty-false_sortkeys-false.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/pretty-false_sortkeys-true.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/pretty-false_sortkeys-true.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/pretty-true_sortkeys-false.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/pretty-true_sortkeys-false.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/pretty-true_sortkeys-true.json +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/saver/pretty-true_sortkeys-true.yaml +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/state/analysis_dates.txt +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/state/last_build_date.txt +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/fixtures/test_data.csv +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/conftest.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_compare.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_dateparse.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_dictandlist.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_easy_logging.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_email.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_encoding.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_error_handler.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_file_hashing.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_html.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_loader.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_matching.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_path.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_retriever.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_state.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_text.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_url.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_useragent.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_uuid.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_zip_crc.py +0 -0
- {hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hdx-python-utilities
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.6
|
|
4
4
|
Summary: HDX Python Utilities for streaming tabular data, date and time handling and other helpful functions
|
|
5
5
|
Project-URL: Homepage, https://github.com/OCHA-DAP/hdx-python-utilities
|
|
6
6
|
Author-email: Michael Rans <rans@email.com>
|
|
@@ -83,3 +83,78 @@ For more information, please read the [documentation](https://hdx-python-utiliti
|
|
|
83
83
|
|
|
84
84
|
This library is part of the [Humanitarian Data Exchange](https://data.humdata.org/) (HDX) project. If you have
|
|
85
85
|
humanitarian related data, please upload your datasets to HDX.
|
|
86
|
+
|
|
87
|
+
# Development
|
|
88
|
+
|
|
89
|
+
## Environment
|
|
90
|
+
|
|
91
|
+
Development is currently done using Python 3.13. The environment can be created with:
|
|
92
|
+
|
|
93
|
+
```shell
|
|
94
|
+
uv sync
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
This creates a .venv folder with the versions specified in the project's uv.lock file.
|
|
98
|
+
|
|
99
|
+
### Pre-commit
|
|
100
|
+
|
|
101
|
+
pre-commit will be installed when syncing uv. It is run every time you make a git
|
|
102
|
+
commit if you call it like this:
|
|
103
|
+
|
|
104
|
+
```shell
|
|
105
|
+
pre-commit install
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
With pre-commit, all code is formatted according to
|
|
109
|
+
[ruff](https://docs.astral.sh/ruff/) guidelines.
|
|
110
|
+
|
|
111
|
+
To check if your changes pass pre-commit without committing, run:
|
|
112
|
+
|
|
113
|
+
```shell
|
|
114
|
+
pre-commit run --all-files
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Packages
|
|
118
|
+
|
|
119
|
+
[uv](https://github.com/astral-sh/uv) is used for package management. If
|
|
120
|
+
you’ve introduced a new package to the source code (i.e. anywhere in `src/`),
|
|
121
|
+
please add it to the `project.dependencies` section of `pyproject.toml` with
|
|
122
|
+
any known version constraints.
|
|
123
|
+
|
|
124
|
+
To add packages required only for testing, add them to the
|
|
125
|
+
`[dependency-groups]`.
|
|
126
|
+
|
|
127
|
+
Any changes to the dependencies will be automatically reflected in
|
|
128
|
+
`uv.lock` with `pre-commit`, but you can re-generate the files without committing by
|
|
129
|
+
executing:
|
|
130
|
+
|
|
131
|
+
```shell
|
|
132
|
+
uv lock --upgrade
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Project
|
|
136
|
+
|
|
137
|
+
[uv](https://github.com/astral-sh/uv) is used for project management. The project can be
|
|
138
|
+
built using:
|
|
139
|
+
|
|
140
|
+
```shell
|
|
141
|
+
uv build
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Linting and syntax checking can be run with:
|
|
145
|
+
|
|
146
|
+
```shell
|
|
147
|
+
uv run ruff check
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
To run the tests and view coverage, execute:
|
|
151
|
+
|
|
152
|
+
```shell
|
|
153
|
+
uv run pytest
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Documentation
|
|
157
|
+
|
|
158
|
+
The documentation, including API documentation, is generated using ReadtheDocs and
|
|
159
|
+
MkDocs with Material. As you change the source code, remember to update the
|
|
160
|
+
documentation at `documentation/index.md`.
|
|
@@ -30,3 +30,78 @@ For more information, please read the [documentation](https://hdx-python-utiliti
|
|
|
30
30
|
|
|
31
31
|
This library is part of the [Humanitarian Data Exchange](https://data.humdata.org/) (HDX) project. If you have
|
|
32
32
|
humanitarian related data, please upload your datasets to HDX.
|
|
33
|
+
|
|
34
|
+
# Development
|
|
35
|
+
|
|
36
|
+
## Environment
|
|
37
|
+
|
|
38
|
+
Development is currently done using Python 3.13. The environment can be created with:
|
|
39
|
+
|
|
40
|
+
```shell
|
|
41
|
+
uv sync
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This creates a .venv folder with the versions specified in the project's uv.lock file.
|
|
45
|
+
|
|
46
|
+
### Pre-commit
|
|
47
|
+
|
|
48
|
+
pre-commit will be installed when syncing uv. It is run every time you make a git
|
|
49
|
+
commit if you call it like this:
|
|
50
|
+
|
|
51
|
+
```shell
|
|
52
|
+
pre-commit install
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
With pre-commit, all code is formatted according to
|
|
56
|
+
[ruff](https://docs.astral.sh/ruff/) guidelines.
|
|
57
|
+
|
|
58
|
+
To check if your changes pass pre-commit without committing, run:
|
|
59
|
+
|
|
60
|
+
```shell
|
|
61
|
+
pre-commit run --all-files
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Packages
|
|
65
|
+
|
|
66
|
+
[uv](https://github.com/astral-sh/uv) is used for package management. If
|
|
67
|
+
you’ve introduced a new package to the source code (i.e. anywhere in `src/`),
|
|
68
|
+
please add it to the `project.dependencies` section of `pyproject.toml` with
|
|
69
|
+
any known version constraints.
|
|
70
|
+
|
|
71
|
+
To add packages required only for testing, add them to the
|
|
72
|
+
`[dependency-groups]`.
|
|
73
|
+
|
|
74
|
+
Any changes to the dependencies will be automatically reflected in
|
|
75
|
+
`uv.lock` with `pre-commit`, but you can re-generate the files without committing by
|
|
76
|
+
executing:
|
|
77
|
+
|
|
78
|
+
```shell
|
|
79
|
+
uv lock --upgrade
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Project
|
|
83
|
+
|
|
84
|
+
[uv](https://github.com/astral-sh/uv) is used for project management. The project can be
|
|
85
|
+
built using:
|
|
86
|
+
|
|
87
|
+
```shell
|
|
88
|
+
uv build
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Linting and syntax checking can be run with:
|
|
92
|
+
|
|
93
|
+
```shell
|
|
94
|
+
uv run ruff check
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
To run the tests and view coverage, execute:
|
|
98
|
+
|
|
99
|
+
```shell
|
|
100
|
+
uv run pytest
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Documentation
|
|
104
|
+
|
|
105
|
+
The documentation, including API documentation, is generated using ReadtheDocs and
|
|
106
|
+
MkDocs with Material. As you change the source code, remember to update the
|
|
107
|
+
documentation at `documentation/index.md`.
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '4.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (4, 0,
|
|
31
|
+
__version__ = version = '4.0.6'
|
|
32
|
+
__version_tuple__ = version_tuple = (4, 0, 6)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
{hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/base_downloader.py
RENAMED
|
@@ -35,7 +35,7 @@ class BaseDownload(ABC):
|
|
|
35
35
|
"""
|
|
36
36
|
|
|
37
37
|
@abstractmethod
|
|
38
|
-
def download_file(self, url: str, *args: Any, **kwargs: Any) -> Path:
|
|
38
|
+
def download_file(self, url: Path | str, *args: Any, **kwargs: Any) -> Path:
|
|
39
39
|
"""Download file from url.
|
|
40
40
|
|
|
41
41
|
Args:
|
|
@@ -48,7 +48,7 @@ class BaseDownload(ABC):
|
|
|
48
48
|
"""
|
|
49
49
|
|
|
50
50
|
@abstractmethod
|
|
51
|
-
def download_text(self, url: str, *args: Any, **kwargs: Any) -> str:
|
|
51
|
+
def download_text(self, url: Path | str, *args: Any, **kwargs: Any) -> str:
|
|
52
52
|
"""Download text from url.
|
|
53
53
|
|
|
54
54
|
Args:
|
|
@@ -61,7 +61,7 @@ class BaseDownload(ABC):
|
|
|
61
61
|
"""
|
|
62
62
|
|
|
63
63
|
@abstractmethod
|
|
64
|
-
def download_yaml(self, url: str, *args: Any, **kwargs: Any) -> Any:
|
|
64
|
+
def download_yaml(self, url: Path | str, *args: Any, **kwargs: Any) -> Any:
|
|
65
65
|
"""Download YAML from url.
|
|
66
66
|
|
|
67
67
|
Args:
|
|
@@ -74,7 +74,7 @@ class BaseDownload(ABC):
|
|
|
74
74
|
"""
|
|
75
75
|
|
|
76
76
|
@abstractmethod
|
|
77
|
-
def download_json(self, url: str, *args: Any, **kwargs: Any) -> Any:
|
|
77
|
+
def download_json(self, url: Path | str, *args: Any, **kwargs: Any) -> Any:
|
|
78
78
|
"""Download JSON from url.
|
|
79
79
|
|
|
80
80
|
Args:
|
|
@@ -89,7 +89,7 @@ class BaseDownload(ABC):
|
|
|
89
89
|
@abstractmethod
|
|
90
90
|
def get_tabular_rows(
|
|
91
91
|
self,
|
|
92
|
-
url: str | Sequence[str],
|
|
92
|
+
url: Path | str | Sequence[str],
|
|
93
93
|
has_hxl: bool = False,
|
|
94
94
|
headers: int | Sequence[int] | Sequence[str] = 1,
|
|
95
95
|
dict_form: bool = False,
|
|
@@ -129,7 +129,7 @@ class Download(BaseDownload):
|
|
|
129
129
|
"""
|
|
130
130
|
self.close()
|
|
131
131
|
|
|
132
|
-
def get_full_url(self, url: str) -> str:
|
|
132
|
+
def get_full_url(self, url: Path | str) -> str:
|
|
133
133
|
"""Get full url including any additional parameters added to the session.
|
|
134
134
|
|
|
135
135
|
Args:
|
|
@@ -193,14 +193,16 @@ class Download(BaseDownload):
|
|
|
193
193
|
self.close_response()
|
|
194
194
|
self.response = None
|
|
195
195
|
try:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
196
|
+
if isinstance(url, Path):
|
|
197
|
+
url = url.resolve().as_uri()
|
|
198
|
+
else:
|
|
199
|
+
spliturl = urlsplit(url)
|
|
200
|
+
if not spliturl.scheme:
|
|
201
|
+
if isfile(url):
|
|
202
|
+
url = Path(url).resolve().as_uri()
|
|
203
|
+
else:
|
|
204
|
+
spliturl = spliturl._replace(scheme="https")
|
|
205
|
+
url = urlunsplit(spliturl)
|
|
204
206
|
if post:
|
|
205
207
|
full_url, parameters = get_url_params_for_post(url, parameters)
|
|
206
208
|
if json_string:
|
|
@@ -671,7 +673,7 @@ class Download(BaseDownload):
|
|
|
671
673
|
|
|
672
674
|
def get_tabular_rows(
|
|
673
675
|
self,
|
|
674
|
-
url: str | Sequence[str],
|
|
676
|
+
url: Path | str | Sequence[str],
|
|
675
677
|
has_hxl: bool = False,
|
|
676
678
|
headers: int | Sequence[int] | Sequence[str] = 1,
|
|
677
679
|
dict_form: bool = False,
|
|
@@ -778,7 +780,7 @@ class Download(BaseDownload):
|
|
|
778
780
|
|
|
779
781
|
def get_tabular_rows_as_list(
|
|
780
782
|
self,
|
|
781
|
-
url: str | Sequence[str],
|
|
783
|
+
url: Path | str | Sequence[str],
|
|
782
784
|
has_hxl: bool = False,
|
|
783
785
|
headers: int | Sequence[int] | Sequence[str] = 1,
|
|
784
786
|
include_headers: bool = True,
|
|
@@ -854,7 +856,7 @@ class Download(BaseDownload):
|
|
|
854
856
|
|
|
855
857
|
def get_tabular_rows_as_dict(
|
|
856
858
|
self,
|
|
857
|
-
url: str | Sequence[str],
|
|
859
|
+
url: Path | str | Sequence[str],
|
|
858
860
|
has_hxl: bool = False,
|
|
859
861
|
headers: int | Sequence[int] | Sequence[str] = 1,
|
|
860
862
|
ignore_blank_rows: bool = True,
|
|
@@ -928,7 +930,7 @@ class Download(BaseDownload):
|
|
|
928
930
|
|
|
929
931
|
def download_tabular_key_value(
|
|
930
932
|
self,
|
|
931
|
-
url: str | Sequence[str],
|
|
933
|
+
url: Path | str | Sequence[str],
|
|
932
934
|
has_hxl: bool = False,
|
|
933
935
|
headers: int | Sequence[int] | Sequence[str] = 1,
|
|
934
936
|
include_headers: bool = True,
|
|
@@ -1008,7 +1010,7 @@ class Download(BaseDownload):
|
|
|
1008
1010
|
|
|
1009
1011
|
def download_tabular_rows_as_dicts(
|
|
1010
1012
|
self,
|
|
1011
|
-
url: str | Sequence[str],
|
|
1013
|
+
url: Path | str | Sequence[str],
|
|
1012
1014
|
has_hxl: bool = False,
|
|
1013
1015
|
headers: int | Sequence[int] | Sequence[str] = 1,
|
|
1014
1016
|
keycolumn: int = 1,
|
|
@@ -1092,7 +1094,7 @@ class Download(BaseDownload):
|
|
|
1092
1094
|
|
|
1093
1095
|
def download_tabular_cols_as_dicts(
|
|
1094
1096
|
self,
|
|
1095
|
-
url: str | Sequence[str],
|
|
1097
|
+
url: Path | str | Sequence[str],
|
|
1096
1098
|
has_hxl: bool = False,
|
|
1097
1099
|
headers: int | Sequence[int] | Sequence[str] = 1,
|
|
1098
1100
|
keycolumn: int = 1,
|
{hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/src/hdx/utilities/frictionless_wrapper.py
RENAMED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Frictionless wrapper"""
|
|
2
2
|
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
from typing import Any
|
|
4
5
|
|
|
5
6
|
import requests
|
|
@@ -119,7 +120,7 @@ def get_frictionless_dialect(
|
|
|
119
120
|
|
|
120
121
|
|
|
121
122
|
def get_frictionless_tableresource(
|
|
122
|
-
url: str | None = None,
|
|
123
|
+
url: Path | str | None = None,
|
|
123
124
|
ignore_blank_rows: bool = True,
|
|
124
125
|
infer_types: bool = False,
|
|
125
126
|
session: requests.Session | None = None,
|
|
@@ -120,7 +120,7 @@ class Retrieve(BaseDownload):
|
|
|
120
120
|
|
|
121
121
|
def get_filename(
|
|
122
122
|
self,
|
|
123
|
-
url: str,
|
|
123
|
+
url: Path | str,
|
|
124
124
|
filename: str | None = None,
|
|
125
125
|
possible_extensions: tuple[str, ...] = tuple(),
|
|
126
126
|
**kwargs: Any,
|
|
@@ -180,7 +180,7 @@ class Retrieve(BaseDownload):
|
|
|
180
180
|
|
|
181
181
|
def download_file(
|
|
182
182
|
self,
|
|
183
|
-
url: str,
|
|
183
|
+
url: Path | str,
|
|
184
184
|
filename: str | None = None,
|
|
185
185
|
logstr: str | None = None,
|
|
186
186
|
fallback: bool = False,
|
|
@@ -231,7 +231,7 @@ class Retrieve(BaseDownload):
|
|
|
231
231
|
|
|
232
232
|
def download_text(
|
|
233
233
|
self,
|
|
234
|
-
url: str,
|
|
234
|
+
url: Path | str,
|
|
235
235
|
filename: str | None = None,
|
|
236
236
|
logstr: str | None = None,
|
|
237
237
|
fallback: bool = False,
|
|
@@ -282,7 +282,7 @@ class Retrieve(BaseDownload):
|
|
|
282
282
|
|
|
283
283
|
def download_yaml(
|
|
284
284
|
self,
|
|
285
|
-
url: str,
|
|
285
|
+
url: Path | str,
|
|
286
286
|
filename: str | None = None,
|
|
287
287
|
logstr: str | None = None,
|
|
288
288
|
fallback: bool = False,
|
|
@@ -333,7 +333,7 @@ class Retrieve(BaseDownload):
|
|
|
333
333
|
|
|
334
334
|
def download_json(
|
|
335
335
|
self,
|
|
336
|
-
url: str,
|
|
336
|
+
url: Path | str,
|
|
337
337
|
filename: str | None = None,
|
|
338
338
|
logstr: str | None = None,
|
|
339
339
|
fallback: bool = False,
|
|
@@ -384,7 +384,7 @@ class Retrieve(BaseDownload):
|
|
|
384
384
|
|
|
385
385
|
def get_tabular_rows(
|
|
386
386
|
self,
|
|
387
|
-
url: str | Sequence[str],
|
|
387
|
+
url: Path | str | Sequence[str],
|
|
388
388
|
has_hxl: bool = False,
|
|
389
389
|
headers: int | Sequence[int] | Sequence[str] = 1,
|
|
390
390
|
dict_form: bool = False,
|
|
@@ -281,10 +281,13 @@ def save_iterable(
|
|
|
281
281
|
row_function: Callable[[dict], dict | None] | None = None,
|
|
282
282
|
no_empty: bool = True,
|
|
283
283
|
) -> list:
|
|
284
|
-
"""Save an iterable of rows in dict or list form to a csv.
|
|
284
|
+
"""Save an iterable of rows in dict or list form to a csv. The headers
|
|
285
285
|
argument is either a row number (rows start counting at 1), or the actual
|
|
286
|
-
headers defined as a list of strings
|
|
287
|
-
|
|
286
|
+
headers defined as a list of strings, the order of which defines the column order.
|
|
287
|
+
Columns not named in that list of strings will be dropped. If headers is not set,
|
|
288
|
+
all rows will be treated as containing values. The columns argument defines which
|
|
289
|
+
columns will be output. It can be used in conjunction with an integer headers with
|
|
290
|
+
columns selecting the columns and hedders selecting the starting row.
|
|
288
291
|
|
|
289
292
|
Args:
|
|
290
293
|
filepath: Path to write to
|
|
@@ -327,32 +330,23 @@ def save_iterable(
|
|
|
327
330
|
if isinstance(row, dict):
|
|
328
331
|
has_header = True
|
|
329
332
|
row = row_function(row)
|
|
333
|
+
while row is None:
|
|
334
|
+
row = next(rows)
|
|
335
|
+
row = row_function(row)
|
|
330
336
|
if columns:
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
for column in columns:
|
|
334
|
-
if column in row:
|
|
335
|
-
newrow[column] = row[column]
|
|
336
|
-
newrows.append(newrow)
|
|
337
|
-
for row in rows:
|
|
338
|
-
row = row_function(row)
|
|
339
|
-
if row is None:
|
|
340
|
-
continue
|
|
341
|
-
newrow = {}
|
|
342
|
-
for column in columns:
|
|
343
|
-
if column in row:
|
|
344
|
-
newrow[column] = row[column]
|
|
345
|
-
newrows.append(newrow)
|
|
337
|
+
row = {k: row[k] for k in columns if k in row}
|
|
338
|
+
newrows.append(row)
|
|
346
339
|
if headers is None:
|
|
347
340
|
headers = columns
|
|
348
341
|
else:
|
|
349
|
-
if
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
342
|
+
if headers and isinstance(headers, list):
|
|
343
|
+
row = {k: row.get(k) for k in headers}
|
|
344
|
+
newrows.append(row)
|
|
345
|
+
for row in rows:
|
|
346
|
+
row = row_function(row)
|
|
347
|
+
if row is None:
|
|
348
|
+
continue
|
|
349
|
+
newrows.append(row)
|
|
356
350
|
else:
|
|
357
351
|
if headers is None:
|
|
358
352
|
headers = 1
|
{hdx_python_utilities-4.0.4 → hdx_python_utilities-4.0.6}/tests/hdx/utilities/test_downloader.py
RENAMED
|
@@ -48,6 +48,10 @@ class TestDownloader:
|
|
|
48
48
|
def fixturefile(self, downloaderfolder):
|
|
49
49
|
return downloaderfolder / "extra_params_tree.yaml"
|
|
50
50
|
|
|
51
|
+
@pytest.fixture(scope="class")
|
|
52
|
+
def fixturepath(self, downloaderfolder):
|
|
53
|
+
return downloaderfolder / "test_csv_processing.csv"
|
|
54
|
+
|
|
51
55
|
@pytest.fixture(scope="class")
|
|
52
56
|
def fixtureurlexcel(self):
|
|
53
57
|
return "https://raw.githubusercontent.com/OCHA-DAP/hdx-python-utilities/main/tests/fixtures/downloader/test_data.xlsx"
|
|
@@ -595,7 +599,9 @@ class TestDownloader:
|
|
|
595
599
|
{"la1": "gas", "ha1": "2", "ba1": "6.5", "ma1": "'n/a'"},
|
|
596
600
|
]
|
|
597
601
|
|
|
598
|
-
def test_get_tabular_rows(
|
|
602
|
+
def test_get_tabular_rows(
|
|
603
|
+
self, fixturepath, fixtureprocessurl, fixtureprocessurlblank
|
|
604
|
+
):
|
|
599
605
|
with Download() as downloader:
|
|
600
606
|
expected = [
|
|
601
607
|
["la1", "ha1", "ba1", "ma1"],
|
|
@@ -604,6 +610,9 @@ class TestDownloader:
|
|
|
604
610
|
["gas", "2", "6.5", "'n/a'"],
|
|
605
611
|
]
|
|
606
612
|
expected_headers = expected[0]
|
|
613
|
+
headers, iterator = downloader.get_tabular_rows(fixturepath)
|
|
614
|
+
assert headers == expected_headers
|
|
615
|
+
assert list(iterator) == expected[1:]
|
|
607
616
|
headers, iterator = downloader.get_tabular_rows(fixtureprocessurl)
|
|
608
617
|
assert headers == expected_headers
|
|
609
618
|
assert list(iterator) == expected[1:]
|
|
@@ -1271,11 +1280,9 @@ class TestDownloader:
|
|
|
1271
1280
|
["AFG", "Afghanistan", 38041754],
|
|
1272
1281
|
]
|
|
1273
1282
|
|
|
1274
|
-
def test_download_tabular_rows_as_dicts(self, fixtureprocessurl):
|
|
1283
|
+
def test_download_tabular_rows_as_dicts(self, fixturepath, fixtureprocessurl):
|
|
1275
1284
|
with Download() as downloader:
|
|
1276
|
-
result = downloader.download_tabular_rows_as_dicts(
|
|
1277
|
-
fixtureprocessurl, headers=2
|
|
1278
|
-
)
|
|
1285
|
+
result = downloader.download_tabular_rows_as_dicts(fixturepath, headers=2)
|
|
1279
1286
|
assert result == {
|
|
1280
1287
|
"coal": {
|
|
1281
1288
|
"header2": "3",
|
|
@@ -353,6 +353,12 @@ class TestLoader:
|
|
|
353
353
|
["5", "6", "4"],
|
|
354
354
|
["8", "9", "7"],
|
|
355
355
|
]
|
|
356
|
+
save_iterable(
|
|
357
|
+
str(filepath), list_of_dicts, headers=2, columns=["h2", "h3", "h1"]
|
|
358
|
+
)
|
|
359
|
+
newll = read_list_from_csv(filepath)
|
|
360
|
+
remove(filepath)
|
|
361
|
+
assert newll == [["2", "3", "1"], ["5", "6", "4"], ["8", "9", "7"]]
|
|
356
362
|
|
|
357
363
|
xlfilepath = filepath.with_suffix(".xlsx")
|
|
358
364
|
rows = save_iterable(
|
|
@@ -465,6 +471,24 @@ class TestLoader:
|
|
|
465
471
|
["4", "5", "6", "b"],
|
|
466
472
|
["7", "8", "9", "c"],
|
|
467
473
|
]
|
|
474
|
+
save_iterable(filepath, list_of_dicts, headers=["h2", "h1", "h4", "h3"])
|
|
475
|
+
newll = read_list_from_csv(filepath)
|
|
476
|
+
remove(filepath)
|
|
477
|
+
assert newll == [
|
|
478
|
+
["h2", "h1", "h4", "h3"],
|
|
479
|
+
["2", "1", "a", "3"],
|
|
480
|
+
["5", "4", "b", "6"],
|
|
481
|
+
["8", "7", "c", "9"],
|
|
482
|
+
]
|
|
483
|
+
save_iterable(filepath, list_of_dicts, headers=["h2", "h1", "h4"])
|
|
484
|
+
newll = read_list_from_csv(filepath)
|
|
485
|
+
remove(filepath)
|
|
486
|
+
assert newll == [
|
|
487
|
+
["h2", "h1", "h4"],
|
|
488
|
+
["2", "1", "a"],
|
|
489
|
+
["5", "4", "b"],
|
|
490
|
+
["8", "7", "c"],
|
|
491
|
+
]
|
|
468
492
|
save_iterable(filepath, list_of_dicts)
|
|
469
493
|
newll = read_list_from_csv(filepath)
|
|
470
494
|
remove(filepath)
|