hdx-python-pipelineutils 0.0.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 (33) hide show
  1. hdx_python_pipelineutils-0.0.1/.github/workflows/publish.yaml +34 -0
  2. hdx_python_pipelineutils-0.0.1/.github/workflows/run-python-tests.yaml +52 -0
  3. hdx_python_pipelineutils-0.0.1/.gitignore +102 -0
  4. hdx_python_pipelineutils-0.0.1/.pre-commit-config.yaml +26 -0
  5. hdx_python_pipelineutils-0.0.1/LICENSE +21 -0
  6. hdx_python_pipelineutils-0.0.1/PKG-INFO +50 -0
  7. hdx_python_pipelineutils-0.0.1/README.md +11 -0
  8. hdx_python_pipelineutils-0.0.1/pyproject.toml +150 -0
  9. hdx_python_pipelineutils-0.0.1/src/hdx/python/pipelineutils/__init__.py +55 -0
  10. hdx_python_pipelineutils-0.0.1/src/hdx/python/pipelineutils/_version.py +24 -0
  11. hdx_python_pipelineutils-0.0.1/src/hdx/python/pipelineutils/hapi_admins.py +117 -0
  12. hdx_python_pipelineutils-0.0.1/src/hdx/python/pipelineutils/lookup.py +113 -0
  13. hdx_python_pipelineutils-0.0.1/src/hdx/python/pipelineutils/org_type.py +8 -0
  14. hdx_python_pipelineutils-0.0.1/src/hdx/python/pipelineutils/org_type_configuration.yaml +76 -0
  15. hdx_python_pipelineutils-0.0.1/src/hdx/python/pipelineutils/reader.py +595 -0
  16. hdx_python_pipelineutils-0.0.1/src/hdx/python/pipelineutils/sector.py +8 -0
  17. hdx_python_pipelineutils-0.0.1/src/hdx/python/pipelineutils/sector_configuration.yaml +179 -0
  18. hdx_python_pipelineutils-0.0.1/tests/config/project_configuration.yaml +1684 -0
  19. hdx_python_pipelineutils-0.0.1/tests/conftest.py +82 -0
  20. hdx_python_pipelineutils-0.0.1/tests/fixtures/input/download-global-pcode-lengths.csv +157 -0
  21. hdx_python_pipelineutils-0.0.1/tests/fixtures/input/download-global-pcodes-adm-1-2.csv +33364 -0
  22. hdx_python_pipelineutils-0.0.1/tests/fixtures/input/education_closures_school_closures.csv +4 -0
  23. hdx_python_pipelineutils-0.0.1/tests/fixtures/input/global-coordination-groups-beta.json +1 -0
  24. hdx_python_pipelineutils-0.0.1/tests/fixtures/input/hno_2017_sahel_nutrition.csv +28 -0
  25. hdx_python_pipelineutils-0.0.1/tests/fixtures/input/hno_2017_sahel_people_in_need.xlsx +0 -0
  26. hdx_python_pipelineutils-0.0.1/tests/fixtures/input/org_type_organization_types_beta_csv_no_hxl.csv +16 -0
  27. hdx_python_pipelineutils-0.0.1/tests/fixtures/input/organization-types-beta.json +1 -0
  28. hdx_python_pipelineutils-0.0.1/tests/fixtures/input/sahel-humanitarian-needs-overview.json +1 -0
  29. hdx_python_pipelineutils-0.0.1/tests/fixtures/input/sector_global_coordination_groups_beta_csv_no_hxl.csv +16 -0
  30. hdx_python_pipelineutils-0.0.1/tests/test_hapi_admins.py +250 -0
  31. hdx_python_pipelineutils-0.0.1/tests/test_lookup.py +18 -0
  32. hdx_python_pipelineutils-0.0.1/tests/test_readers.py +291 -0
  33. hdx_python_pipelineutils-0.0.1/uv.lock +2806 -0
@@ -0,0 +1,34 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+
11
+ environment:
12
+ name: pypi
13
+ url: https://pypi.org/p/hdx-python-pipelineutils
14
+
15
+ permissions:
16
+ id-token: write
17
+ contents: read
18
+
19
+ steps:
20
+ - uses: actions/checkout@v6
21
+
22
+ - name: Get history and tags for versioning to work
23
+ run: |
24
+ git fetch --prune --unshallow
25
+ git fetch --depth=1 origin +refs/tags/*:refs/tags/*
26
+
27
+ - name: Install uv
28
+ uses: astral-sh/setup-uv@v7
29
+
30
+ - name: Build with uv
31
+ run: uv build
32
+
33
+ - name: Publish distribution 📦 to PyPI
34
+ run: uv publish
@@ -0,0 +1,52 @@
1
+ name: Run tests
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ branches-ignore: [gh-pages, "dependabot/**"]
7
+ pull_request:
8
+ branches-ignore: [gh-pages]
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ permissions:
14
+ contents: read
15
+ checks: write
16
+ pull-requests: write
17
+
18
+ steps:
19
+ - uses: actions/checkout@v6
20
+
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@v7
23
+ with:
24
+ enable-cache: true
25
+ python-version: "3.13"
26
+
27
+ - name: Install dependencies
28
+ run: uv sync --frozen
29
+
30
+ - name: Check styling
31
+ run: |
32
+ uv run ruff format --check
33
+ uv run ruff check
34
+
35
+ - name: Test with pytest
36
+ env:
37
+ HDX_KEY_TEST: ${{ secrets.HDX_BOT_SCRAPERS_API_TOKEN }}
38
+ GSHEET_AUTH: ${{ secrets.HDX_PIPELINE_GSHEET_AUTH }}
39
+ run: uv run pytest
40
+
41
+ - name: Publish Unit Test Results
42
+ uses: EnricoMi/publish-unit-test-result-action@v2
43
+ if: always()
44
+ with:
45
+ files: test-results.xml
46
+
47
+ - name: Publish in Coveralls
48
+ uses: coverallsapp/github-action@v2
49
+ if: always()
50
+ with:
51
+ flag-name: tests
52
+ format: lcov
@@ -0,0 +1,102 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ env/
12
+ build/
13
+ develop-eggs/
14
+ dist/
15
+ downloads/
16
+ eggs/
17
+ .eggs/
18
+ lib/
19
+ lib64/
20
+ parts/
21
+ sdist/
22
+ var/
23
+ *.egg-info/
24
+ .installed.cfg
25
+ *.egg
26
+
27
+ # PyInstaller
28
+ # Usually these files are written by a python script from a template
29
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
30
+ *.manifest
31
+ *.spec
32
+
33
+ # Installer logs
34
+ pip-log.txt
35
+ pip-delete-this-directory.txt
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .coverage
41
+ .coverage.*
42
+ .cache
43
+ nosetests.xml
44
+ coverage.lcov
45
+ coverage.xml
46
+ test-results.xml
47
+ *,cover
48
+ .hypothesis/
49
+ tests/*.log
50
+ .pytest_cache/
51
+
52
+ # Translations
53
+ *.mo
54
+ *.pot
55
+
56
+ # Django stuff:
57
+ *.log
58
+ local_settings.py
59
+
60
+ # Flask stuff:
61
+ instance/
62
+ .webassets-cache
63
+
64
+ # Scrapy stuff:
65
+ .scrapy
66
+
67
+ # Sphinx documentation
68
+ documentation/_*/
69
+ documentation/source/
70
+
71
+ # PyBuilder
72
+ target/
73
+
74
+ # IPython Notebook
75
+ .ipynb_checkpoints
76
+
77
+ # pyenv
78
+ .python-version
79
+
80
+ # celery beat schedule file
81
+ celerybeat-schedule
82
+
83
+ # dotenv
84
+ .env
85
+
86
+ # virtualenv
87
+ venv/
88
+ ENV/
89
+
90
+ # Spyder project settings
91
+ .spyderproject
92
+
93
+ # Rope project settings
94
+ .ropeproject
95
+
96
+ # IntelliJ
97
+ .idea/
98
+
99
+ # hatch-vcs
100
+ _version.py
101
+
102
+ .vscode/settings.json
@@ -0,0 +1,26 @@
1
+ default_language_version:
2
+ python: python3.13
3
+
4
+ repos:
5
+ - repo: https://github.com/pre-commit/pre-commit-hooks
6
+ rev: v6.0.0
7
+ hooks:
8
+ - id: trailing-whitespace
9
+ - id: end-of-file-fixer
10
+ exclude: test_scraper_.*\.json
11
+ - id: check-ast
12
+
13
+ - repo: https://github.com/astral-sh/ruff-pre-commit
14
+ rev: v0.14.14
15
+ hooks:
16
+ # Run the linter.
17
+ - id: ruff-check
18
+ args: [ --fix ]
19
+ # Run the formatter.
20
+ - id: ruff-format
21
+
22
+ - repo: https://github.com/astral-sh/uv-pre-commit
23
+ rev: 0.9.25
24
+ hooks:
25
+ # Ensure the lockfile is up-to-date with pyproject.toml
26
+ - id: uv-lock
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Michael Rans
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,50 @@
1
+ Metadata-Version: 2.4
2
+ Name: hdx-python-pipelineutils
3
+ Version: 0.0.1
4
+ Summary: HDX Python Pipeline Utilities
5
+ Project-URL: Homepage, https://github.com/OCHA-DAP/hdx-python-pipelineutils
6
+ Author-email: Michael Rans <rans@email.com>
7
+ License: MIT
8
+ License-File: LICENSE
9
+ Keywords: HDX,pipelines,scrapers,utilities
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Natural Language :: English
14
+ Classifier: Operating System :: MacOS
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Operating System :: Unix
18
+ Classifier: Programming Language :: Python
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3 :: Only
21
+ Classifier: Programming Language :: Python :: 3.8
22
+ Classifier: Programming Language :: Python :: 3.9
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
+ Requires-Python: >=3.10
28
+ Requires-Dist: gspread
29
+ Requires-Dist: hdx-python-api>=6.6.7
30
+ Requires-Dist: hdx-python-country>=4.1.1
31
+ Requires-Dist: hdx-python-utilities>=4.0.8
32
+ Requires-Dist: libhxl
33
+ Requires-Dist: regex
34
+ Provides-Extra: docs
35
+ Requires-Dist: mkapi; extra == 'docs'
36
+ Provides-Extra: pandas
37
+ Requires-Dist: pandas>=2.3.3; extra == 'pandas'
38
+ Description-Content-Type: text/markdown
39
+
40
+ [![Build Status](https://github.com/OCHA-DAP/hdx-python-pipelineutils/actions/workflows/run-python-tests.yaml/badge.svg)](https://github.com/OCHA-DAP/hdx-python-pipelineutils/actions/workflows/run-python-tests.yaml)
41
+ [![Coverage Status](https://coveralls.io/repos/github/OCHA-DAP/hdx-python-pipelineutils/badge.svg?branch=main&ts=1)](https://coveralls.io/github/OCHA-DAP/hdx-python-pipelineutils?branch=main)
42
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
43
+ [![Downloads](https://img.shields.io/pypi/dm/hdx-python-pipelineutils.svg)](https://pypistats.org/packages/hdx-python-pipelineutils)
44
+
45
+
46
+ The HDX Python PipelineUtils Library contains various utilities for use by pipelines.
47
+
48
+ This library is part of the
49
+ [Humanitarian Data Exchange](https://data.humdata.org/) (HDX) project. If you have
50
+ humanitarian related data, please upload your datasets to HDX.
@@ -0,0 +1,11 @@
1
+ [![Build Status](https://github.com/OCHA-DAP/hdx-python-pipelineutils/actions/workflows/run-python-tests.yaml/badge.svg)](https://github.com/OCHA-DAP/hdx-python-pipelineutils/actions/workflows/run-python-tests.yaml)
2
+ [![Coverage Status](https://coveralls.io/repos/github/OCHA-DAP/hdx-python-pipelineutils/badge.svg?branch=main&ts=1)](https://coveralls.io/github/OCHA-DAP/hdx-python-pipelineutils?branch=main)
3
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
4
+ [![Downloads](https://img.shields.io/pypi/dm/hdx-python-pipelineutils.svg)](https://pypistats.org/packages/hdx-python-pipelineutils)
5
+
6
+
7
+ The HDX Python PipelineUtils Library contains various utilities for use by pipelines.
8
+
9
+ This library is part of the
10
+ [Humanitarian Data Exchange](https://data.humdata.org/) (HDX) project. If you have
11
+ humanitarian related data, please upload your datasets to HDX.
@@ -0,0 +1,150 @@
1
+ #########################
2
+ # Project Configuration #
3
+ #########################
4
+
5
+ [build-system]
6
+ requires = ["hatchling", "hatch-vcs"]
7
+ build-backend = "hatchling.build"
8
+
9
+ [project]
10
+ name = "hdx-python-pipelineutils"
11
+ description = "HDX Python Pipeline Utilities"
12
+ authors = [{name = "Michael Rans", email = "rans@email.com"}]
13
+ license = {text = "MIT"}
14
+ keywords = ["HDX", "scrapers", "pipelines", "utilities"]
15
+ classifiers = [
16
+ "Development Status :: 5 - Production/Stable",
17
+ "Topic :: Software Development :: Libraries :: Python Modules",
18
+ "Programming Language :: Python",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Programming Language :: Python :: 3.8",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Intended Audience :: Developers",
27
+ "License :: OSI Approved :: MIT License",
28
+ "Natural Language :: English",
29
+ "Operating System :: POSIX :: Linux",
30
+ "Operating System :: Unix",
31
+ "Operating System :: MacOS",
32
+ "Operating System :: Microsoft :: Windows",
33
+ ]
34
+ readme = "README.md"
35
+ dynamic = ["version"]
36
+ requires-python = ">=3.10"
37
+
38
+
39
+ dependencies = [
40
+ "hdx-python-api>=6.6.7",
41
+ "hdx-python-country>=4.1.1",
42
+ "hdx-python-utilities>=4.0.8",
43
+ "libhxl",
44
+ "gspread",
45
+ "regex",
46
+ ]
47
+
48
+ [project.optional-dependencies]
49
+ pandas = ["pandas>=2.3.3"]
50
+ docs = ["mkapi"]
51
+
52
+ [dependency-groups]
53
+ dev = [
54
+ "pandas>=2.3.3",
55
+ "pytest",
56
+ "pytest-cov",
57
+ "pre-commit",
58
+ "ruff==0.14.14",
59
+ ]
60
+
61
+ [project.urls]
62
+ Homepage = "https://github.com/OCHA-DAP/hdx-python-pipelineutils"
63
+
64
+ # ----------------------------------------------------------------------------
65
+ # Hatchling (Build & Versioning)
66
+ # ----------------------------------------------------------------------------
67
+
68
+ [tool.hatch.version]
69
+ source = "vcs"
70
+
71
+ [tool.hatch.version.raw-options]
72
+ local_scheme = "no-local-version"
73
+ version_scheme = "python-simplified-semver"
74
+
75
+ [tool.hatch.build.hooks.vcs]
76
+ version-file = "src/hdx/python/pipelineutils/_version.py"
77
+
78
+ [tool.hatch.build.targets.wheel]
79
+ packages = ["src/hdx"]
80
+
81
+ [tool.hatch.metadata]
82
+ allow-direct-references = true
83
+
84
+ # ----------------------------------------------------------------------------
85
+ # Ruff (Linting & Formatting)
86
+ # ----------------------------------------------------------------------------
87
+
88
+ [tool.ruff]
89
+ target-version = "py310"
90
+ src = ["src"]
91
+ exclude = ["_version.py"]
92
+
93
+ [tool.ruff.lint]
94
+ # Defaults are E (pycodestyle) and F (pyflakes). We extend them:
95
+ extend-select = [
96
+ "I", # isort
97
+ "UP", # pyupgrade
98
+ ]
99
+ ignore = [
100
+ "E501", # Line too long
101
+ ]
102
+
103
+ [tool.ruff.lint.isort]
104
+ known-local-folder = ["hdx.python.pipelineutils"]
105
+ known-third-party = [
106
+ "hdx.api",
107
+ "hdx.data",
108
+ "hdx.facades",
109
+ "hdx.location",
110
+ "hdx.utilities",
111
+ ]
112
+
113
+ # ----------------------------------------------------------------------------
114
+ # Pytest (Testing)
115
+ # ----------------------------------------------------------------------------
116
+
117
+ [tool.pytest.ini_options]
118
+ pythonpath = "src"
119
+ log_cli = true
120
+ addopts = """
121
+ --color=yes
122
+ --rootdir=.
123
+ --junitxml=test-results.xml
124
+ --cov
125
+ --no-cov-on-fail
126
+ --cov-report=lcov
127
+ --cov-report=term-missing
128
+ """
129
+
130
+ # ----------------------------------------------------------------------------
131
+ # Coverage (Reporting)
132
+ # ----------------------------------------------------------------------------
133
+
134
+ [tool.coverage.run]
135
+ source = ["src"]
136
+ omit = ["*/_version.py"]
137
+
138
+ [tool.coverage.report]
139
+ exclude_also = [
140
+ "from ._version",
141
+ "def __repr__",
142
+ "if self.debug:",
143
+ "if settings.DEBUG",
144
+ "raise AssertionError",
145
+ "raise NotImplementedError",
146
+ "if 0:",
147
+ "if __name__ == .__main__.:",
148
+ "if TYPE_CHECKING:",
149
+ "@(abc\\.)?abstractmethod",
150
+ ]
@@ -0,0 +1,55 @@
1
+ import re
2
+ from datetime import datetime
3
+
4
+ from hdx.data.dataset import Dataset
5
+
6
+ template = re.compile("{{.*?}}")
7
+
8
+
9
+ def string_params_to_dict(string: str) -> dict[str, str]:
10
+ params = {}
11
+ if not string:
12
+ return params
13
+ for name_par in string.split(","):
14
+ name, par = name_par.strip().split(":")
15
+ params[name] = par.strip()
16
+ return params
17
+
18
+
19
+ def match_template(input: str) -> tuple[str | None, str | None]:
20
+ """Try to match {{XXX}} in input string
21
+
22
+ Args:
23
+ input: String in which to look for template
24
+
25
+ Returns:
26
+ (Matched string with brackets, matched string without brackets)
27
+ """
28
+ match = template.search(input)
29
+ if match:
30
+ template_string = match.group()
31
+ return template_string, template_string[2:-2]
32
+ return None, None
33
+
34
+
35
+ def get_startend_dates_from_time_period(
36
+ dataset: Dataset, today: datetime | None = None
37
+ ) -> dict | None:
38
+ """Return the time period in form required for source_date
39
+
40
+ Args:
41
+ dataset: Dataset object
42
+ today: Date to use for today. Default is None (datetime.utcnow)
43
+
44
+ Returns:
45
+ Time period in form required for source_date
46
+ """
47
+ if today is None:
48
+ date_info = dataset.get_time_period()
49
+ else:
50
+ date_info = dataset.get_time_period(today=today)
51
+ startdate = date_info.get("startdate")
52
+ enddate = date_info.get("enddate")
53
+ if enddate is None:
54
+ return None
55
+ return {"start": startdate, "end": enddate}
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '0.0.1'
22
+ __version_tuple__ = version_tuple = (0, 0, 1)
23
+
24
+ __commit_id__ = commit_id = None
@@ -0,0 +1,117 @@
1
+ from hdx.location.adminlevel import AdminLevel
2
+
3
+
4
+ def complete_admins(
5
+ admins: list[AdminLevel],
6
+ countryiso3: str,
7
+ provider_adm_names: list,
8
+ adm_codes: list,
9
+ adm_names: list,
10
+ fuzzy_match: bool = True,
11
+ ) -> tuple[int, list[str]]:
12
+ """Use information from adm_codes to populate adm_names and from
13
+ provider_adm_names to populate adm_codes with outptu of the admin level
14
+ and arnings for unknown and mismatched p-codes. All provided lists
15
+ should be of the same length.
16
+
17
+ Args:
18
+ admins: List of AdminLevel objects
19
+ countryiso3: Country ISO3 code
20
+ provider_adm_names: List of provider adm names
21
+ adm_codes: List of adm codes
22
+ adm_names: List of adm names
23
+ fuzzy_match: Whether to use fuzzy matching. Default is True.
24
+
25
+ Returns:
26
+ Admin level and warnings
27
+ """
28
+
29
+ warnings = []
30
+ child = None
31
+ adm_level = len(provider_adm_names)
32
+
33
+ def check_unknown_pcode(adm_code: str, pcode: str) -> str:
34
+ if pcode:
35
+ warnings.append(f"PCode unknown {adm_code}->{pcode} ({warntxt})")
36
+ return pcode
37
+ else:
38
+ warnings.append(f"PCode unknown {adm_code}->''")
39
+ return ""
40
+
41
+ for i, provider_adm_name in reversed(list(enumerate(provider_adm_names))):
42
+ adm_code = adm_codes[i]
43
+ parent = admins[i].pcode_to_parent.get(adm_code)
44
+ if not parent and i > 0:
45
+ parent = adm_codes[i - 1]
46
+ if not provider_adm_name:
47
+ provider_adm_name = ""
48
+ provider_adm_names[i] = ""
49
+ if child:
50
+ pcode = admins[i + 1].pcode_to_parent.get(child)
51
+ warntxt = "parent"
52
+ elif provider_adm_name:
53
+ pcode, _ = admins[i].get_pcode(
54
+ countryiso3,
55
+ provider_adm_name,
56
+ parent=parent,
57
+ fuzzy_match=fuzzy_match,
58
+ )
59
+ warntxt = f"provider_adm{i + 1}_name"
60
+ else:
61
+ pcode = None
62
+ if adm_code:
63
+ if adm_code not in admins[i].pcodes:
64
+ if admins[i].looks_like_pcode(adm_code):
65
+ adj_adm_code = admins[i].convert_admin_pcode_length(
66
+ countryiso3, adm_code, parent=parent
67
+ )
68
+ if adj_adm_code:
69
+ warnings.append(f"PCode length {adm_code}->{adj_adm_code}")
70
+ adm_code = adj_adm_code
71
+ else:
72
+ adm_code = check_unknown_pcode(adm_code, pcode)
73
+ else:
74
+ adm_code = check_unknown_pcode(adm_code, pcode)
75
+ elif pcode and adm_code != pcode:
76
+ if child:
77
+ warnings.append(f"PCode mismatch {adm_code}->{pcode} ({warntxt})")
78
+ adm_code = pcode
79
+ else:
80
+ warnings.append(f"PCode mismatch {adm_code} != {provider_adm_name}")
81
+ elif pcode:
82
+ adm_code = pcode
83
+ else:
84
+ adm_code = ""
85
+ adm_codes[i] = adm_code
86
+ if adm_code:
87
+ adm_names[i] = admins[i].pcode_to_name.get(adm_code, "")
88
+ child = adm_code
89
+ else:
90
+ adm_names[i] = ""
91
+ if provider_adm_name == "":
92
+ adm_level -= 1
93
+ return adm_level, warnings
94
+
95
+
96
+ def pad_admins(
97
+ provider_adm_names: list[str],
98
+ adm_codes: list[str],
99
+ adm_names: list[str],
100
+ adm_level: int = 2,
101
+ ) -> None:
102
+ """Pad lists to size given in adm_level adding as many "" as needed.
103
+
104
+ Args:
105
+ provider_adm_names: List of provider adm names
106
+ adm_codes: List of adm codes
107
+ adm_names: List of adm names
108
+ adm_level: Admin level to which to pad. Default is 2.
109
+
110
+ Returns:
111
+ Admin level and warnings
112
+ """
113
+
114
+ for i in range(len(provider_adm_names), adm_level):
115
+ provider_adm_names.append("")
116
+ adm_codes.append("")
117
+ adm_names.append("")