Przeglądaj źródła

Add tools from CR copier template and some restructuring of code folders. Also some smaller fixes e.g. automatic file retrieval when running crf test reads

Johannes Gütschow 1 rok temu
rodzic
commit
cb6cc3fdd7
100 zmienionych plików z 6882 dodań i 1148 usunięć
  1. 18 0
      .copier-answers.yml
  2. 57 0
      .github/actions/setup/action.yml
  3. 60 0
      .github/workflows/bump.yaml
  4. 112 0
      .github/workflows/ci.yaml
  5. 33 0
      .github/workflows/deploy.yaml
  6. 30 0
      .github/workflows/install.yaml
  7. 47 0
      .github/workflows/release.yaml
  8. 153 12
      .gitignore
  9. 50 0
      .pre-commit-config.yaml
  10. 24 0
      .readthedocs.yaml
  11. 76 10
      Makefile
  12. 81 2
      README.md
  13. 0 10
      UNFCCC_GHG_data/UNFCCC_CRF_reader/crf_specifications/__init__.py
  14. 0 30
      UNFCCC_GHG_data/UNFCCC_DI_reader/__init__.py
  15. 0 33
      UNFCCC_GHG_data/helper/__init__.py
  16. 41 0
      changelog/README.md
  17. 20 0
      docs/Makefile
  18. 35 0
      docs/make.bat
  19. 0 0
      docs/source/_static/.gitkeep
  20. 0 0
      docs/source/_templates/.gitkeep
  21. 13 0
      docs/source/api/unfccc_ghg_data.operations.rst
  22. 12 0
      docs/source/api/unfccc_ghg_data.rst
  23. 20 0
      docs/source/changelog.md
  24. 168 0
      docs/source/conf.py
  25. 55 0
      docs/source/development.md
  26. 42 0
      docs/source/index.md
  27. 21 0
      docs/source/notebooks.md
  28. 24 0
      docs/source/notebooks/basic-demo.py
  29. 82 66
      dodo.py
  30. 4263 0
      poetry.lock
  31. 214 7
      pyproject.toml
  32. 0 1
      requirements.txt
  33. 0 1
      requirements_dev.txt
  34. 28 0
      scripts/test-install.py
  35. 0 79
      setup.cfg
  36. 0 5
      setup.py
  37. 2 6
      src/unfccc_ghg_data/__init__.py
  38. 54 0
      src/unfccc_ghg_data/helper/__init__.py
  39. 10 6
      src/unfccc_ghg_data/helper/country_info.py
  40. 8 5
      src/unfccc_ghg_data/helper/definitions.py
  41. 8 4
      src/unfccc_ghg_data/helper/folder_mapping.py
  42. 97 57
      src/unfccc_ghg_data/helper/functions.py
  43. 1 1
      src/unfccc_ghg_data/unfccc_crf_reader/__init__.py
  44. 10 7
      src/unfccc_ghg_data/unfccc_crf_reader/crf_raw_for_year.py
  45. 10 0
      src/unfccc_ghg_data/unfccc_crf_reader/crf_specifications/__init__.py
  46. 101 100
      src/unfccc_ghg_data/unfccc_crf_reader/crf_specifications/crf2021_specification.py
  47. 102 101
      src/unfccc_ghg_data/unfccc_crf_reader/crf_specifications/crf2022_specification.py
  48. 95 94
      src/unfccc_ghg_data/unfccc_crf_reader/crf_specifications/crf2023_aus_specification.py
  49. 102 101
      src/unfccc_ghg_data/unfccc_crf_reader/crf_specifications/crf2023_specification.py
  50. 2 2
      src/unfccc_ghg_data/unfccc_crf_reader/crf_specifications/util.py
  51. 2 2
      src/unfccc_ghg_data/unfccc_crf_reader/read_new_unfccc_crf_for_year.py
  52. 4 3
      src/unfccc_ghg_data/unfccc_crf_reader/read_new_unfccc_crf_for_year_datalad.py
  53. 2 1
      src/unfccc_ghg_data/unfccc_crf_reader/read_unfccc_crf_submission.py
  54. 3 2
      src/unfccc_ghg_data/unfccc_crf_reader/read_unfccc_crf_submission_datalad.py
  55. 2 1
      src/unfccc_ghg_data/unfccc_crf_reader/test_read_unfccc_crf_for_year.py
  56. 100 71
      src/unfccc_ghg_data/unfccc_crf_reader/unfccc_crf_reader_core.py
  57. 56 54
      src/unfccc_ghg_data/unfccc_crf_reader/unfccc_crf_reader_devel.py
  58. 50 43
      src/unfccc_ghg_data/unfccc_crf_reader/unfccc_crf_reader_prod.py
  59. 1 1
      src/unfccc_ghg_data/unfccc_crf_reader/util.py
  60. 0 0
      src/unfccc_ghg_data/unfccc_di_reader/DI_AI_parties.conf
  61. 0 0
      src/unfccc_ghg_data/unfccc_di_reader/DI_NAI_parties.conf
  62. 36 0
      src/unfccc_ghg_data/unfccc_di_reader/__init__.py
  63. 1 2
      src/unfccc_ghg_data/unfccc_di_reader/process_unfccc_di_for_country.py
  64. 3 3
      src/unfccc_ghg_data/unfccc_di_reader/process_unfccc_di_for_country_datalad.py
  65. 1 2
      src/unfccc_ghg_data/unfccc_di_reader/process_unfccc_di_for_country_group.py
  66. 2 2
      src/unfccc_ghg_data/unfccc_di_reader/process_unfccc_di_for_country_group_datalad.py
  67. 1 2
      src/unfccc_ghg_data/unfccc_di_reader/read_unfccc_di_for_country.py
  68. 3 3
      src/unfccc_ghg_data/unfccc_di_reader/read_unfccc_di_for_country_datalad.py
  69. 1 2
      src/unfccc_ghg_data/unfccc_di_reader/read_unfccc_di_for_country_group.py
  70. 2 2
      src/unfccc_ghg_data/unfccc_di_reader/read_unfccc_di_for_country_group_datalad.py
  71. 0 0
      src/unfccc_ghg_data/unfccc_di_reader/unfccc_di_reader_config.py
  72. 23 26
      src/unfccc_ghg_data/unfccc_di_reader/unfccc_di_reader_core.py
  73. 25 22
      src/unfccc_ghg_data/unfccc_di_reader/unfccc_di_reader_datalad.py
  74. 25 23
      src/unfccc_ghg_data/unfccc_di_reader/unfccc_di_reader_helper.py
  75. 4 5
      src/unfccc_ghg_data/unfccc_di_reader/unfccc_di_reader_io.py
  76. 21 26
      src/unfccc_ghg_data/unfccc_di_reader/unfccc_di_reader_proc.py
  77. 4 4
      src/unfccc_ghg_data/unfccc_di_reader/util.py
  78. 1 1
      src/unfccc_ghg_data/unfccc_downloader/__init__.py
  79. 13 12
      src/unfccc_ghg_data/unfccc_downloader/download_annexI.py
  80. 13 11
      src/unfccc_ghg_data/unfccc_downloader/download_ndc.py
  81. 13 11
      src/unfccc_ghg_data/unfccc_downloader/download_non-annexI.py
  82. 1 1
      src/unfccc_ghg_data/unfccc_downloader/fetch_submissions_annexI.py
  83. 7 6
      src/unfccc_ghg_data/unfccc_downloader/fetch_submissions_bur.py
  84. 8 8
      src/unfccc_ghg_data/unfccc_downloader/fetch_submissions_nc.py
  85. 6 6
      src/unfccc_ghg_data/unfccc_downloader/unfccc_submission_info.py
  86. 0 0
      src/unfccc_ghg_data/unfccc_reader/Argentina/__init__.py
  87. 10 9
      src/unfccc_ghg_data/unfccc_reader/Argentina/read_ARG_BUR4_from_pdf.py
  88. 0 0
      src/unfccc_ghg_data/unfccc_reader/Chile/__init__.py
  89. 6 6
      src/unfccc_ghg_data/unfccc_reader/Chile/config_chl_bur4.py
  90. 6 6
      src/unfccc_ghg_data/unfccc_reader/Chile/read_CHL_BUR4_from_xlsx.py
  91. 6 6
      src/unfccc_ghg_data/unfccc_reader/Chile/read_CHL_BUR5_from_xlsx.py
  92. 0 0
      src/unfccc_ghg_data/unfccc_reader/Colombia/__init__.py
  93. 4 3
      src/unfccc_ghg_data/unfccc_reader/Colombia/read_COL_BUR3_from_xlsx.py
  94. 0 0
      src/unfccc_ghg_data/unfccc_reader/Indonesia/__init__.py
  95. 7 5
      src/unfccc_ghg_data/unfccc_reader/Indonesia/read_IDN_BUR3_from_pdf.py
  96. 0 0
      src/unfccc_ghg_data/unfccc_reader/Israel/__init__.py
  97. 2 1
      src/unfccc_ghg_data/unfccc_reader/Israel/config_isr_bur2.py
  98. 25 12
      src/unfccc_ghg_data/unfccc_reader/Israel/read_ISR_BUR2_from_pdf.py
  99. 0 0
      src/unfccc_ghg_data/unfccc_reader/Malaysia/__init__.py
  100. 1 2
      src/unfccc_ghg_data/unfccc_reader/Malaysia/config_mys_bur3.py

+ 18 - 0
.copier-answers.yml

@@ -0,0 +1,18 @@
+# Changes here will be overwritten by Copier
+_commit: v0.3.0
+_src_path: ../../../helper_tools/copier-core-python-repository/
+email: mail@johannes-guetschow.de
+initial_setup: true
+name: Johannes Gütschow
+notebook_dependencies: false
+pandas_doctests: false
+plot_dependencies: true
+project_description_short: Reading country greenhouse gas data submitted to the United
+    Nations Framework Convention on Climate Change (UNFCCC)in different submissions
+    and formats and providing it in a standadized nc and csv format compatible with
+    primap2. Data are read using different methods from APIs, xlsx and csv files as
+    well as pdf files.
+project_name_human: Country greenhouse gas data submitted to the UNFCCC
+project_name_pip: unfccc-ghg-data
+project_name_python: unfccc_ghg_data
+project_url: https://github.com/JGuetschow/UNFCCC_non-AnnexI_data

+ 57 - 0
.github/actions/setup/action.yml

@@ -0,0 +1,57 @@
+name: "Setup Python and Poetry"
+description: "setup Python and Poetry with caches"
+
+inputs:
+  python-version:
+    description: "Python version to use"
+    required: true
+  venv-id:
+    description: "ID to identify cached environment (should be unique from other steps)"
+    required: true
+  poetry-dependency-install-flags:
+    description: "Flags to pass to poetry when running `poetry install --no-interaction --no-root`"
+    required: true
+  run-poetry-install:
+    description: "Should we run the poetry install steps"
+    required: false
+    default: true
+
+
+runs:
+  using: "composite"
+  steps:
+    - name: Set up Python ${{ inputs.python-version }}
+      id: setup-python
+      uses: actions/setup-python@v4
+      with:
+        python-version: ${{ inputs.python-version }}
+    - name: Load cached Poetry installation
+      id: cached-poetry
+      uses: actions/cache@v3
+      with:
+        path: ~/.local  # the path depends on the OS
+        key: poetry-2  # increment to reset cache
+    - name: Install Poetry
+      if: steps.cached-poetry.outputs.cache-hit != 'true'
+      uses: snok/install-poetry@v1
+    - name: Load cached venv
+      if: ${{ inputs.run-poetry-install == 'true' }}
+      id: cached-poetry-dependencies
+      uses: actions/cache@v3
+      with:
+        path: .venv
+        key: "venv-${{ inputs.venv-id }}-${{ inputs.python-version }}-${{ hashFiles('**/poetry.lock') }}"
+    # Install dependencies first so that our package doesn't appear in the cache by accident
+    - name: Install dependencies
+      if: ${{ inputs.run-poetry-install == 'true' }}
+      shell: bash
+      run: |
+        poetry config virtualenvs.create true
+        poetry config virtualenvs.in-project true
+        poetry env use ${{ inputs.python-version }}
+        poetry install --no-interaction --no-root ${{ inputs.poetry-dependency-install-flags }}
+    # Now run same command but let the package install too
+    - name: Install package
+      if: ${{ inputs.run-poetry-install == 'true' }}
+      shell: bash
+      run: poetry install --no-interaction ${{ inputs.poetry-dependency-install-flags }}

+ 60 - 0
.github/workflows/bump.yaml

@@ -0,0 +1,60 @@
+name: Bump version
+
+on:
+  workflow_dispatch:
+    inputs:
+      bump_rule:
+        type: choice
+        description: How to bump the project's version (see https://python-poetry.org/docs/cli/#version)
+        options:
+          - patch
+          - minor
+          - major
+          - prepatch
+          - preminor
+          - premajor
+          - prerelease
+        required: true
+
+jobs:
+  bump_version:
+    name: "Bump version and create changelog"
+    if: "!startsWith(github.event.head_commit.message, 'bump:')"
+    runs-on: ubuntu-latest
+    env:
+      CI_COMMIT_EMAIL: "ci-runner@unfccc-ghg-data.invalid"
+    steps:
+      - name: Check out repository
+        uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+          token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}"
+
+      # towncrier imports the package as part of building so we have to
+      # install the pacakage (to keep things slim, we only install the main
+      # dependencies, which also means that we get a test that we can import
+      # the package with only the compulsory dependencies installed for free)
+      - uses: ./.github/actions/setup
+        with:
+          python-version: "3.11"
+          venv-id: "bump"
+          poetry-dependency-install-flags: "--only main"
+
+      - name: Install towncrier
+        run: |
+          poetry run pip install towncrier
+
+      - name: Create bump and changelog
+
+        run: |
+          BASE_VERSION=`poetry version -s`
+          NEW_VERSION=`poetry version -s ${{ github.event.inputs.bump_rule }}`
+          poetry run towncrier build --yes --version v$NEW_VERSION
+
+          git config --global user.name "$GITHUB_ACTOR"
+          git config --global user.email "$CI_COMMIT_EMAIL"
+
+          git commit -a -m "bump: version $BASE_VERSION -> $NEW_VERSION"
+          git tag v$NEW_VERSION
+          git push && git push --tags
+          echo "Bumped to version $NEW_VERSION"

+ 112 - 0
.github/workflows/ci.yaml

@@ -0,0 +1,112 @@
+name: CI
+
+on:
+  pull_request:
+  push:
+    branches: [main]
+    tags: ['v*']
+
+jobs:
+  mypy:
+    if: ${{ !github.event.pull_request.draft }}
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check out repository
+        uses: actions/checkout@v3
+      - uses: ./.github/actions/setup
+        with:
+          python-version: "3.9"
+          venv-id: "docs"
+          poetry-dependency-install-flags: "--all-extras --only 'main,dev'"
+      - name: mypy
+        run: MYPYPATH=stubs poetry run mypy src
+
+  docs:
+    if: ${{ !github.event.pull_request.draft }}
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check out repository
+        uses: actions/checkout@v3
+      - uses: ./.github/actions/setup
+        with:
+          python-version: "3.9"
+          venv-id: "docs"
+          poetry-dependency-install-flags: "--all-extras --only 'main,docs'"
+      - name: docs
+        run: poetry run sphinx-build -W --keep-going -T -b html docs/source docs/build
+
+  tests:
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ "ubuntu-latest" ]
+        python-version: [ "3.9", "3.10", "3.11" ]
+    runs-on: "${{ matrix.os }}"
+    steps:
+      - name: Check out repository
+        uses: actions/checkout@v3
+      - uses: ./.github/actions/setup
+        with:
+          python-version: "${{ matrix.python-version }}"
+          venv-id: "tests-${{ runner.os }}"
+          poetry-dependency-install-flags: "--all-extras"
+      - name: Run tests
+        run: |
+          poetry run pytest -r a -v src tests --doctest-modules --cov=src --cov-report=term-missing --cov-report=xml
+          poetry run coverage report
+      - name: Upload coverage reports to Codecov
+        uses: codecov/codecov-action@v3
+
+  imports-without-extras:
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ "ubuntu-latest" ]
+        python-version: [ "3.9", "3.10", "3.11" ]
+    runs-on: "${{ matrix.os }}"
+    steps:
+      - name: Check out repository
+        uses: actions/checkout@v3
+      - uses: ./.github/actions/setup
+        with:
+          python-version: "${{ matrix.python-version }}"
+          venv-id: "imports-without-extras-${{ runner.os }}"
+          poetry-dependency-install-flags: "--only main"
+      - name: Check importable without extras
+        run: poetry run python scripts/test-install.py
+
+  check-build:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check out repository
+        uses: actions/checkout@v3
+      - uses: ./.github/actions/setup
+        with:
+          python-version: "3.9"
+          venv-id: "check-build-${{ runner.os }}"
+          run-poetry-install: false
+          poetry-dependency-install-flags: "not used"
+      - name: Build package
+        run: |
+          poetry build --no-interaction
+      - name: Check build
+        run: |
+          tar -tvf dist/unfccc_ghg_data-*.tar.gz --wildcards '*unfccc_ghg_data/py.typed'
+
+  check-dependency-licences:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check out repository
+        uses: actions/checkout@v3
+      - uses: ./.github/actions/setup
+        with:
+          python-version: "3.9"
+          venv-id: "licence-check"
+          poetry-dependency-install-flags: "--all-extras"
+      - name: Check licences of dependencies
+        shell: bash
+        run: |
+          TEMP_FILE=$(mktemp)
+          poetry export --without=tests --without=docs --without=dev > $TEMP_FILE
+          poetry run liccheck -r $TEMP_FILE -R licence-check.txt
+          cat licence-check.txt

+ 33 - 0
.github/workflows/deploy.yaml

@@ -0,0 +1,33 @@
+name: Deploy
+
+on:
+  release:
+    types: [published]
+
+defaults:
+  run:
+    shell: bash
+
+jobs:
+  deploy-pypi:
+    name: Deploy to PyPI
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check out repository
+        uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+      - uses: ./.github/actions/setup
+        with:
+          python-version: "3.9"
+          venv-id: "deploy"
+          poetry-dependency-install-flags: "--all-extras"
+      - name: Run tests
+        run: |
+          poetry run pytest -r a src tests --doctest-modules
+      - name: Publish to PyPI
+        env:
+          PYPI_TOKEN: "${{ secrets.PYPI_TOKEN }}"
+        run: |
+          poetry config pypi-token.pypi $PYPI_TOKEN
+          poetry publish --build --no-interaction

+ 30 - 0
.github/workflows/install.yaml

@@ -0,0 +1,30 @@
+name: Install
+
+on:
+  schedule:
+    # * is a special character in YAML so you have to quote this string
+    - cron:  '0 0 * * 3'
+
+jobs:
+  test-pypi-install:
+    runs-on: "${{ matrix.os }}"
+    strategy:
+      fail-fast: false
+      matrix:
+        os: ["ubuntu-latest", "macos-latest", "windows-latest"]
+        python-version: [ "3.9", "3.10", "3.11" ]
+    steps:
+    - name: Set up Python "${{ matrix.python-version }}"
+      id: setup-python
+      uses: actions/setup-python@v4
+      with:
+        python-version: "${{ matrix.python-version }}"
+    - name: Install
+      run: |
+        pip install --upgrade pip
+        pip install unfccc-ghg-data
+    - name: Checkout repository
+      uses: actions/checkout@v3
+    - name: Test installation (${{ matrix.os }} Python ${{ matrix.python-version }})
+      run: |
+        python scripts/test-install.py

+ 47 - 0
.github/workflows/release.yaml

@@ -0,0 +1,47 @@
+name: Release
+
+on:
+  push:
+    tags: ['v*']
+
+defaults:
+  run:
+    shell: bash
+
+jobs:
+  draft-release:
+    name: Create draft release
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check out repository
+        uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+      - uses: ./.github/actions/setup
+        with:
+          python-version: "3.9"
+          venv-id: "release"
+          poetry-dependency-install-flags: "--all-extras"
+      - name: Add version to environment
+        run: |
+          PROJECT_VERSION=$(poetry version --short)
+          echo "PROJECT_VERSION=$PROJECT_VERSION" >> $GITHUB_ENV
+      - name: Run tests
+        run: |
+          poetry run pytest -r a -v src tests --doctest-modules
+      - name: Build package
+        run: |
+          poetry build --no-interaction
+      - name: Generate Release Notes
+        run: |
+          git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty='format:* %h %s' --no-merges >> ".github/release_template.md"
+      - name: Create Release Draft
+        uses: softprops/action-gh-release@v1
+        with:
+          body_path: ".github/release_template.md"
+          draft: true
+          files: |
+            dist/unfccc_ghg_data-${{ env.PROJECT_VERSION }}-py3-none-any.whl
+            dist/unfccc_ghg_data-${{ env.PROJECT_VERSION }}.tar.gz
+        env:
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"

+ 153 - 12
.gitignore

@@ -1,16 +1,157 @@
-.idea
-venv
+# temporary
+src/unfccc_ghg_data/datasets
+
+# loging
+log/*
 geckodriver.log
 geckodriver.log
-__pycache__
+
+# private dev code
 /JG_test_code/
 /JG_test_code/
-.doit.db
-log/*
-UNFCCC_GHG_data/datasets
-UNFCCC_GHG_data/UNFCCC_DI_reader/test_UNFCCC_DI_reader.ipynb
-UNFCCC_GHG_data/UNFCCC_DI_reader/.ipynb_checkpoints/
-*.autosave
-#UNFCCC_GHG_data/UNFCCC_DI_reader
-build
-UNFCCC_GHG_data.egg-info
 
 
+# Notebooks
+*.ipynb
+
+# Databases
+*.db
+
+# Jupyter cache
+.jupyter_cache
+
+# Licence check
+licence-check.txt
+
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+.python-version
+
+# pipenv
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+#   However, in case of collaboration, if having platform-specific dependencies or dependencies
+#   having no cross-platform support, pipenv may install dependencies that don't work, or not
+#   install all needed dependencies.
+#Pipfile.lock
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# pycharm settings
+.idea
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
 
 
+# Mac stuff
+*.DS_Store

+ 50 - 0
.pre-commit-config.yaml

@@ -0,0 +1,50 @@
+# See https://pre-commit.com for more information
+ci:
+  autofix_prs: false
+  autoupdate_schedule: quarterly
+  autoupdate_branch: pre-commit-autoupdate
+
+# See https://pre-commit.com/hooks.html for more hooks
+repos:
+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: 'v4.4.0'
+    hooks:
+      - id: check-added-large-files
+      - id: check-ast
+      - id: check-case-conflict
+      - id: check-json
+      - id: check-merge-conflict
+      - id: check-symlinks
+      - id: check-yaml
+      - id: debug-statements
+      - id: detect-private-key
+      - id: end-of-file-fixer
+      - id: fix-byte-order-marker
+      - id: mixed-line-ending
+      - id: trailing-whitespace
+  - repo: local
+    hooks:
+      # Prevent committing .rej files
+      - id: forbidden-files
+        name: forbidden files
+        entry: found Copier update rejection files; review them and remove them
+        language: fail
+        files: "\\.rej$"
+  - repo: https://github.com/charliermarsh/ruff-pre-commit
+    rev: 'v0.0.263'
+    hooks:
+      - id: ruff
+        args: [ --fix, --exit-non-zero-on-fix ]
+  - repo: https://github.com/psf/black
+    rev: '23.3.0'
+    hooks:
+      - id: black
+  # additional to the above, apply black to doctests in source code
+  - repo: https://github.com/keewis/blackdoc
+    rev: v0.3.8
+    hooks:
+      - id: blackdoc
+  - repo: https://github.com/python-poetry/poetry
+    rev: '1.4.2'
+    hooks:
+      - id: poetry-check

+ 24 - 0
.readthedocs.yaml

@@ -0,0 +1,24 @@
+# .readthedocs.yaml
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Thank you also https://browniebroke.com/blog/specify-docs-dependency-groups-with-poetry-and-read-the-docs/
+
+# Required
+version: 2
+
+# Set the version of Python and other tools you might need
+build:
+  os: ubuntu-22.04
+  tools:
+    python: "3.9"
+  jobs:
+    post_create_environment:
+      - pip install poetry
+      - poetry config virtualenvs.create false
+    post_install:
+      - poetry install --with docs --all-extras
+
+# Build documentation in the docs/ directory with Sphinx
+sphinx:
+   configuration: docs/source/conf.py

+ 76 - 10
Makefile

@@ -1,10 +1,76 @@
-.SILENT: help
-help:
-	echo Options:
-	echo make venv: create virtual environment
-
-venv: UNFCCC_GHG_data
-	[ -d ./venv ] || python3 -m venv venv
-	./venv/bin/pip install --upgrade pip
-	./venv/bin/pip install -Ur code/requirements.txt
-	touch venv
+# Makefile to help automate key steps
+
+.DEFAULT_GOAL := help
+# Will likely fail on Windows, but Makefiles are in general not Windows
+# compatible so we're not too worried
+TEMP_FILE := $(shell mktemp)
+
+# A helper script to get short descriptions of each target in the Makefile
+define PRINT_HELP_PYSCRIPT
+import re, sys
+
+for line in sys.stdin:
+	match = re.match(r'^([\$$\(\)a-zA-Z_-]+):.*?## (.*)$$', line)
+	if match:
+		target, help = match.groups()
+		print("%-30s %s" % (target, help))
+endef
+export PRINT_HELP_PYSCRIPT
+
+
+help:  ## print short description of each target
+	@python3 -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)
+
+.PHONY: checks
+checks:  ## run all the linting checks of the codebase
+	@echo "=== pre-commit ==="; poetry run pre-commit run --all-files || echo "--- pre-commit failed ---" >&2; \
+		echo "=== mypy ==="; MYPYPATH=stubs poetry run mypy src || echo "--- mypy failed ---" >&2; \
+		echo "======"
+
+.PHONY: black
+black:  ## format the code using black
+	poetry run black src tests docs/source/conf.py scripts docs/source/notebooks/*.py
+	poetry run blackdoc src
+
+.PHONY: ruff-fixes
+ruff-fixes:  ## fix the code using ruff
+	poetry run ruff src tests scripts docs/source/conf.py docs/source/notebooks/*.py --fix
+
+
+.PHONY: test
+test:  ## run the tests
+	poetry run pytest src tests -r a -v --doctest-modules --cov=src
+
+# Note on code coverage and testing:
+# You must specify cov=src as otherwise funny things happen when doctests are
+# involved.
+# If you want to debug what is going on with coverage, we have found
+# that adding COVERAGE_DEBUG=trace to the front of the below command
+# can be very helpful as it shows you if coverage is tracking the coverage
+# of all of the expected files or not.
+# We are sure that the coverage maintainers would appreciate a PR that improves
+# the coverage handling when there are doctests and a `src` layout like ours.
+
+.PHONY: docs
+docs:  ## build the docs
+	poetry run sphinx-build -T -b html docs/source docs/build/html
+
+.PHONY: changelog-draft
+changelog-draft:  ## compile a draft of the next changelog
+	poetry run towncrier build --draft
+
+.PHONY: licence-check
+licence-check:  ## Check that licences of the dependencies are suitable
+	# Will likely fail on Windows, but Makefiles are in general not Windows
+	# compatible so we're not too worried
+	poetry export --without=tests --without=docs --without=dev > $(TEMP_FILE)
+	poetry run liccheck -r $(TEMP_FILE) -R licence-check.txt
+	rm -f $(TEMP_FILE)
+
+.PHONY: virtual-environment
+virtual-environment:  ## update virtual environment, create a new one if it doesn't already exist
+	poetry lock
+	# Put virtual environments in the project
+	poetry config virtualenvs.in-project true
+	poetry install --all-extras
+	poetry run pre-commit install

+ 81 - 2
README.md

@@ -1,7 +1,86 @@
-# Collaborative UNFCCC non-AnnexI dataset
+# Country greenhouse gas data submitted to the UNFCCC
 This repository aims to organize a collective effort to bring GHG emissions and related data submitted by developing countries (non-AnnexI) to the UNFCCC into a standardized machine readable format. We focus on data not available through the [UNFCCC DI interface](https://di.unfccc.int/) which is mostly data submitted in IPCC 2006 categories.
 This repository aims to organize a collective effort to bring GHG emissions and related data submitted by developing countries (non-AnnexI) to the UNFCCC into a standardized machine readable format. We focus on data not available through the [UNFCCC DI interface](https://di.unfccc.int/) which is mostly data submitted in IPCC 2006 categories.
 
 
-The code is based on [national-inventory-submissions](https://github.com/openclimatedata/national-inventory-submisions)
+<!--- sec-begin-description -->
+
+Reading country greenhouse gas data submitted to the United Nations Framework Convention on Climate Change (UNFCCC)in different submissions and formats and providing it in a standadized nc and csv format compatible with primap2. Data are read using different methods from APIs, xlsx and csv files as well as pdf files.
+
+
+
+[![CI](https://github.com/JGuetschow/UNFCCC_non-AnnexI_data/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/JGuetschow/UNFCCC_non-AnnexI_data/actions/workflows/ci.yaml)
+[![Coverage](https://codecov.io/gh/climate-resource/UNFCCC_non-AnnexI_data/branch/main/graph/badge.svg)](https://codecov.io/gh/climate-resource/UNFCCC_non-AnnexI_data)
+[![Docs](https://readthedocs.org/projects/unfccc-ghg-data/badge/?version=latest)](https://unfccc-ghg-data.readthedocs.io)
+
+**PyPI :**
+[![PyPI](https://img.shields.io/pypi/v/unfccc-ghg-data.svg)](https://pypi.org/project/unfccc-ghg-data/)
+[![PyPI: Supported Python versions](https://img.shields.io/pypi/pyversions/unfccc-ghg-data.svg)](https://pypi.org/project/unfccc-ghg-data/)
+[![PyPI install](https://github.com/JGuetschow/UNFCCC_non-AnnexI_data/actions/workflows/install.yaml/badge.svg?branch=main)](https://github.com/JGuetschow/UNFCCC_non-AnnexI_data/actions/workflows/install.yaml)
+
+**Other info :**
+[![License](https://img.shields.io/github/license/JGuetschow/UNFCCC_non-AnnexI_data.svg)](https://github.com/JGuetschow/UNFCCC_non-AnnexI_data/blob/main/LICENSE)
+[![Last Commit](https://img.shields.io/github/last-commit/JGuetschow/UNFCCC_non-AnnexI_data.svg)](https://github.com/JGuetschow/UNFCCC_non-AnnexI_data/commits/main)
+[![Contributors](https://img.shields.io/github/contributors/JGuetschow/UNFCCC_non-AnnexI_data.svg)](https://github.com/JGuetschow/UNFCCC_non-AnnexI_data/graphs/contributors)
+
+
+<!--- sec-end-description -->
+
+Full documentation can be found at:
+[unfccc-ghg-data.readthedocs.io](https://unfccc-ghg-data.readthedocs.io/en/latest/).
+We recommend reading the docs there because the internal documentation links
+don't render correctly on GitHub's viewer.
+
+## Installation
+
+<!--- sec-begin-installation -->
+
+Country greenhouse gas data submitted to the UNFCCC can be installed with conda or pip:
+
+```bash
+pip install unfccc-ghg-data
+conda install -c conda-forge unfccc-ghg-data
+```
+
+Additional dependencies can be installed using
+
+```bash
+# To add plotting dependencies
+pip install unfccc-ghg-data[plots]
+
+# If you are installing with conda, we recommend
+# installing the extras by hand because there is no stable
+# solution yet (issue here: https://github.com/conda/conda/issues/7502)
+```
+
+<!--- sec-end-installation -->
+
+### For developers
+
+<!--- sec-begin-installation-dev -->
+
+For development, we rely on [poetry](https://python-poetry.org) for all our
+dependency management. To get started, you will need to make sure that poetry
+is installed
+([instructions here](https://python-poetry.org/docs/#installing-with-the-official-installer),
+we found that pipx and pip worked better to install on a Mac).
+
+For all of work, we use our `Makefile`.
+You can read the instructions out and run the commands by hand if you wish,
+but we generally discourage this because it can be error prone.
+In order to create your environment, run `make virtual-environment`.
+
+If there are any issues, the messages from the `Makefile` should guide you
+through. If not, please raise an issue in the [issue tracker][issue_tracker].
+
+For the rest of our developer docs, please see [](development-reference).
+
+[issue_tracker]: https://github.com/JGuetschow/UNFCCC_non-AnnexI_data/issues
+
+<!--- sec-end-installation-dev -->
+
+
+TODO: old README below. reorganize into proper docs.
+
+The code for downloading submissions is based on [national-inventory-submissions](https://github.com/openclimatedata/national-inventory-submisions)
 
 
 
 
 **The repository is currently under initial development so a lot of things are still subject to change.**
 **The repository is currently under initial development so a lot of things are still subject to change.**

+ 0 - 10
UNFCCC_GHG_data/UNFCCC_CRF_reader/crf_specifications/__init__.py

@@ -1,10 +0,0 @@
-"""
-Define the CRF specifications here for easy access
-"""
-
-from .CRF2021_specification import CRF2021
-from .CRF2022_specification import CRF2022
-from .CRF2023_specification import CRF2023
-from .CRF2023_AUS_specification import CRF2023_AUS
-
-__all__ = ["CRF2021", "CRF2022", "CRF2023", "CRF2023_AUS"]

+ 0 - 30
UNFCCC_GHG_data/UNFCCC_DI_reader/__init__.py

@@ -1,30 +0,0 @@
-# submodule to read data from UNFCCC DI API using the unfccc_di_api package
-
-#import unfccc_di_api
-from .UNFCCC_DI_reader_core import read_UNFCCC_DI_for_country,  \
-    convert_DI_data_to_pm2_if, convert_DI_IF_data_to_pm2, \
-    read_UNFCCC_DI_for_country_group
-
-from .UNFCCC_DI_reader_proc import process_UNFCCC_DI_for_country, \
-    process_and_save_UNFCCC_DI_for_country, process_UNFCCC_DI_for_country_group
-
-from .UNFCCC_DI_reader_datalad import read_DI_for_country_datalad, \
-read_DI_for_country_group_datalad, process_DI_for_country_datalad, \
-    process_DI_for_country_group_datalad
-
-from .UNFCCC_DI_reader_helper import determine_filename
-
-__all__ = [
-    "read_UNFCCC_DI_for_country",
-    "convert_DI_data_to_pm2_if",
-    "convert_DI_IF_data_to_pm2",
-    "read_UNFCCC_DI_for_country_group",
-    "process_UNFCCC_DI_for_country",
-    "process_and_save_UNFCCC_DI_for_country",
-    "process_UNFCCC_DI_for_country_group",
-    "process_DI_for_country_group_datalad",
-    "read_DI_for_country_datalad",
-    "process_DI_for_country_datalad",
-    "read_DI_for_country_group_datalad",
-    "determine_filename",
-]

+ 0 - 33
UNFCCC_GHG_data/helper/__init__.py

@@ -1,33 +0,0 @@
-from .definitions import root_path, code_path, log_path
-from .definitions import extracted_data_path, extracted_data_path_UNFCCC
-from .definitions import legacy_data_path
-from .definitions import downloaded_data_path, downloaded_data_path_UNFCCC
-from .definitions import dataset_path, dataset_path_UNFCCC
-from .definitions import custom_country_mapping, custom_folders
-from .definitions import GWP_factors, gas_baskets
-from .functions import get_country_code, get_country_name, convert_categories
-from .functions import create_folder_mapping, process_data_for_country, get_code_file
-from .functions import fix_rows
-
-__all__ = [
-    "root_path",
-    "code_path",
-    "log_path",
-    "extracted_data_path",
-    "extracted_data_path_UNFCCC",
-    "legacy_data_path",
-    "downloaded_data_path",
-    "downloaded_data_path_UNFCCC",
-    "dataset_path",
-    "dataset_path_UNFCCC",
-    "custom_country_mapping",
-    "custom_folders",
-    "GWP_factors",
-    "gas_baskets",
-    "get_country_code",
-    "get_country_name",
-    "convert_categories",
-    "create_folder_mapping",
-    "process_data_for_country",
-    "fix_rows",
-]

+ 41 - 0
changelog/README.md

@@ -0,0 +1,41 @@
+# CHANGELOG
+
+This directory contains "news fragments", i.e. short files that contain a small markdown-formatted bit of text that will be
+added to the CHANGELOG when it is next compiled.
+
+The CHANGELOG will be read by users, so this description should be aimed to Country greenhouse gas data submitted to the UNFCCC users instead of
+describing internal changes which are only relevant to developers. Merge requests in combination with our git history provides additional
+developer-centric information.
+
+Make sure to use phrases in the past tense and use punctuation, examples:
+
+```
+Improved verbose diff output with sequences.
+
+Terminal summary statistics now use multiple colors.
+```
+
+Each file should have a name of the form `<MR>.<TYPE>.md`, where `<MR>` is the merge request number, and `<TYPE>` is one of:
+
+* `feature`: new user facing features, like new command-line options and new behaviour.
+* `improvement`: improvement of existing functionality, usually without requiring user intervention
+* `fix`: fixes a bug.
+* `docs`: documentation improvement, like rewording an entire section or adding missing docs.
+* `deprecation`: feature deprecation.
+* `breaking`: a change which may break existing uses, such as feature removal or behaviour change.
+* `trivial`: fixing a small typo or internal change that might be noteworthy.
+
+So for example: `123.feature.md`, `456.fix.md`.
+
+Since you need the merge request number for the filename, you must submit a MR first. From this MR, you can get the MR number and then create the news file. A single MR can also have multiple news items, for example a given MR may add a feature as well as
+deprecate some existing functionality.
+
+If you are not sure what issue type to use, don't hesitate to ask in your MR.
+
+`towncrier` preserves multiple paragraphs and formatting (code blocks, lists, and so on), but for entries other than
+features it is usually better to stick to a single paragraph to keep it concise. You may also use `MyST` [style
+cross-referencing](https://myst-parser.readthedocs.io/en/latest/syntax/cross-referencing.html) within your news items to link to other
+documentation.
+
+You can also run `towncrier build --draft` to see the draft changelog that will be appended to [docs/source/changelog.md]()
+on the next release.

+ 20 - 0
docs/Makefile

@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS    ?=
+SPHINXBUILD   ?= sphinx-build
+SOURCEDIR     = source
+BUILDDIR      = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

+ 35 - 0
docs/make.bat

@@ -0,0 +1,35 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=source
+set BUILDDIR=build
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+	echo.
+	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+	echo.installed, then set the SPHINXBUILD environment variable to point
+	echo.to the full path of the 'sphinx-build' executable. Alternatively you
+	echo.may add the Sphinx directory to PATH.
+	echo.
+	echo.If you don't have Sphinx installed, grab it from
+	echo.https://www.sphinx-doc.org/
+	exit /b 1
+)
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd

+ 0 - 0
docs/source/_static/.gitkeep


+ 0 - 0
docs/source/_templates/.gitkeep


+ 13 - 0
docs/source/api/unfccc_ghg_data.operations.rst

@@ -0,0 +1,13 @@
+unfccc\_ghg\_data.operations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. automodule:: unfccc_ghg_data.operations
+
+.. currentmodule:: unfccc_ghg_data.operations
+
+
+
+add\_two
+========
+
+.. autofunction:: add_two

+ 12 - 0
docs/source/api/unfccc_ghg_data.rst

@@ -0,0 +1,12 @@
+API Reference
+~~~~~~~~~~~~~
+
+.. automodule:: unfccc_ghg_data
+
+.. currentmodule:: unfccc_ghg_data
+
+
+.. autosummary::
+  :toctree: ./
+
+  unfccc_ghg_data.operations

+ 20 - 0
docs/source/changelog.md

@@ -0,0 +1,20 @@
+# Changelog
+
+Versions follow [Semantic Versioning](https://semver.org/) (`<major>.<minor>.<patch>`).
+
+Backward incompatible (breaking) changes will only be introduced in major versions
+with advance notice in the **Deprecations** section of releases.
+
+
+<!--
+You should *NOT* be adding new changelog entries to this file, this
+file is managed by towncrier. See changelog/README.md.
+
+You *may* edit previous changelogs to fix problems like typo corrections or such.
+To add a new changelog entry, please see
+https://pip.pypa.io/en/latest/development/contributing/#news-entries,
+noting that we use the `changelog` directory instead of news, md instead
+of rst and use slightly different categories.
+-->
+
+<!-- towncrier release notes start -->

+ 168 - 0
docs/source/conf.py

@@ -0,0 +1,168 @@
+"""
+Configuration file for the Sphinx documentation builder.
+
+For the full list of built-in configuration values, see the documentation:
+https://www.sphinx-doc.org/en/master/usage/configuration.html
+"""
+from functools import wraps
+
+from sphinxcontrib_autodocgen import AutoDocGen
+
+from src import unfccc_ghg_data
+
+# -- Project information -----------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
+
+project = "Country greenhouse gas data submitted to the UNFCCC"
+# put the authors in their own variable, so they can be reused later
+authors = ", ".join(["Johannes Gütschow"])
+# add a copyright year variable, we can extend this over time in future as
+# needed
+copyright_year = "2023"
+copyright = f"{copyright_year}, {authors}"
+
+# -- General configuration ---------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions = [
+    # create documentation automatically from source code
+    # https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html
+    "sphinx.ext.autodoc",
+    # automatic summary
+    "sphinx.ext.autosummary",
+    # automatic summary with better control
+    "sphinxcontrib_autodocgen",
+    # tell sphinx that we're using numpy style docstrings
+    # https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html
+    "sphinx.ext.napoleon",
+    # add support for type hints too (so type hints are included next to
+    # argument and return types in docs)
+    # https://github.com/tox-dev/sphinx-autodoc-typehints
+    # this must come after napoleon
+    # in the list for things to work properly
+    # https://github.com/tox-dev/sphinx-autodoc-typehints#compatibility-with-sphinxextnapoleon
+    "sphinx_autodoc_typehints",
+    # jupytext rendered notebook support (also loads myst_parser)
+    "myst_nb",
+    # links to other docs
+    "sphinx.ext.intersphinx",
+    # add source code to docs
+    "sphinx.ext.viewcode",
+    # add copy code button to code examples
+    "sphinx_copybutton",
+    # math support
+    "sphinx.ext.mathjax",
+]
+
+# general sphinx settings
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+# Don't include module names in object names (can also be left on,
+# depends a bit how your project is structured and what you prefer)
+add_module_names = False
+# Other global settings which we've never used but are included by default
+templates_path = ["_templates"]
+# Avoid sphinx thinking that conf.py is a source file because we use .py
+# endings for notebooks
+exclude_patterns = ["conf.py"]
+# Stop sphinx doing funny things with byte order markers
+source_encoding = "utf-8"
+
+# configure default settings for autodoc directives
+# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#directives
+autodoc_default_options = {
+    # Show the inheritance of classes
+    "show-inheritance": True,
+}
+
+# autosummary with autodocgen
+# make sure autosummary doesn't interfere
+autosummary_generate = True
+autosummary_generate_overwrite = False
+
+autodocgen_config = [
+    {
+        "modules": [unfccc_ghg_data],
+        "generated_source_dir": "docs/source/api",
+        # choose a different title for specific modules, e.g. the toplevel one
+        "module_title_decider": lambda modulename: "API Reference"
+        if modulename == "unfccc_ghg_data"
+        else modulename,
+    }
+]
+
+# monkey patch to remove leading newlines
+generate_module_rst_orig = AutoDocGen.generate_module_rst
+
+
+@wraps(generate_module_rst_orig)
+def _generate_module_rst_new(*args, **kwargs):
+    default = generate_module_rst_orig(*args, **kwargs)
+    out = default.lstrip("\n")
+    if not out.endswith("\n"):
+        out = f"{out}\n"
+
+    return out
+
+
+AutoDocGen.generate_module_rst = _generate_module_rst_new
+
+# napoleon extension settings
+# https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html
+# We use numpy style docstrings
+napoleon_numpy_docstring = True
+# We don't use google docstrings
+napoleon_google_docstring = False
+# Don't use separate rtype for the return documentation
+napoleon_use_rtype = False
+
+# autodoc type hints settings
+# https://github.com/tox-dev/sphinx-autodoc-typehints
+# include full name of classes when expanding type hints?
+typehints_fully_qualified = True
+# Add rtype directive if needed
+typehints_document_rtype = True
+# Put the return type as part of the return documentation
+typehints_use_rtype = False
+
+# Left-align maths equations
+mathjax3_config = {"chtml": {"displayAlign": "center"}}
+
+# myst configuration
+myst_enable_extensions = ["amsmath", "dollarmath"]
+# cache because we save our notebooks as `.py` files i.e. without output
+# stored so auto doesn't work (it just ends up being run every time)
+nb_execution_mode = "cache"
+nb_execution_raise_on_error = True
+nb_execution_show_tb = True
+nb_execution_timeout = 120
+nb_custom_formats = {".py": ["jupytext.reads", {"fmt": "py:percent"}]}
+
+# -- Options for HTML output -------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
+
+# Pick your theme for html output, we typically use the read the docs theme
+html_theme = "sphinx_rtd_theme"
+html_static_path = ["_static"]
+
+
+# Ignore ipynb files when building (see https://github.com/executablebooks/MyST-NB/issues/363).
+def setup(app):
+    """
+    Set up the Sphinx app
+    """
+    app.registry.source_suffix.pop(".ipynb", None)
+
+
+# Intersphinx mapping
+intersphinx_mapping = {
+    "numpy": ("https://docs.scipy.org/doc/numpy", None),
+    "pandas": ("https://pandas.pydata.org/pandas-docs/stable", None),
+    "python": ("https://docs.python.org/3", None),
+    "pyam": ("https://pyam-iamc.readthedocs.io/en/latest", None),
+    "scmdata": ("https://scmdata.readthedocs.io/en/latest", None),
+    "xarray": ("http://xarray.pydata.org/en/stable", None),
+    "pint": (
+        "https://pint.readthedocs.io/en/latest",
+        None,
+    ),
+}

+ 55 - 0
docs/source/development.md

@@ -0,0 +1,55 @@
+(development-reference)=
+# Development
+
+Notes for developers. If you want to get involved, please do!
+
+## Language
+
+We use British English for our development.
+We do this for consistency with the broader work context of our lead developers.
+
+## Versioning
+
+This package follows the version format described in [PEP440](https://peps.python.org/pep-0440/) and
+[Semantic Versioning](https://semver.org/) to describe how the version should change depending on the updates to the
+code base. Our commit messages are written using written to follow the
+[conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) standard which makes it easy to find the
+commits that matter when traversing through the commit history.
+
+(releasing-reference)=
+## Releasing
+
+Releasing is semi-automated via a CI job. The CI job requires the type of version bump that will be performed to be
+manually specified. See the poetry docs for the [list of available bump rules](https://python-poetry.org/docs/cli/#version).
+
+### Standard process
+
+The steps required are the following:
+
+
+1. Bump the version: manually trigger the "bump" workflow from the main branch
+   (see here: https://github.com/JGuetschow/UNFCCC_non-AnnexI_data/actions/workflows/bump.yaml).
+   A valid "bump_rule" (see https://python-poetry.org/docs/cli/#version) will need to be specified.
+   This will then trigger a draft release.
+
+1. Edit the draft release which has been created
+   (see here:
+   https://github.com/JGuetschow/UNFCCC_non-AnnexI_data/releases).
+   Once you are happy with the release (removed placeholders, added key
+   announcements etc.) then hit 'Publish release'. This triggers a release to
+   PyPI (which you can then add to the release if you want).
+
+
+1. That's it, release done, make noise on social media of choice, do whatever
+   else
+
+1. Enjoy the newly available version
+
+## Read the Docs
+
+Our documentation is hosted by
+[Read the Docs (RtD)](https://www.readthedocs.org/), a service for which we are
+very grateful. The RtD configuration can be found in the `.readthedocs.yaml`
+file in the root of this repository. The docs are automatically
+deployed at
+[unfccc-ghg-data.readthedocs.io](https://unfccc-ghg-data.readthedocs.io/en/latest/).

+ 42 - 0
docs/source/index.md

@@ -0,0 +1,42 @@
+% Country greenhouse gas data submitted to the UNFCCC documentation master file
+% This was based on a sphinx-quickstart from Mon May  1 20:20:44 2023.
+% If you're having issues with sphinx, you may need to regenerate this doc.
+% You can adapt this file completely to your liking, but it should at least
+% contain the root `toctree` directive.
+
+# Country greenhouse gas data submitted to the UNFCCC
+
+```{include} ../../README.md
+:start-after: <!--- sec-begin-description -->
+:end-before: <!--- sec-end-description -->
+```
+
+## Installation
+
+```{include} ../../README.md
+:start-after: <!--- sec-begin-installation -->
+:end-before: <!--- sec-end-installation -->
+```
+
+### For developers
+
+```{include} ../../README.md
+:start-after: <!--- sec-begin-installation-dev -->
+:end-before: <!--- sec-end-installation-dev -->
+```
+
+```{toctree}
+:caption: Contents
+:maxdepth: 2
+notebooks
+development
+api/unfccc_ghg_data
+changelog
+```
+
+Index
+-----
+
+- :ref:`genindex`
+- :ref:`modindex`
+- :ref:`search`

+ 21 - 0
docs/source/notebooks.md

@@ -0,0 +1,21 @@
+(notebooks-reference)=
+# Notebooks
+
+Here we provide various examples of how to use Country greenhouse gas data submitted to the UNFCCC.
+They  are derived from
+[jupyter notebooks](https://docs.jupyter.org/en/latest/start/index.html),
+but are saved using [jupytext](https://jupytext.readthedocs.io/en/latest/)
+to keep our repository slim and make it easier to track changes.
+
+## Basic demos
+
+```{toctree}
+:caption: Contents
+:maxdepth: 1
+notebooks/basic-demo.py
+```
+
+## Notebook execution info
+
+```{nb-exec-table}
+```

+ 24 - 0
docs/source/notebooks/basic-demo.py

@@ -0,0 +1,24 @@
+# ---
+# jupyter:
+#   jupytext:
+#     text_representation:
+#       extension: .py
+#       format_name: percent
+#       format_version: '1.3'
+#       jupytext_version: 1.14.5
+#   kernelspec:
+#     display_name: Python 3 (ipykernel)
+#     language: python
+#     name: python3
+# ---
+
+# %% [markdown]
+# # Basic demo
+#
+# This notebook gives a basic demonstration of how to use Country greenhouse gas data submitted to the UNFCCC.
+
+# %%
+from src import unfccc_ghg_data
+
+# %%
+print(f"You are using unfccc_ghg_data version {unfccc_ghg_data.__version__}")

+ 82 - 66
dodo.py

@@ -1,24 +1,35 @@
 # define tasks for UNFCCC data repository
 # define tasks for UNFCCC data repository
 from doit import get_var
 from doit import get_var
 import os
 import os
+import sys
 
 
 # TODO: task for folder mapping
 # TODO: task for folder mapping
 
 
 # create virtual environment
 # create virtual environment
-def task_setup_venv():
-    """Create virtual environment"""
+# def task_setup_venv():
+#     """Create virtual environment"""
+#     return {
+#         'file_dep': ['requirements_dev.txt', 'setup.cfg', 'pyproject.toml'],
+#         'actions': ['python3 -m venv venv',
+#                     './venv/bin/pip install --upgrade pip wheel',
+#                     #'./venv/bin/pip install -Ur unfccc_ghg_data/requirements.txt',
+#                     './venv/bin/pip install --upgrade --upgrade-strategy '
+#                     'eager -e .[dev]',
+#                     'touch venv',],
+#         'targets': ['venv'],
+#         'verbosity': 2,
+#     }
+
+def task_in_venv():
+    def in_venv():
+        if sys.prefix == sys.base_prefix:
+            raise ValueError("You need to run the code from the virtual environment.")
+
     return {
     return {
-        'file_dep': ['requirements_dev.txt', 'setup.cfg', 'pyproject.toml'],
-        'actions': ['python3 -m venv venv',
-                    './venv/bin/pip install --upgrade pip wheel',
-                    #'./venv/bin/pip install -Ur UNFCCC_GHG_data/requirements.txt',
-                    './venv/bin/pip install --upgrade --upgrade-strategy '
-                    'eager -e .[dev]',
-                    'touch venv',],
-        'targets': ['venv'],
-        'verbosity': 2,
+        'actions': [in_venv],
     }
     }
 
 
+
 # set UNFCCC_GHG_ROOT_PATH environment variable
 # set UNFCCC_GHG_ROOT_PATH environment variable
 def task_set_env():
 def task_set_env():
     """
     """
@@ -42,11 +53,11 @@ def task_map_folders():
     Create or update the folder mapping in the given folder
     Create or update the folder mapping in the given folder
     """
     """
     return {
     return {
-        'actions': [f"./venv/bin/python UNFCCC_GHG_data/helper/folder_mapping.py "
+        'actions': [f"python src/unfccc_ghg_data/helper/folder_mapping.py "
                     f"--folder={read_config_folder['folder']}"],
                     f"--folder={read_config_folder['folder']}"],
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 
 
@@ -57,10 +68,10 @@ def task_update_bur():
         'targets': ['downloaded_data/UNFCCC/submissions-bur.csv'],
         'targets': ['downloaded_data/UNFCCC/submissions-bur.csv'],
         'actions': ['datalad run -m "Fetch BUR submissions" '
         'actions': ['datalad run -m "Fetch BUR submissions" '
                     '-o downloaded_data/UNFCCC/submissions-bur.csv '
                     '-o downloaded_data/UNFCCC/submissions-bur.csv '
-                    './venv/bin/python UNFCCC_GHG_data/UNFCCC_downloader/fetch_submissions_bur.py'],
+                    'python src/unfccc_ghg_data/unfccc_downloader/fetch_submissions_bur.py'],
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 
 
@@ -72,13 +83,13 @@ def task_download_bur():
         # before download
         # before download
         'actions': ['datalad run -m "Download BUR submissions" '
         'actions': ['datalad run -m "Download BUR submissions" '
                     '-i downloaded_data/UNFCCC/submissions-bur.csv '
                     '-i downloaded_data/UNFCCC/submissions-bur.csv '
-                    './venv/bin/python UNFCCC_GHG_data/UNFCCC_downloader/download_non-annexI.py --category=BUR',
-                    f"./venv/bin/python UNFCCC_GHG_data/helper/folder_mapping.py "
+                    'python src/unfccc_ghg_data/unfccc_downloader/download_non-annexI.py --category=BUR',
+                    f"python src/unfccc_ghg_data/helper/folder_mapping.py "
                     f"--folder=downloaded_data/UNFCCC"
                     f"--folder=downloaded_data/UNFCCC"
                     ],
                     ],
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 
 
@@ -88,10 +99,10 @@ def task_update_nc():
         'targets': ['downloaded_data/UNFCCC/submissions-nc.csv'],
         'targets': ['downloaded_data/UNFCCC/submissions-nc.csv'],
         'actions': ['datalad run -m "Fetch NC submissions" '
         'actions': ['datalad run -m "Fetch NC submissions" '
                     '-o downloaded_data/UNFCCC/submissions-nc.csv '
                     '-o downloaded_data/UNFCCC/submissions-nc.csv '
-                    './venv/bin/python UNFCCC_GHG_data/UNFCCC_downloader/fetch_submissions_nc.py'],
+                    'python src/unfccc_ghg_data/unfccc_downloader/fetch_submissions_nc.py'],
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 
 
@@ -103,13 +114,13 @@ def task_download_nc():
         # before download
         # before download
         'actions': ['datalad run -m "Download NC submissions" '
         'actions': ['datalad run -m "Download NC submissions" '
                     '-i downloaded_data/UNFCCC/submissions-nc.csv '
                     '-i downloaded_data/UNFCCC/submissions-nc.csv '
-                    './venv/bin/python UNFCCC_GHG_data/UNFCCC_downloader/download_non-annexI.py --category=NC',
-                    f"./venv/bin/python UNFCCC_GHG_data/helper/folder_mapping.py "
+                    'python src/unfccc_ghg_data/unfccc_downloader/download_non-annexI.py --category=NC',
+                    f"python src/unfccc_ghg_data/helper/folder_mapping.py "
                     f"--folder=downloaded_data/UNFCCC"
                     f"--folder=downloaded_data/UNFCCC"
                     ],
                     ],
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 # annexI data: one update call for all data types (as they are on one page)
 # annexI data: one update call for all data types (as they are on one page)
@@ -128,11 +139,11 @@ def task_update_annexi():
         'actions': [f"datalad run -m 'Fetch AnnexI submissions for {update_aI_config['year']}' "
         'actions': [f"datalad run -m 'Fetch AnnexI submissions for {update_aI_config['year']}' "
                     "--explicit "
                     "--explicit "
                     f"-o downloaded_data/UNFCCC/submissions-annexI_{update_aI_config['year']}.csv "
                     f"-o downloaded_data/UNFCCC/submissions-annexI_{update_aI_config['year']}.csv "
-                    f"./venv/bin/python UNFCCC_GHG_data/UNFCCC_downloader/fetch_submissions_annexI.py "
+                    f"python src/unfccc_ghg_data/unfccc_downloader/fetch_submissions_annexI.py "
                     f"--year={update_aI_config['year']}"],
                     f"--year={update_aI_config['year']}"],
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 
 
@@ -145,14 +156,14 @@ def task_download_annexi():
         'actions': [f"datalad run -m 'Download AnnexI submissions for "
         'actions': [f"datalad run -m 'Download AnnexI submissions for "
                     f"{update_aI_config['category']}{update_aI_config['year']}' "
                     f"{update_aI_config['category']}{update_aI_config['year']}' "
                     f"-i downloaded_data/UNFCCC/submissions-annexI_{update_aI_config['year']}.csv "
                     f"-i downloaded_data/UNFCCC/submissions-annexI_{update_aI_config['year']}.csv "
-                    f"./venv/bin/python UNFCCC_GHG_data/UNFCCC_downloader/download_annexI.py "
+                    f"python src/unfccc_ghg_data/unfccc_downloader/download_annexI.py "
                     f"--category={update_aI_config['category']} --year={update_aI_config['year']}",
                     f"--category={update_aI_config['category']} --year={update_aI_config['year']}",
-                    f"./venv/bin/python UNFCCC_GHG_data/helper/folder_mapping.py "
+                    f"python src/unfccc_ghg_data/helper/folder_mapping.py "
                     f"--folder=downloaded_data/UNFCCC"
                     f"--folder=downloaded_data/UNFCCC"
                     ],
                     ],
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 
 
@@ -160,13 +171,13 @@ def task_download_ndc():
     """ Download NDC submissions """
     """ Download NDC submissions """
     return {
     return {
         'actions': ['datalad run -m "Download NDC submissions" '
         'actions': ['datalad run -m "Download NDC submissions" '
-                    './venv/bin/python UNFCCC_GHG_data/UNFCCC_downloader/download_ndc.py',
-                    f"./venv/bin/python UNFCCC_GHG_data/helper/folder_mapping.py "
+                    'python src/unfccc_ghg_data/unfccc_downloader/download_ndc.py',
+                    f"python src/unfccc_ghg_data/helper/folder_mapping.py "
                     f"--folder=downloaded_data/UNFCCC"
                     f"--folder=downloaded_data/UNFCCC"
                     ],
                     ],
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 
 
@@ -180,16 +191,16 @@ read_config = {
 
 
 # TODO: make individual task for non-UNFCCC submissions
 # TODO: make individual task for non-UNFCCC submissions
 def task_read_unfccc_submission():
 def task_read_unfccc_submission():
-    """ Read submission for a country (if UNFCCC_GHG_data exists) (not for CRF)"""
+    """ Read submission for a country (if code exists) (not for CRF)"""
     return {
     return {
-        'actions': [f"./venv/bin/python UNFCCC_GHG_data/UNFCCC_reader/read_UNFCCC_submission.py "
+        'actions': [f"python src/unfccc_ghg_data/unfccc_reader/read_UNFCCC_submission.py "
                     f"--country={read_config['country']} --submission={read_config['submission']}",
                     f"--country={read_config['country']} --submission={read_config['submission']}",
-                    f"./venv/bin/python UNFCCC_GHG_data/helper/folder_mapping.py "
+                    f"python src/unfccc_ghg_data/helper/folder_mapping.py "
                     f"--folder=extracted_data/UNFCCC"
                     f"--folder=extracted_data/UNFCCC"
                     ],
                     ],
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 
 
@@ -208,11 +219,12 @@ read_config_crf = {
 def task_read_unfccc_crf_submission():
 def task_read_unfccc_crf_submission():
     """ Read CRF submission for a country """
     """ Read CRF submission for a country """
     actions = [
     actions = [
-        f"./venv/bin/python UNFCCC_GHG_data/UNFCCC_CRF_reader/read_UNFCCC_CRF_submission_datalad.py "
+        f"python src/unfccc_ghg_data/unfccc_crf_reader"
+        f"/read_unfccc_crf_submission_datalad.py "
         f"--country={read_config_crf['country']} "
         f"--country={read_config_crf['country']} "
         f"--submission_year={read_config_crf['submission_year']} "
         f"--submission_year={read_config_crf['submission_year']} "
         f"--submission_date={read_config_crf['submission_date']} ",
         f"--submission_date={read_config_crf['submission_date']} ",
-        f"./venv/bin/python UNFCCC_GHG_data/helper/folder_mapping.py "
+        f"python src/unfccc_ghg_data/helper/folder_mapping.py "
         f"--folder=extracted_data/UNFCCC"
         f"--folder=extracted_data/UNFCCC"
         ]
         ]
     if read_config_crf["re_read"] == "True":
     if read_config_crf["re_read"] == "True":
@@ -221,16 +233,17 @@ def task_read_unfccc_crf_submission():
         'actions': actions,
         'actions': actions,
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 
 
 def task_read_new_unfccc_crf_for_year():
 def task_read_new_unfccc_crf_for_year():
     """ Read CRF submission for all countries for given submission year. by default only reads
     """ Read CRF submission for all countries for given submission year. by default only reads
     data not present yet. Only reads the latest updated submission for each country."""
     data not present yet. Only reads the latest updated submission for each country."""
-    actions = [f"./venv/bin/python UNFCCC_GHG_data/UNFCCC_CRF_reader/read_new_UNFCCC_CRF_for_year_datalad.py "
+    actions = [f"python src/unfccc_ghg_data/unfccc_crf_reader"
+               f"/read_new_unfccc_crf_for_year_datalad.py "
                f"--submission_year={read_config_crf['submission_year']} ",
                f"--submission_year={read_config_crf['submission_year']} ",
-               f"./venv/bin/python UNFCCC_GHG_data/helper/folder_mapping.py "
+               f"python src/unfccc_ghg_data/helper/folder_mapping.py "
                f"--folder=extracted_data/UNFCCC"
                f"--folder=extracted_data/UNFCCC"
                ]
                ]
     # specifying countries is currently disabled duo to problems with command line
     # specifying countries is currently disabled duo to problems with command line
@@ -244,16 +257,16 @@ def task_read_new_unfccc_crf_for_year():
         'actions': actions,
         'actions': actions,
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 
 
 def task_test_read_unfccc_crf_for_year():
 def task_test_read_unfccc_crf_for_year():
     """ Read CRF submission for all countries for given submission year. by default only reads
     """ Read CRF submission for all countries for given submission year. by default only reads
     data not present yet. Only reads the latest updated submission for each country."""
     data not present yet. Only reads the latest updated submission for each country."""
-    actions = [f"./venv/bin/python "
-               f"UNFCCC_GHG_data/UNFCCC_CRF_reader"
-               f"/test_read_UNFCCC_CRF_for_year.py "
+    actions = [f"python "
+               f"src/unfccc_ghg_data/unfccc_crf_reader"
+               f"/test_read_unfccc_crf_for_year.py "
                f"--submission_year={read_config_crf['submission_year']} "
                f"--submission_year={read_config_crf['submission_year']} "
                f"--country={read_config_crf['country']} "
                f"--country={read_config_crf['country']} "
                ]
                ]
@@ -267,26 +280,26 @@ def task_test_read_unfccc_crf_for_year():
         'actions': actions,
         'actions': actions,
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 
 
 def task_compile_raw_unfccc_crf_for_year():
 def task_compile_raw_unfccc_crf_for_year():
     """ Read CRF submission for all countries for given submission year. by default only reads
     """ Read CRF submission for all countries for given submission year. by default only reads
     data not present yet. Only reads the latest updated submission for each country."""
     data not present yet. Only reads the latest updated submission for each country."""
-    actions = [f"./venv/bin/python "
-               f"UNFCCC_GHG_data/UNFCCC_CRF_reader/CRF_raw_for_year.py "
+    actions = [f"python "
+               f"src/unfccc_ghg_data/unfccc_crf_reader/crf_raw_for_year.py "
                f"--submission_year={read_config_crf['submission_year']} "
                f"--submission_year={read_config_crf['submission_year']} "
                ]
                ]
     return {
     return {
         'actions': actions,
         'actions': actions,
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 # tasks for DI reader
 # tasks for DI reader
-# datalad run is called from within the read_UNFCCC_DI_for_country.py script
+# datalad run is called from within the read_unfccc_di_for_country.py script
 read_config_di = {
 read_config_di = {
     "country": get_var('country', None),
     "country": get_var('country', None),
     "date": get_var('date', None),
     "date": get_var('date', None),
@@ -297,41 +310,43 @@ read_config_di = {
 def task_read_unfccc_di_for_country():
 def task_read_unfccc_di_for_country():
     """ Read DI data for a country """
     """ Read DI data for a country """
     actions = [
     actions = [
-        f"./venv/bin/python "
-        f"UNFCCC_GHG_data/UNFCCC_DI_reader/read_UNFCCC_DI_for_country_datalad.py "
+        f"python "
+        f"src/unfccc_ghg_data/unfccc_di_reader/read_unfccc_di_for_country_datalad.py "
         f"--country={read_config_di['country']}",
         f"--country={read_config_di['country']}",
-        f"./venv/bin/python UNFCCC_GHG_data/helper/folder_mapping.py "
+        f"python src/unfccc_ghg_data/helper/folder_mapping.py "
         f"--folder=extracted_data/UNFCCC"
         f"--folder=extracted_data/UNFCCC"
         ]
         ]
     return {
     return {
         'actions': actions,
         'actions': actions,
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 def task_process_unfccc_di_for_country():
 def task_process_unfccc_di_for_country():
     """ Process DI data for a country """
     """ Process DI data for a country """
     actions = [
     actions = [
-        f"./venv/bin/python "
-        f"UNFCCC_GHG_data/UNFCCC_DI_reader/process_UNFCCC_DI_for_country_datalad.py "
+        f"python "
+        f"src/unfccc_ghg_data/unfccc_di_reader/process_unfccc_di_for_country_datalad"
+        f".py "
         f"--country={read_config_di['country']} --date={read_config_di['date']}",
         f"--country={read_config_di['country']} --date={read_config_di['date']}",
-        f"./venv/bin/python UNFCCC_GHG_data/helper/folder_mapping.py "
+        f"python src/unfccc_ghg_data/helper/folder_mapping.py "
         f"--folder=extracted_data/UNFCCC"
         f"--folder=extracted_data/UNFCCC"
         ]
         ]
     return {
     return {
         'actions': actions,
         'actions': actions,
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 def task_read_unfccc_di_for_country_group():
 def task_read_unfccc_di_for_country_group():
     """ Read DI data for a country group """
     """ Read DI data for a country group """
     actions = [
     actions = [
-        f"./venv/bin/python "
-        f"UNFCCC_GHG_data/UNFCCC_DI_reader/read_UNFCCC_DI_for_country_group_datalad.py",
-        f"./venv/bin/python UNFCCC_GHG_data/helper/folder_mapping.py "
+        f"python "
+        f"src/unfccc_ghg_data/unfccc_di_reader/read_unfccc_di_for_country_group_datalad"
+        f".py",
+        f"python src/unfccc_ghg_data/helper/folder_mapping.py "
         f"--folder=extracted_data/UNFCCC"
         f"--folder=extracted_data/UNFCCC"
         ]
         ]
     if read_config_di["annexI"] == "True":
     if read_config_di["annexI"] == "True":
@@ -341,15 +356,16 @@ def task_read_unfccc_di_for_country_group():
         'actions': actions,
         'actions': actions,
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 
 
 def task_process_unfccc_di_for_country_group():
 def task_process_unfccc_di_for_country_group():
     """ Process DI data for a country group """
     """ Process DI data for a country group """
     actions = [
     actions = [
-        f"./venv/bin/python "
-        f"UNFCCC_GHG_data/UNFCCC_DI_reader/process_UNFCCC_DI_for_country_group_datalad"
+        f"python "
+        f"src/unfccc_ghg_data/unfccc_di_reader"
+        f"/process_unfccc_di_for_country_group_datalad"
         f".py",
         f".py",
         ]
         ]
     if read_config_di["annexI"] == "True":
     if read_config_di["annexI"] == "True":
@@ -361,7 +377,7 @@ def task_process_unfccc_di_for_country_group():
         'actions': actions,
         'actions': actions,
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 
 # general tasks
 # general tasks
@@ -369,10 +385,10 @@ def task_country_info():
     """ Print information on submissions and datasets
     """ Print information on submissions and datasets
     available for given country"""
     available for given country"""
     return {
     return {
-        'actions': [f"./venv/bin/python UNFCCC_GHG_data/helper/country_info.py "
+        'actions': [f"python src/unfccc_ghg_data/helper/country_info.py "
                     f"--country={read_config['country']}"],
                     f"--country={read_config['country']}"],
         'task_dep': ['set_env'],
         'task_dep': ['set_env'],
         'verbosity': 2,
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
     }
 
 

+ 4263 - 0
poetry.lock

@@ -0,0 +1,4263 @@
+# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
+
+[[package]]
+name = "alabaster"
+version = "0.7.13"
+description = "A configurable sidebar-enabled Sphinx theme"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"},
+    {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"},
+]
+
+[[package]]
+name = "annexremote"
+version = "1.6.4"
+description = "git annex special remotes made easy"
+optional = false
+python-versions = "*"
+files = [
+    {file = "annexremote-1.6.4-py3-none-any.whl", hash = "sha256:74fdf4d4e20fd3b5a5bc827b4c488dd5de95cb8161cda77ad06a6b5fbd22e82b"},
+    {file = "annexremote-1.6.4.tar.gz", hash = "sha256:da4198a25b36c699216fd5f1e93ba0e655e167b6822b64284a4bf90388ea69ae"},
+]
+
+[package.extras]
+doc = ["sphinx"]
+tests = ["coverage", "pytest"]
+
+[[package]]
+name = "appnope"
+version = "0.1.3"
+description = "Disable App Nap on macOS >= 10.9"
+optional = false
+python-versions = "*"
+files = [
+    {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"},
+    {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"},
+]
+
+[[package]]
+name = "asttokens"
+version = "2.4.1"
+description = "Annotate AST trees with source code positions"
+optional = false
+python-versions = "*"
+files = [
+    {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"},
+    {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"},
+]
+
+[package.dependencies]
+six = ">=1.12.0"
+
+[package.extras]
+astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"]
+test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"]
+
+[[package]]
+name = "attrs"
+version = "23.1.0"
+description = "Classes Without Boilerplate"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
+    {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
+]
+
+[package.extras]
+cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
+dev = ["attrs[docs,tests]", "pre-commit"]
+docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
+tests = ["attrs[tests-no-zope]", "zope-interface"]
+tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+
+[[package]]
+name = "babel"
+version = "2.13.1"
+description = "Internationalization utilities"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "Babel-2.13.1-py3-none-any.whl", hash = "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed"},
+    {file = "Babel-2.13.1.tar.gz", hash = "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900"},
+]
+
+[package.dependencies]
+setuptools = {version = "*", markers = "python_version >= \"3.12\""}
+
+[package.extras]
+dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
+
+[[package]]
+name = "beautifulsoup4"
+version = "4.12.2"
+description = "Screen-scraping library"
+optional = false
+python-versions = ">=3.6.0"
+files = [
+    {file = "beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a"},
+    {file = "beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da"},
+]
+
+[package.dependencies]
+soupsieve = ">1.2"
+
+[package.extras]
+html5lib = ["html5lib"]
+lxml = ["lxml"]
+
+[[package]]
+name = "black"
+version = "23.3.0"
+description = "The uncompromising code formatter."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"},
+    {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"},
+    {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"},
+    {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"},
+    {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"},
+    {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"},
+    {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"},
+    {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"},
+    {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"},
+    {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"},
+    {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"},
+    {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"},
+    {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"},
+    {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"},
+    {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"},
+    {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"},
+    {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"},
+    {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"},
+    {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"},
+    {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"},
+    {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"},
+    {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"},
+    {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"},
+    {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"},
+    {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"},
+]
+
+[package.dependencies]
+click = ">=8.0.0"
+mypy-extensions = ">=0.4.3"
+packaging = ">=22.0"
+pathspec = ">=0.9.0"
+platformdirs = ">=2"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
+
+[package.extras]
+colorama = ["colorama (>=0.4.3)"]
+d = ["aiohttp (>=3.7.4)"]
+jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
+uvloop = ["uvloop (>=0.15.2)"]
+
+[[package]]
+name = "blackdoc"
+version = "0.3.8"
+description = "run black on documentation code snippets"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "blackdoc-0.3.8-py3-none-any.whl", hash = "sha256:c003a1b72d57692b343815c8b7a15e78977caba96c86060def892602b5aba083"},
+    {file = "blackdoc-0.3.8.tar.gz", hash = "sha256:3c9d5534f92557a627a31550c7faec8363b5b0929bbb0ca3f5df179a81a9d6b2"},
+]
+
+[package.dependencies]
+black = "*"
+more-itertools = "*"
+pathspec = "*"
+rich = "*"
+tomli = "*"
+
+[[package]]
+name = "boto"
+version = "2.49.0"
+description = "Amazon Web Services Library"
+optional = false
+python-versions = "*"
+files = [
+    {file = "boto-2.49.0-py2.py3-none-any.whl", hash = "sha256:147758d41ae7240dc989f0039f27da8ca0d53734be0eb869ef16e3adcfa462e8"},
+    {file = "boto-2.49.0.tar.gz", hash = "sha256:ea0d3b40a2d852767be77ca343b58a9e3a4b00d9db440efb8da74b4e58025e5a"},
+]
+
+[[package]]
+name = "bottleneck"
+version = "1.3.7"
+description = "Fast NumPy array functions written in C"
+optional = false
+python-versions = "*"
+files = [
+    {file = "Bottleneck-1.3.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ada1a9ff93fd6b1b19f12398a6761940372b00e53d86db98bd4613a751c60043"},
+    {file = "Bottleneck-1.3.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a477101ee12155a0d2f9a82cd3e2a44b9b1aa53afe5b20acc065c91cf35c3106"},
+    {file = "Bottleneck-1.3.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfe5f3010e9ad8ae54871d1e8fd61109c5981ed8d9d14e8496a1c37fe2050a04"},
+    {file = "Bottleneck-1.3.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:955df78713ff58cf815c0a1fa4782b2dc51a8787c0971688472c64b267303855"},
+    {file = "Bottleneck-1.3.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:92fc5d3ecfedde3b28c56ca686cff70a8125d1ddc281eb468b5e9d6a61269802"},
+    {file = "Bottleneck-1.3.7-cp310-cp310-win32.whl", hash = "sha256:e2a290dcb148c0ddf182052e333892e46730c7d39a1f251af87e3d81a43cdde3"},
+    {file = "Bottleneck-1.3.7-cp310-cp310-win_amd64.whl", hash = "sha256:9170ebee4cff423c92b3760afec179bded90eaede7c70dd27cf5f406cc00a1e7"},
+    {file = "Bottleneck-1.3.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:752c97d64ebebdc10a5568d97b81b4971238fa4b53533248d227c4ea759aee4e"},
+    {file = "Bottleneck-1.3.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbda2b27e81a47b7578bce6a8cb2f5eb899279c828d8efb5a154d8ede785093d"},
+    {file = "Bottleneck-1.3.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79160e49a5a0438468b970967e29addde2d9c6a6ce930144de7ccd8151077603"},
+    {file = "Bottleneck-1.3.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:abfc22762640cc7716c1bd9a409bde0f834167a2584775eb644c6afe7bae3319"},
+    {file = "Bottleneck-1.3.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a39049aa1cb798538f96150098f50badb37417c41cecfa8a441c0c4e6433c7e"},
+    {file = "Bottleneck-1.3.7-cp311-cp311-win32.whl", hash = "sha256:b624023f173332d209ed5bd4134fae43d2432d61c6b17a49a6b7c5591caa7cc4"},
+    {file = "Bottleneck-1.3.7-cp311-cp311-win_amd64.whl", hash = "sha256:bd69b1844c90f6bcf1b679a608fb2c0909be5e045f91674d61a0e4c3596644be"},
+    {file = "Bottleneck-1.3.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c8fa2d85298cdd0f88f51fb46604039abe9a5a2b57e00acfe2b64f546754c053"},
+    {file = "Bottleneck-1.3.7-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09fa97df2f572aed5da487d3fe467829c2212c97b1d63c768ec9be9fd1c57a9"},
+    {file = "Bottleneck-1.3.7-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f239ba0d992c013564979cff4fecf2b251614de3730641e79d05ecc09268c00c"},
+    {file = "Bottleneck-1.3.7-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:f5409cf6db5e60256626a7c110b2b4c80d9f6b0d1ec0b66565bbab978f96b7a6"},
+    {file = "Bottleneck-1.3.7-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b3c65a9aedada04872cba450676d132d7af8b9da47f58b82f20ffe9b9ff77a46"},
+    {file = "Bottleneck-1.3.7-cp36-cp36m-win32.whl", hash = "sha256:b4a47f972e919d22c1725ff7262d209e6ea3a4d9bcfea71fb454a18e166515ec"},
+    {file = "Bottleneck-1.3.7-cp36-cp36m-win_amd64.whl", hash = "sha256:8d6865327ebbea5578f99b073538789df2123cf9009e99fe94efc4d25a4b888b"},
+    {file = "Bottleneck-1.3.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:685812254238c2059810f8e25c8215b09795b974f5b1a89f0accda3d93cc8734"},
+    {file = "Bottleneck-1.3.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5977f1fd02f01035176a99c01b3fb0eefdaff002c30a4710f7279215b0a317f5"},
+    {file = "Bottleneck-1.3.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e26c655736701365d66c64056fc272952d0e2a52718c637254d7dd9a7efa97a8"},
+    {file = "Bottleneck-1.3.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d982e1e3f72cc7ca4f558e9ef7db7a97ce68a915b1db8249fe088b3e78974b21"},
+    {file = "Bottleneck-1.3.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b5ec31e0b52cbfd716255695ec5fe87662a5961d2b8b49936f3608e36a04d926"},
+    {file = "Bottleneck-1.3.7-cp37-cp37m-win32.whl", hash = "sha256:f2c8b631552908b11905cf87b4a90dd4af332b0726dd9b49d26d6a0fbb38e6d4"},
+    {file = "Bottleneck-1.3.7-cp37-cp37m-win_amd64.whl", hash = "sha256:1045f9b199bba2675bd7642c25dec5daa21a03a5f0444eb863f2790af52b00b0"},
+    {file = "Bottleneck-1.3.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5af0c679da9dc41d6a3c436785c664fff41b4c1178d46afaa630620ab31e970f"},
+    {file = "Bottleneck-1.3.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c65d0a9498b2ccda236b28b1b36bc35402e81ebc4575b6cf44033b7e4460f067"},
+    {file = "Bottleneck-1.3.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:752f4c3fc5b7cc49814d41e9ecf6f228f33ea407bdb8c889da53716b5628abc7"},
+    {file = "Bottleneck-1.3.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:54fc579445688c5309a0af7634db3be4e17659c6b664f9332ec404738e847894"},
+    {file = "Bottleneck-1.3.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:175ae3d92142769a5acd169ac2d7df22107b72f6d4c932ff56f5afcef39d5877"},
+    {file = "Bottleneck-1.3.7-cp38-cp38-win32.whl", hash = "sha256:64ef9ad7187282745205b735e8c33307ec14c7be39f9971bc3f375104355cfb9"},
+    {file = "Bottleneck-1.3.7-cp38-cp38-win_amd64.whl", hash = "sha256:fa80c318b5164e39e4f2d5abf95f5ff42744e3d8535a4c85ede94ccc5fca8f9b"},
+    {file = "Bottleneck-1.3.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:01e61a512d645193cf4cf4fdacf98d3140c26ace0fcf4c4ed8fdfa366c57e0d1"},
+    {file = "Bottleneck-1.3.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:699fb76ef50cf85be8f8d644b533488de3cec4c6ddf00fd770f73cc5caac9938"},
+    {file = "Bottleneck-1.3.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6311ee47641ed5fbc543d2e49cbfa90bd9ece208a0c1bdc2c2b14b9132982b2a"},
+    {file = "Bottleneck-1.3.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a1e50fb506693186a4b8f85ac79df1a5af1ab1f774bf20004280e0658a731a89"},
+    {file = "Bottleneck-1.3.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4d2ae3e1ac0626107c6916783befc39473900bb22a9b275e21550c99abe8283c"},
+    {file = "Bottleneck-1.3.7-cp39-cp39-win32.whl", hash = "sha256:68d0f9d32d45f62028ab27d2b51d1a2af72a5ca6a7c3b1f86e9115fedb266300"},
+    {file = "Bottleneck-1.3.7-cp39-cp39-win_amd64.whl", hash = "sha256:83d71c49dd9d6b99def958b6ccba3c8b5aac7b90849a5a9fe935648436dd46b9"},
+    {file = "Bottleneck-1.3.7.tar.gz", hash = "sha256:e1467e373ad469da340ed0ff283214d6531cc08bfdca2083361a3aa6470681f8"},
+]
+
+[package.dependencies]
+numpy = "*"
+
+[package.extras]
+doc = ["gitpython", "numpydoc", "sphinx"]
+
+[[package]]
+name = "bs4"
+version = "0.0.1"
+description = "Dummy package for Beautiful Soup"
+optional = false
+python-versions = "*"
+files = [
+    {file = "bs4-0.0.1.tar.gz", hash = "sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a"},
+]
+
+[package.dependencies]
+beautifulsoup4 = "*"
+
+[[package]]
+name = "camelot-py"
+version = "0.11.0"
+description = "PDF Table Extraction for Humans."
+optional = false
+python-versions = "*"
+files = [
+    {file = "camelot-py-0.11.0.tar.gz", hash = "sha256:97a7d906d685e4059a4a549a63ae3a51f0ab72a3c826557f8443c65a1181dfe6"},
+    {file = "camelot_py-0.11.0-py3-none-any.whl", hash = "sha256:96d0f0386c8993f8f6b0aaaddf5f14a4a6ec6e9d1e07b6128d1c3abfa9156683"},
+]
+
+[package.dependencies]
+chardet = ">=3.0.4"
+click = ">=6.7"
+numpy = ">=1.13.3"
+openpyxl = ">=2.5.8"
+pandas = ">=0.23.4"
+"pdfminer.six" = ">=20200726"
+pypdf = ">=3.0.0"
+tabulate = ">=0.8.9"
+
+[package.extras]
+all = ["ghostscript (>=0.7)", "matplotlib (>=2.2.3)", "opencv-python (>=3.4.2.17)", "pdftopng (>=0.2.3)"]
+base = ["ghostscript (>=0.7)", "opencv-python (>=3.4.2.17)", "pdftopng (>=0.2.3)"]
+cv = ["ghostscript (>=0.7)", "opencv-python (>=3.4.2.17)", "pdftopng (>=0.2.3)"]
+dev = ["Sphinx (>=3.1.2)", "codecov (>=2.0.15)", "ghostscript (>=0.7)", "matplotlib (>=2.2.3)", "opencv-python (>=3.4.2.17)", "pdftopng (>=0.2.3)", "pytest (>=5.4.3)", "pytest-cov (>=2.10.0)", "pytest-mpl (>=0.11)", "pytest-runner (>=5.2)", "sphinx-autobuild (>=2021.3.14)"]
+plot = ["matplotlib (>=2.2.3)"]
+
+[[package]]
+name = "certifi"
+version = "2023.11.17"
+description = "Python package for providing Mozilla's CA Bundle."
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"},
+    {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"},
+]
+
+[[package]]
+name = "cffi"
+version = "1.16.0"
+description = "Foreign Function Interface for Python calling C code."
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"},
+    {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"},
+    {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"},
+    {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"},
+    {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"},
+    {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"},
+    {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"},
+    {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"},
+    {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"},
+    {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"},
+    {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"},
+    {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"},
+    {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"},
+    {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"},
+    {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"},
+    {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"},
+    {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"},
+    {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"},
+    {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"},
+    {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"},
+    {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"},
+    {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"},
+    {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"},
+    {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"},
+    {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"},
+    {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"},
+    {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"},
+    {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"},
+    {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"},
+    {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"},
+    {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"},
+    {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"},
+    {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"},
+    {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"},
+    {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"},
+    {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"},
+    {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"},
+    {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"},
+    {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"},
+    {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"},
+    {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"},
+    {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"},
+    {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"},
+    {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"},
+    {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"},
+    {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"},
+    {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"},
+    {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"},
+    {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"},
+    {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"},
+    {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"},
+    {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"},
+]
+
+[package.dependencies]
+pycparser = "*"
+
+[[package]]
+name = "cfgv"
+version = "3.4.0"
+description = "Validate configuration and produce human readable error messages."
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
+    {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
+]
+
+[[package]]
+name = "chardet"
+version = "5.2.0"
+description = "Universal encoding detector for Python 3"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"},
+    {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"},
+]
+
+[[package]]
+name = "charset-normalizer"
+version = "3.3.2"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+optional = false
+python-versions = ">=3.7.0"
+files = [
+    {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
+    {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
+    {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
+    {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
+    {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
+    {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
+    {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
+    {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
+    {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
+    {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
+    {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
+    {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
+    {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
+    {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
+    {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
+    {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
+    {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
+    {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
+    {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
+    {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
+]
+
+[[package]]
+name = "click"
+version = "8.1.7"
+description = "Composable command line interface toolkit"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
+    {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "cloudpickle"
+version = "3.0.0"
+description = "Pickler class to extend the standard pickle.Pickler functionality"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "cloudpickle-3.0.0-py3-none-any.whl", hash = "sha256:246ee7d0c295602a036e86369c77fecda4ab17b506496730f2f576d9016fd9c7"},
+    {file = "cloudpickle-3.0.0.tar.gz", hash = "sha256:996d9a482c6fb4f33c1a35335cf8afd065d2a56e973270364840712d9131a882"},
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+    {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+    {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "comm"
+version = "0.2.0"
+description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc."
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "comm-0.2.0-py3-none-any.whl", hash = "sha256:2da8d9ebb8dd7bfc247adaff99f24dce705638a8042b85cb995066793e391001"},
+    {file = "comm-0.2.0.tar.gz", hash = "sha256:a517ea2ca28931c7007a7a99c562a0fa5883cfb48963140cf642c41c948498be"},
+]
+
+[package.dependencies]
+traitlets = ">=4"
+
+[package.extras]
+test = ["pytest"]
+
+[[package]]
+name = "contourpy"
+version = "1.2.0"
+description = "Python library for calculating contours of 2D quadrilateral grids"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "contourpy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8"},
+    {file = "contourpy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4"},
+    {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f"},
+    {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e"},
+    {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9"},
+    {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa"},
+    {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9"},
+    {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab"},
+    {file = "contourpy-1.2.0-cp310-cp310-win32.whl", hash = "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488"},
+    {file = "contourpy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41"},
+    {file = "contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727"},
+    {file = "contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd"},
+    {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a"},
+    {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063"},
+    {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e"},
+    {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686"},
+    {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286"},
+    {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95"},
+    {file = "contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6"},
+    {file = "contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de"},
+    {file = "contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0"},
+    {file = "contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4"},
+    {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779"},
+    {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316"},
+    {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399"},
+    {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0"},
+    {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0"},
+    {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431"},
+    {file = "contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f"},
+    {file = "contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9"},
+    {file = "contourpy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5fd1810973a375ca0e097dee059c407913ba35723b111df75671a1976efa04bc"},
+    {file = "contourpy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:999c71939aad2780f003979b25ac5b8f2df651dac7b38fb8ce6c46ba5abe6ae9"},
+    {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7caf9b241464c404613512d5594a6e2ff0cc9cb5615c9475cc1d9b514218ae8"},
+    {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:266270c6f6608340f6c9836a0fb9b367be61dde0c9a9a18d5ece97774105ff3e"},
+    {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbd50d0a0539ae2e96e537553aff6d02c10ed165ef40c65b0e27e744a0f10af8"},
+    {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11f8d2554e52f459918f7b8e6aa20ec2a3bce35ce95c1f0ef4ba36fbda306df5"},
+    {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ce96dd400486e80ac7d195b2d800b03e3e6a787e2a522bfb83755938465a819e"},
+    {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d3364b999c62f539cd403f8123ae426da946e142312a514162adb2addd8d808"},
+    {file = "contourpy-1.2.0-cp39-cp39-win32.whl", hash = "sha256:1c88dfb9e0c77612febebb6ac69d44a8d81e3dc60f993215425b62c1161353f4"},
+    {file = "contourpy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:78e6ad33cf2e2e80c5dfaaa0beec3d61face0fb650557100ee36db808bfa6843"},
+    {file = "contourpy-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be16975d94c320432657ad2402f6760990cb640c161ae6da1363051805fa8108"},
+    {file = "contourpy-1.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b95a225d4948b26a28c08307a60ac00fb8671b14f2047fc5476613252a129776"},
+    {file = "contourpy-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d7e03c0f9a4f90dc18d4e77e9ef4ec7b7bbb437f7f675be8e530d65ae6ef956"},
+    {file = "contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a"},
+]
+
+[package.dependencies]
+numpy = ">=1.20,<2.0"
+
+[package.extras]
+bokeh = ["bokeh", "selenium"]
+docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"]
+mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.6.1)", "types-Pillow"]
+test = ["Pillow", "contourpy[test-no-images]", "matplotlib"]
+test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"]
+
+[[package]]
+name = "coverage"
+version = "7.3.2"
+description = "Code coverage measurement for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"},
+    {file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"},
+    {file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"},
+    {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"},
+    {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"},
+    {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"},
+    {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"},
+    {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"},
+    {file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"},
+    {file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"},
+    {file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"},
+    {file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"},
+    {file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"},
+    {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"},
+    {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"},
+    {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"},
+    {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"},
+    {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"},
+    {file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"},
+    {file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"},
+    {file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"},
+    {file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"},
+    {file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"},
+    {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"},
+    {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"},
+    {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"},
+    {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"},
+    {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"},
+    {file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"},
+    {file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"},
+    {file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"},
+    {file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"},
+    {file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"},
+    {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"},
+    {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"},
+    {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"},
+    {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"},
+    {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"},
+    {file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"},
+    {file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"},
+    {file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"},
+    {file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"},
+    {file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"},
+    {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"},
+    {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"},
+    {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"},
+    {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"},
+    {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"},
+    {file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"},
+    {file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"},
+    {file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"},
+    {file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"},
+]
+
+[package.dependencies]
+tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
+
+[package.extras]
+toml = ["tomli"]
+
+[[package]]
+name = "cryptography"
+version = "41.0.7"
+description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf"},
+    {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d"},
+    {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a"},
+    {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15"},
+    {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a"},
+    {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1"},
+    {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157"},
+    {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406"},
+    {file = "cryptography-41.0.7-cp37-abi3-win32.whl", hash = "sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d"},
+    {file = "cryptography-41.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2"},
+    {file = "cryptography-41.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960"},
+    {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003"},
+    {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7"},
+    {file = "cryptography-41.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec"},
+    {file = "cryptography-41.0.7-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be"},
+    {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a"},
+    {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c"},
+    {file = "cryptography-41.0.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a"},
+    {file = "cryptography-41.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39"},
+    {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a"},
+    {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248"},
+    {file = "cryptography-41.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309"},
+    {file = "cryptography-41.0.7.tar.gz", hash = "sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc"},
+]
+
+[package.dependencies]
+cffi = ">=1.12"
+
+[package.extras]
+docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"]
+docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"]
+nox = ["nox"]
+pep8test = ["black", "check-sdist", "mypy", "ruff"]
+sdist = ["build"]
+ssh = ["bcrypt (>=3.1.5)"]
+test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]
+test-randomorder = ["pytest-randomly"]
+
+[[package]]
+name = "cycler"
+version = "0.12.1"
+description = "Composable style cycles"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"},
+    {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"},
+]
+
+[package.extras]
+docs = ["ipython", "matplotlib", "numpydoc", "sphinx"]
+tests = ["pytest", "pytest-cov", "pytest-xdist"]
+
+[[package]]
+name = "datalad"
+version = "0.19.3"
+description = "data distribution geared toward scientific datasets"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "datalad-0.19.3-py3-none-any.whl", hash = "sha256:75ee17d571f17cef8a75dad996e558188f583f3c3e017e6a6467d471a64d9ab0"},
+    {file = "datalad-0.19.3.tar.gz", hash = "sha256:1002181d50fc8d8f7f434ec39b6daa70c1b7786d275c52a56aa04af26ca74e05"},
+]
+
+[package.dependencies]
+annexremote = "*"
+boto = "*"
+chardet = ">=3.0.4"
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+distro = {version = "*", markers = "python_version >= \"3.8\""}
+fasteners = ">=0.14"
+humanize = "*"
+importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""}
+iso8601 = "*"
+keyring = ">=20.0,<23.9.0 || >23.9.0"
+"keyrings.alt" = "*"
+looseversion = "*"
+msgpack = "*"
+packaging = "*"
+patool = ">=1.7"
+platformdirs = "*"
+python-gitlab = "*"
+requests = ">=1.2"
+tqdm = ">=4.32.0"
+typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+core = ["annexremote", "chardet (>=3.0.4)", "colorama", "distro", "fasteners (>=0.14)", "humanize", "importlib-metadata (>=3.6)", "importlib-resources (>=3.0)", "iso8601", "looseversion", "packaging", "patool (>=1.7)", "platformdirs", "tqdm (>=4.32.0)", "typing-extensions (>=4.0.0)"]
+devel = ["BeautifulSoup4", "annexremote", "argcomplete (>=1.12.3)", "asv", "boto", "chardet (>=3.0.4)", "colorama", "coverage", "distro", "duecredit", "fasteners (>=0.14)", "gprof2dot", "httpretty (>=0.9.4)", "humanize", "importlib-metadata (>=3.6)", "importlib-resources (>=3.0)", "iso8601", "keyring (>=20.0,!=23.9.0)", "keyrings.alt", "looseversion", "msgpack", "mypy", "packaging", "patool (>=1.7)", "platformdirs", "psutil", "pypandoc", "pyperclip", "pytest", "pytest-cov", "pytest-fail-slow (>=0.2,<1.0)", "pytest-xdist", "python-dateutil", "python-gitlab", "requests (>=1.2)", "requests-ftp", "scriv", "sphinx (>=4.3.0)", "sphinx-autodoc-typehints", "sphinx-rtd-theme (>=0.5.1)", "tqdm (>=4.32.0)", "types-python-dateutil", "types-requests", "typing-extensions (>=4.0.0)", "vcrpy"]
+devel-docs = ["pypandoc", "sphinx (>=4.3.0)", "sphinx-autodoc-typehints", "sphinx-rtd-theme (>=0.5.1)"]
+devel-utils = ["asv", "coverage", "gprof2dot", "psutil", "pytest-xdist", "scriv"]
+downloaders = ["boto", "keyring (>=20.0,!=23.9.0)", "keyrings.alt", "msgpack", "requests (>=1.2)"]
+downloaders-extra = ["requests-ftp"]
+duecredit = ["duecredit"]
+full = ["BeautifulSoup4", "annexremote", "argcomplete (>=1.12.3)", "boto", "chardet (>=3.0.4)", "colorama", "distro", "duecredit", "fasteners (>=0.14)", "httpretty (>=0.9.4)", "humanize", "importlib-metadata (>=3.6)", "importlib-resources (>=3.0)", "iso8601", "keyring (>=20.0,!=23.9.0)", "keyrings.alt", "looseversion", "msgpack", "mypy", "packaging", "patool (>=1.7)", "platformdirs", "pyperclip", "pytest", "pytest-cov", "pytest-fail-slow (>=0.2,<1.0)", "python-dateutil", "python-gitlab", "requests (>=1.2)", "requests-ftp", "tqdm (>=4.32.0)", "types-python-dateutil", "types-requests", "typing-extensions (>=4.0.0)", "vcrpy"]
+misc = ["argcomplete (>=1.12.3)", "pyperclip", "python-dateutil"]
+publish = ["python-gitlab"]
+tests = ["BeautifulSoup4", "httpretty (>=0.9.4)", "mypy", "pytest", "pytest-cov", "pytest-fail-slow (>=0.2,<1.0)", "types-python-dateutil", "types-requests", "vcrpy"]
+
+[[package]]
+name = "debugpy"
+version = "1.8.0"
+description = "An implementation of the Debug Adapter Protocol for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "debugpy-1.8.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:7fb95ca78f7ac43393cd0e0f2b6deda438ec7c5e47fa5d38553340897d2fbdfb"},
+    {file = "debugpy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef9ab7df0b9a42ed9c878afd3eaaff471fce3fa73df96022e1f5c9f8f8c87ada"},
+    {file = "debugpy-1.8.0-cp310-cp310-win32.whl", hash = "sha256:a8b7a2fd27cd9f3553ac112f356ad4ca93338feadd8910277aff71ab24d8775f"},
+    {file = "debugpy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5d9de202f5d42e62f932507ee8b21e30d49aae7e46d5b1dd5c908db1d7068637"},
+    {file = "debugpy-1.8.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:ef54404365fae8d45cf450d0544ee40cefbcb9cb85ea7afe89a963c27028261e"},
+    {file = "debugpy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60009b132c91951354f54363f8ebdf7457aeb150e84abba5ae251b8e9f29a8a6"},
+    {file = "debugpy-1.8.0-cp311-cp311-win32.whl", hash = "sha256:8cd0197141eb9e8a4566794550cfdcdb8b3db0818bdf8c49a8e8f8053e56e38b"},
+    {file = "debugpy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:a64093656c4c64dc6a438e11d59369875d200bd5abb8f9b26c1f5f723622e153"},
+    {file = "debugpy-1.8.0-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:b05a6b503ed520ad58c8dc682749113d2fd9f41ffd45daec16e558ca884008cd"},
+    {file = "debugpy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c6fb41c98ec51dd010d7ed650accfd07a87fe5e93eca9d5f584d0578f28f35f"},
+    {file = "debugpy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:46ab6780159eeabb43c1495d9c84cf85d62975e48b6ec21ee10c95767c0590aa"},
+    {file = "debugpy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:bdc5ef99d14b9c0fcb35351b4fbfc06ac0ee576aeab6b2511702e5a648a2e595"},
+    {file = "debugpy-1.8.0-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:61eab4a4c8b6125d41a34bad4e5fe3d2cc145caecd63c3fe953be4cc53e65bf8"},
+    {file = "debugpy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:125b9a637e013f9faac0a3d6a82bd17c8b5d2c875fb6b7e2772c5aba6d082332"},
+    {file = "debugpy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:57161629133113c97b387382045649a2b985a348f0c9366e22217c87b68b73c6"},
+    {file = "debugpy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:e3412f9faa9ade82aa64a50b602544efcba848c91384e9f93497a458767e6926"},
+    {file = "debugpy-1.8.0-py2.py3-none-any.whl", hash = "sha256:9c9b0ac1ce2a42888199df1a1906e45e6f3c9555497643a85e0bf2406e3ffbc4"},
+    {file = "debugpy-1.8.0.zip", hash = "sha256:12af2c55b419521e33d5fb21bd022df0b5eb267c3e178f1d374a63a2a6bdccd0"},
+]
+
+[[package]]
+name = "decorator"
+version = "5.1.1"
+description = "Decorators for Humans"
+optional = false
+python-versions = ">=3.5"
+files = [
+    {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
+    {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"},
+]
+
+[[package]]
+name = "distlib"
+version = "0.3.7"
+description = "Distribution utilities"
+optional = false
+python-versions = "*"
+files = [
+    {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"},
+    {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"},
+]
+
+[[package]]
+name = "distro"
+version = "1.8.0"
+description = "Distro - an OS platform information API"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "distro-1.8.0-py3-none-any.whl", hash = "sha256:99522ca3e365cac527b44bde033f64c6945d90eb9f769703caaec52b09bbd3ff"},
+    {file = "distro-1.8.0.tar.gz", hash = "sha256:02e111d1dc6a50abb8eed6bf31c3e48ed8b0830d1ea2a1b78c61765c2513fdd8"},
+]
+
+[[package]]
+name = "docutils"
+version = "0.18.1"
+description = "Docutils -- Python Documentation Utilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+    {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"},
+    {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"},
+]
+
+[[package]]
+name = "doit"
+version = "0.36.0"
+description = "doit - Automation Tool"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "doit-0.36.0-py3-none-any.whl", hash = "sha256:ebc285f6666871b5300091c26eafdff3de968a6bd60ea35dd1e3fc6f2e32479a"},
+    {file = "doit-0.36.0.tar.gz", hash = "sha256:71d07ccc9514cb22fe59d98999577665eaab57e16f644d04336ae0b4bae234bc"},
+]
+
+[package.dependencies]
+cloudpickle = "*"
+importlib-metadata = ">=4.4"
+
+[package.extras]
+toml = ["tomli"]
+
+[[package]]
+name = "et-xmlfile"
+version = "1.1.0"
+description = "An implementation of lxml.xmlfile for the standard library"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "et_xmlfile-1.1.0-py3-none-any.whl", hash = "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada"},
+    {file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"},
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.2.0"
+description = "Backport of PEP 654 (exception groups)"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"},
+    {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"},
+]
+
+[package.extras]
+test = ["pytest (>=6)"]
+
+[[package]]
+name = "executing"
+version = "2.0.1"
+description = "Get the currently executing AST node of a frame, and other information"
+optional = false
+python-versions = ">=3.5"
+files = [
+    {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"},
+    {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"},
+]
+
+[package.extras]
+tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"]
+
+[[package]]
+name = "fasteners"
+version = "0.19"
+description = "A python package that provides useful locks"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "fasteners-0.19-py3-none-any.whl", hash = "sha256:758819cb5d94cdedf4e836988b74de396ceacb8e2794d21f82d131fd9ee77237"},
+    {file = "fasteners-0.19.tar.gz", hash = "sha256:b4f37c3ac52d8a445af3a66bce57b33b5e90b97c696b7b984f530cf8f0ded09c"},
+]
+
+[[package]]
+name = "fastjsonschema"
+version = "2.19.0"
+description = "Fastest Python implementation of JSON schema"
+optional = false
+python-versions = "*"
+files = [
+    {file = "fastjsonschema-2.19.0-py3-none-any.whl", hash = "sha256:b9fd1a2dd6971dbc7fee280a95bd199ae0dd9ce22beb91cc75e9c1c528a5170e"},
+    {file = "fastjsonschema-2.19.0.tar.gz", hash = "sha256:e25df6647e1bc4a26070b700897b07b542ec898dd4f1f6ea013e7f6a88417225"},
+]
+
+[package.extras]
+devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"]
+
+[[package]]
+name = "filelock"
+version = "3.13.1"
+description = "A platform independent file lock."
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"},
+    {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"},
+]
+
+[package.extras]
+docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"]
+testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"]
+typing = ["typing-extensions (>=4.8)"]
+
+[[package]]
+name = "fonttools"
+version = "4.46.0"
+description = "Tools to manipulate font files"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "fonttools-4.46.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d4e69e2c7f93b695d2e6f18f709d501d945f65c1d237dafaabdd23cd935a5276"},
+    {file = "fonttools-4.46.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:25852f0c63df0af022f698464a4a80f7d1d5bd974bcd22f995f6b4ad198e32dd"},
+    {file = "fonttools-4.46.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:adab73618d0a328b203a0e242b3eba60a2b5662d9cb2bd16ed9c52af8a7d86af"},
+    {file = "fonttools-4.46.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cf923a4a556ab4cc4c52f69a4a2db624cf5a2cf360394368b40c5152fe3321e"},
+    {file = "fonttools-4.46.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:87c214197712cc14fd2a4621efce2a9c501a77041232b789568149a8a3161517"},
+    {file = "fonttools-4.46.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:156ae342a1ed1fe38e180de471e98fbf5b2b6ae280fa3323138569c4ca215844"},
+    {file = "fonttools-4.46.0-cp310-cp310-win32.whl", hash = "sha256:c506e3d3a9e898caee4dc094f34b49c5566870d5a2d1ca2125f0a9f35ecc2205"},
+    {file = "fonttools-4.46.0-cp310-cp310-win_amd64.whl", hash = "sha256:f8bc3973ed58893c4107993e0a7ae34901cb572b5e798249cbef35d30801ffd4"},
+    {file = "fonttools-4.46.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:982f69855ac258260f51048d9e0c53c5f19881138cc7ca06deb38dc4b97404b6"},
+    {file = "fonttools-4.46.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c23c59d321d62588620f2255cf951270bf637d88070f38ed8b5e5558775b86c"},
+    {file = "fonttools-4.46.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0e94244ec24a940ecfbe5b31c975c8a575d5ed2d80f9a280ce3b21fa5dc9c34"},
+    {file = "fonttools-4.46.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a9f9cdd7ef63d1b8ac90db335762451452426b3207abd79f60da510cea62da5"},
+    {file = "fonttools-4.46.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ca9eceebe70035b057ce549e2054cad73e95cac3fe91a9d827253d1c14618204"},
+    {file = "fonttools-4.46.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8be6adfa4e15977075278dd0a0bae74dec59be7b969b5ceed93fb86af52aa5be"},
+    {file = "fonttools-4.46.0-cp311-cp311-win32.whl", hash = "sha256:7b5636f5706d49f13b6d610fe54ee662336cdf56b5a6f6683c0b803e23d826d2"},
+    {file = "fonttools-4.46.0-cp311-cp311-win_amd64.whl", hash = "sha256:49ea0983e55fd7586a809787cd4644a7ae471e53ab8ddc016f9093b400e32646"},
+    {file = "fonttools-4.46.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7b460720ce81773da1a3e7cc964c48e1e11942b280619582a897fa0117b56a62"},
+    {file = "fonttools-4.46.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8bee9f4fc8c99824a424ae45c789ee8c67cb84f8e747afa7f83b7d3cef439c3b"},
+    {file = "fonttools-4.46.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3d7b96aba96e05e8c911ce2dfc5acc6a178b8f44f6aa69371ab91aa587563da"},
+    {file = "fonttools-4.46.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e6aeb5c340416d11a3209d75c48d13e72deea9e1517837dd1522c1fd1f17c11"},
+    {file = "fonttools-4.46.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c779f8701deedf41908f287aeb775b8a6f59875ad1002b98ac6034ae4ddc1b7b"},
+    {file = "fonttools-4.46.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce199227ce7921eaafdd4f96536f16b232d6b580ce74ce337de544bf06cb2752"},
+    {file = "fonttools-4.46.0-cp312-cp312-win32.whl", hash = "sha256:1c9937c4dd1061afd22643389445fabda858af5e805860ec3082a4bc07c7a720"},
+    {file = "fonttools-4.46.0-cp312-cp312-win_amd64.whl", hash = "sha256:a9fa52ef8fd14d7eb3d813e1451e7ace3e1eebfa9b7237d3f81fee8f3de6a114"},
+    {file = "fonttools-4.46.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c94564b1f3b5dd87e73577610d85115b1936edcc596deaf84a31bbe70e17456b"},
+    {file = "fonttools-4.46.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4a50a1dfad7f7ba5ca3f99cc73bf5cdac67ceade8e4b355a877521f20ad1b63"},
+    {file = "fonttools-4.46.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89c2c520f9492844ecd6316d20c6c7a157b5c0cb73a1411b3db28ee304f30122"},
+    {file = "fonttools-4.46.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5b7905fd68eacb7cc56a13139da5c312c45baae6950dd00b02563c54508a041"},
+    {file = "fonttools-4.46.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8485cc468288e213f31afdaf1fdda3c79010f542559fbba936a54f4644df2570"},
+    {file = "fonttools-4.46.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:87c3299da7da55394fb324349db0ede38114a46aafd0e7dfcabfecd28cdd94c3"},
+    {file = "fonttools-4.46.0-cp38-cp38-win32.whl", hash = "sha256:f5f1423a504ccc329efb5aa79738de83d38c072be5308788dde6bd419969d7f5"},
+    {file = "fonttools-4.46.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d4a4ebcc76e30898ff3296ea786491c70e183f738319ae2629e0d44f17ece42"},
+    {file = "fonttools-4.46.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9a0e422ab79e5cb2b47913be6a4b5fd20c4c7ac34a24f3691a4e099e965e0b8"},
+    {file = "fonttools-4.46.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:13ac0cba2fc63fa4b232f2a7971f35f35c6eaf10bd1271fa96d4ce6253a8acfd"},
+    {file = "fonttools-4.46.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:795150d5edc595e1a2cfb3d65e8f4f3d027704fc2579f8990d381bef6b188eb6"},
+    {file = "fonttools-4.46.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d00fc63131dcac6b25f50a5a129758438317e54e3ce5587163f7058de4b0e933"},
+    {file = "fonttools-4.46.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3033b55f401a622de2630b3982234d97219d89b058607b87927eccb0f922313c"},
+    {file = "fonttools-4.46.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e26e7fb908ae4f622813e7cb32cd2db6c24e3122bb3b98f25e832a2fe0e7e228"},
+    {file = "fonttools-4.46.0-cp39-cp39-win32.whl", hash = "sha256:2d0eba685938c603f2f648dfc0aadbf8c6a4fe1c7ca608c2970a6ef39e00f254"},
+    {file = "fonttools-4.46.0-cp39-cp39-win_amd64.whl", hash = "sha256:5200b01f463d97cc2b7ff8a1e3584151f4413e98cb8419da5f17d1dbb84cc214"},
+    {file = "fonttools-4.46.0-py3-none-any.whl", hash = "sha256:5b627ed142398ea9202bd752c04311592558964d1a765fb2f78dc441a05633f4"},
+    {file = "fonttools-4.46.0.tar.gz", hash = "sha256:2ae45716c27a41807d58a9f3f59983bdc8c0a46cb259e4450ab7e196253a9853"},
+]
+
+[package.extras]
+all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"]
+graphite = ["lz4 (>=1.7.4.2)"]
+interpolatable = ["munkres", "scipy"]
+lxml = ["lxml (>=4.0,<5)"]
+pathops = ["skia-pathops (>=0.5.0)"]
+plot = ["matplotlib"]
+repacker = ["uharfbuzz (>=0.23.0)"]
+symfont = ["sympy"]
+type1 = ["xattr"]
+ufo = ["fs (>=2.2.0,<3)"]
+unicode = ["unicodedata2 (>=15.1.0)"]
+woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"]
+
+[[package]]
+name = "globalwarmingpotentials"
+version = "0.9.3"
+description = "Global warming potentials of greenhouse gases from various IPCC reports"
+optional = false
+python-versions = "*"
+files = [
+    {file = "globalwarmingpotentials-0.9.3-py2.py3-none-any.whl", hash = "sha256:e06839334b34933a3f6fd365aef74f9c7d2c385af9f0908c121f4bfbd85ce246"},
+    {file = "globalwarmingpotentials-0.9.3.tar.gz", hash = "sha256:e81eb717ff81d894e43fcdbee1de7a6f2d83e3e6b63789fada8fb24861a2952a"},
+]
+
+[[package]]
+name = "greenlet"
+version = "3.0.1"
+description = "Lightweight in-process concurrent programming"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "greenlet-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f89e21afe925fcfa655965ca8ea10f24773a1791400989ff32f467badfe4a064"},
+    {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28e89e232c7593d33cac35425b58950789962011cc274aa43ef8865f2e11f46d"},
+    {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8ba29306c5de7717b5761b9ea74f9c72b9e2b834e24aa984da99cbfc70157fd"},
+    {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19bbdf1cce0346ef7341705d71e2ecf6f41a35c311137f29b8a2dc2341374565"},
+    {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:599daf06ea59bfedbec564b1692b0166a0045f32b6f0933b0dd4df59a854caf2"},
+    {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b641161c302efbb860ae6b081f406839a8b7d5573f20a455539823802c655f63"},
+    {file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d57e20ba591727da0c230ab2c3f200ac9d6d333860d85348816e1dca4cc4792e"},
+    {file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5805e71e5b570d490938d55552f5a9e10f477c19400c38bf1d5190d760691846"},
+    {file = "greenlet-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:52e93b28db27ae7d208748f45d2db8a7b6a380e0d703f099c949d0f0d80b70e9"},
+    {file = "greenlet-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f7bfb769f7efa0eefcd039dd19d843a4fbfbac52f1878b1da2ed5793ec9b1a65"},
+    {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e6c7db42638dc45cf2e13c73be16bf83179f7859b07cfc139518941320be96"},
+    {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1757936efea16e3f03db20efd0cd50a1c86b06734f9f7338a90c4ba85ec2ad5a"},
+    {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19075157a10055759066854a973b3d1325d964d498a805bb68a1f9af4aaef8ec"},
+    {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9d21aaa84557d64209af04ff48e0ad5e28c5cca67ce43444e939579d085da72"},
+    {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2847e5d7beedb8d614186962c3d774d40d3374d580d2cbdab7f184580a39d234"},
+    {file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:97e7ac860d64e2dcba5c5944cfc8fa9ea185cd84061c623536154d5a89237884"},
+    {file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b2c02d2ad98116e914d4f3155ffc905fd0c025d901ead3f6ed07385e19122c94"},
+    {file = "greenlet-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:22f79120a24aeeae2b4471c711dcf4f8c736a2bb2fabad2a67ac9a55ea72523c"},
+    {file = "greenlet-3.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:100f78a29707ca1525ea47388cec8a049405147719f47ebf3895e7509c6446aa"},
+    {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60d5772e8195f4e9ebf74046a9121bbb90090f6550f81d8956a05387ba139353"},
+    {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:daa7197b43c707462f06d2c693ffdbb5991cbb8b80b5b984007de431493a319c"},
+    {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea6b8aa9e08eea388c5f7a276fabb1d4b6b9d6e4ceb12cc477c3d352001768a9"},
+    {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d11ebbd679e927593978aa44c10fc2092bc454b7d13fdc958d3e9d508aba7d0"},
+    {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dbd4c177afb8a8d9ba348d925b0b67246147af806f0b104af4d24f144d461cd5"},
+    {file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20107edf7c2c3644c67c12205dc60b1bb11d26b2610b276f97d666110d1b511d"},
+    {file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8bef097455dea90ffe855286926ae02d8faa335ed8e4067326257cb571fc1445"},
+    {file = "greenlet-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:b2d3337dcfaa99698aa2377c81c9ca72fcd89c07e7eb62ece3f23a3fe89b2ce4"},
+    {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80ac992f25d10aaebe1ee15df45ca0d7571d0f70b645c08ec68733fb7a020206"},
+    {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:337322096d92808f76ad26061a8f5fccb22b0809bea39212cd6c406f6a7060d2"},
+    {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9934adbd0f6e476f0ecff3c94626529f344f57b38c9a541f87098710b18af0a"},
+    {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc4d815b794fd8868c4d67602692c21bf5293a75e4b607bb92a11e821e2b859a"},
+    {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41bdeeb552d814bcd7fb52172b304898a35818107cc8778b5101423c9017b3de"},
+    {file = "greenlet-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6e6061bf1e9565c29002e3c601cf68569c450be7fc3f7336671af7ddb4657166"},
+    {file = "greenlet-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fa24255ae3c0ab67e613556375a4341af04a084bd58764731972bcbc8baeba36"},
+    {file = "greenlet-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:b489c36d1327868d207002391f662a1d163bdc8daf10ab2e5f6e41b9b96de3b1"},
+    {file = "greenlet-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f33f3258aae89da191c6ebaa3bc517c6c4cbc9b9f689e5d8452f7aedbb913fa8"},
+    {file = "greenlet-3.0.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d2905ce1df400360463c772b55d8e2518d0e488a87cdea13dd2c71dcb2a1fa16"},
+    {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a02d259510b3630f330c86557331a3b0e0c79dac3d166e449a39363beaae174"},
+    {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55d62807f1c5a1682075c62436702aaba941daa316e9161e4b6ccebbbf38bda3"},
+    {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3fcc780ae8edbb1d050d920ab44790201f027d59fdbd21362340a85c79066a74"},
+    {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eddd98afc726f8aee1948858aed9e6feeb1758889dfd869072d4465973f6bfd"},
+    {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eabe7090db68c981fca689299c2d116400b553f4b713266b130cfc9e2aa9c5a9"},
+    {file = "greenlet-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f2f6d303f3dee132b322a14cd8765287b8f86cdc10d2cb6a6fae234ea488888e"},
+    {file = "greenlet-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d923ff276f1c1f9680d32832f8d6c040fe9306cbfb5d161b0911e9634be9ef0a"},
+    {file = "greenlet-3.0.1-cp38-cp38-win32.whl", hash = "sha256:0b6f9f8ca7093fd4433472fd99b5650f8a26dcd8ba410e14094c1e44cd3ceddd"},
+    {file = "greenlet-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:990066bff27c4fcf3b69382b86f4c99b3652bab2a7e685d968cd4d0cfc6f67c6"},
+    {file = "greenlet-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ce85c43ae54845272f6f9cd8320d034d7a946e9773c693b27d620edec825e376"},
+    {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89ee2e967bd7ff85d84a2de09df10e021c9b38c7d91dead95b406ed6350c6997"},
+    {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87c8ceb0cf8a5a51b8008b643844b7f4a8264a2c13fcbcd8a8316161725383fe"},
+    {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6a8c9d4f8692917a3dc7eb25a6fb337bff86909febe2f793ec1928cd97bedfc"},
+    {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fbc5b8f3dfe24784cee8ce0be3da2d8a79e46a276593db6868382d9c50d97b1"},
+    {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85d2b77e7c9382f004b41d9c72c85537fac834fb141b0296942d52bf03fe4a3d"},
+    {file = "greenlet-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:696d8e7d82398e810f2b3622b24e87906763b6ebfd90e361e88eb85b0e554dc8"},
+    {file = "greenlet-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:329c5a2e5a0ee942f2992c5e3ff40be03e75f745f48847f118a3cfece7a28546"},
+    {file = "greenlet-3.0.1-cp39-cp39-win32.whl", hash = "sha256:cf868e08690cb89360eebc73ba4be7fb461cfbc6168dd88e2fbbe6f31812cd57"},
+    {file = "greenlet-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:ac4a39d1abae48184d420aa8e5e63efd1b75c8444dd95daa3e03f6c6310e9619"},
+    {file = "greenlet-3.0.1.tar.gz", hash = "sha256:816bd9488a94cba78d93e1abb58000e8266fa9cc2aa9ccdd6eb0696acb24005b"},
+]
+
+[package.extras]
+docs = ["Sphinx"]
+test = ["objgraph", "psutil"]
+
+[[package]]
+name = "h11"
+version = "0.14.0"
+description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
+    {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
+]
+
+[[package]]
+name = "h5netcdf"
+version = "1.3.0"
+description = "netCDF4 via h5py"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "h5netcdf-1.3.0-py3-none-any.whl", hash = "sha256:f2df69dcd3665dc9c4d43eb6529dedd113b2508090d12ac973573305a8406465"},
+    {file = "h5netcdf-1.3.0.tar.gz", hash = "sha256:a171c027daeb34b24c24a3b6304195b8eabbb6f10c748256ed3cfe19806383cf"},
+]
+
+[package.dependencies]
+h5py = "*"
+packaging = "*"
+
+[package.extras]
+test = ["netCDF4", "pytest"]
+
+[[package]]
+name = "h5py"
+version = "3.10.0"
+description = "Read and write HDF5 files from Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "h5py-3.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b963fb772964fc1d1563c57e4e2e874022ce11f75ddc6df1a626f42bd49ab99f"},
+    {file = "h5py-3.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:012ab448590e3c4f5a8dd0f3533255bc57f80629bf7c5054cf4c87b30085063c"},
+    {file = "h5py-3.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:781a24263c1270a62cd67be59f293e62b76acfcc207afa6384961762bb88ea03"},
+    {file = "h5py-3.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f42e6c30698b520f0295d70157c4e202a9e402406f50dc08f5a7bc416b24e52d"},
+    {file = "h5py-3.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:93dd840bd675787fc0b016f7a05fc6efe37312a08849d9dd4053fd0377b1357f"},
+    {file = "h5py-3.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2381e98af081b6df7f6db300cd88f88e740649d77736e4b53db522d8874bf2dc"},
+    {file = "h5py-3.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:667fe23ab33d5a8a6b77970b229e14ae3bb84e4ea3382cc08567a02e1499eedd"},
+    {file = "h5py-3.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90286b79abd085e4e65e07c1bd7ee65a0f15818ea107f44b175d2dfe1a4674b7"},
+    {file = "h5py-3.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c013d2e79c00f28ffd0cc24e68665ea03ae9069e167087b2adb5727d2736a52"},
+    {file = "h5py-3.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:92273ce69ae4983dadb898fd4d3bea5eb90820df953b401282ee69ad648df684"},
+    {file = "h5py-3.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c97d03f87f215e7759a354460fb4b0d0f27001450b18b23e556e7856a0b21c3"},
+    {file = "h5py-3.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86df4c2de68257b8539a18646ceccdcf2c1ce6b1768ada16c8dcfb489eafae20"},
+    {file = "h5py-3.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba9ab36be991119a3ff32d0c7cbe5faf9b8d2375b5278b2aea64effbeba66039"},
+    {file = "h5py-3.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:2c8e4fda19eb769e9a678592e67eaec3a2f069f7570c82d2da909c077aa94339"},
+    {file = "h5py-3.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:492305a074327e8d2513011fa9fffeb54ecb28a04ca4c4227d7e1e9616d35641"},
+    {file = "h5py-3.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9450464b458cca2c86252b624279115dcaa7260a40d3cb1594bf2b410a2bd1a3"},
+    {file = "h5py-3.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd6f6d1384a9f491732cee233b99cd4bfd6e838a8815cc86722f9d2ee64032af"},
+    {file = "h5py-3.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3074ec45d3dc6e178c6f96834cf8108bf4a60ccb5ab044e16909580352010a97"},
+    {file = "h5py-3.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:212bb997a91e6a895ce5e2f365ba764debeaef5d2dca5c6fb7098d66607adf99"},
+    {file = "h5py-3.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5dfc65ac21fa2f630323c92453cadbe8d4f504726ec42f6a56cf80c2f90d6c52"},
+    {file = "h5py-3.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d4682b94fd36ab217352be438abd44c8f357c5449b8995e63886b431d260f3d3"},
+    {file = "h5py-3.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aece0e2e1ed2aab076c41802e50a0c3e5ef8816d60ece39107d68717d4559824"},
+    {file = "h5py-3.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43a61b2c2ad65b1fabc28802d133eed34debcc2c8b420cb213d3d4ef4d3e2229"},
+    {file = "h5py-3.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:ae2f0201c950059676455daf92700eeb57dcf5caaf71b9e1328e6e6593601770"},
+    {file = "h5py-3.10.0.tar.gz", hash = "sha256:d93adc48ceeb33347eb24a634fb787efc7ae4644e6ea4ba733d099605045c049"},
+]
+
+[package.dependencies]
+numpy = ">=1.17.3"
+
+[[package]]
+name = "humanize"
+version = "4.9.0"
+description = "Python humanize utilities"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "humanize-4.9.0-py3-none-any.whl", hash = "sha256:ce284a76d5b1377fd8836733b983bfb0b76f1aa1c090de2566fcf008d7f6ab16"},
+    {file = "humanize-4.9.0.tar.gz", hash = "sha256:582a265c931c683a7e9b8ed9559089dea7edcf6cc95be39a3cbc2c5d5ac2bcfa"},
+]
+
+[package.extras]
+tests = ["freezegun", "pytest", "pytest-cov"]
+
+[[package]]
+name = "identify"
+version = "2.5.32"
+description = "File identification library for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "identify-2.5.32-py2.py3-none-any.whl", hash = "sha256:0b7656ef6cba81664b783352c73f8c24b39cf82f926f78f4550eda928e5e0545"},
+    {file = "identify-2.5.32.tar.gz", hash = "sha256:5d9979348ec1a21c768ae07e0a652924538e8bce67313a73cb0f681cf08ba407"},
+]
+
+[package.extras]
+license = ["ukkonen"]
+
+[[package]]
+name = "idna"
+version = "3.6"
+description = "Internationalized Domain Names in Applications (IDNA)"
+optional = false
+python-versions = ">=3.5"
+files = [
+    {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"},
+    {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
+]
+
+[[package]]
+name = "imagesize"
+version = "1.4.1"
+description = "Getting image size from png/jpeg/jpeg2000/gif file"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+    {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"},
+    {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
+]
+
+[[package]]
+name = "importlib-metadata"
+version = "7.0.0"
+description = "Read metadata from Python packages"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"},
+    {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"},
+]
+
+[package.dependencies]
+zipp = ">=0.5"
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"]
+perf = ["ipython"]
+testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"]
+
+[[package]]
+name = "importlib-resources"
+version = "6.1.1"
+description = "Read resources from Python packages"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "importlib_resources-6.1.1-py3-none-any.whl", hash = "sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6"},
+    {file = "importlib_resources-6.1.1.tar.gz", hash = "sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a"},
+]
+
+[package.dependencies]
+zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""}
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"]
+
+[[package]]
+name = "incremental"
+version = "22.10.0"
+description = "\"A small library that versions your Python projects.\""
+optional = false
+python-versions = "*"
+files = [
+    {file = "incremental-22.10.0-py2.py3-none-any.whl", hash = "sha256:b864a1f30885ee72c5ac2835a761b8fe8aa9c28b9395cacf27286602688d3e51"},
+    {file = "incremental-22.10.0.tar.gz", hash = "sha256:912feeb5e0f7e0188e6f42241d2f450002e11bbc0937c65865045854c24c0bd0"},
+]
+
+[package.extras]
+mypy = ["click (>=6.0)", "mypy (==0.812)", "twisted (>=16.4.0)"]
+scripts = ["click (>=6.0)", "twisted (>=16.4.0)"]
+
+[[package]]
+name = "iniconfig"
+version = "2.0.0"
+description = "brain-dead simple config-ini parsing"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
+    {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
+]
+
+[[package]]
+name = "ipykernel"
+version = "6.27.1"
+description = "IPython Kernel for Jupyter"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "ipykernel-6.27.1-py3-none-any.whl", hash = "sha256:dab88b47f112f9f7df62236511023c9bdeef67abc73af7c652e4ce4441601686"},
+    {file = "ipykernel-6.27.1.tar.gz", hash = "sha256:7d5d594b6690654b4d299edba5e872dc17bb7396a8d0609c97cb7b8a1c605de6"},
+]
+
+[package.dependencies]
+appnope = {version = "*", markers = "platform_system == \"Darwin\""}
+comm = ">=0.1.1"
+debugpy = ">=1.6.5"
+ipython = ">=7.23.1"
+jupyter-client = ">=6.1.12"
+jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0"
+matplotlib-inline = ">=0.1"
+nest-asyncio = "*"
+packaging = "*"
+psutil = "*"
+pyzmq = ">=20"
+tornado = ">=6.1"
+traitlets = ">=5.4.0"
+
+[package.extras]
+cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"]
+docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"]
+pyqt5 = ["pyqt5"]
+pyside6 = ["pyside6"]
+test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov", "pytest-timeout"]
+
+[[package]]
+name = "ipython"
+version = "8.18.1"
+description = "IPython: Productive Interactive Computing"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"},
+    {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+decorator = "*"
+exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
+jedi = ">=0.16"
+matplotlib-inline = "*"
+pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""}
+prompt-toolkit = ">=3.0.41,<3.1.0"
+pygments = ">=2.4.0"
+stack-data = "*"
+traitlets = ">=5"
+typing-extensions = {version = "*", markers = "python_version < \"3.10\""}
+
+[package.extras]
+all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"]
+black = ["black"]
+doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"]
+kernel = ["ipykernel"]
+nbconvert = ["nbconvert"]
+nbformat = ["nbformat"]
+notebook = ["ipywidgets", "notebook"]
+parallel = ["ipyparallel"]
+qtconsole = ["qtconsole"]
+test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"]
+test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"]
+
+[[package]]
+name = "iso8601"
+version = "2.1.0"
+description = "Simple module to parse ISO 8601 dates"
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+    {file = "iso8601-2.1.0-py3-none-any.whl", hash = "sha256:aac4145c4dcb66ad8b648a02830f5e2ff6c24af20f4f482689be402db2429242"},
+    {file = "iso8601-2.1.0.tar.gz", hash = "sha256:6b1d3829ee8921c4301998c909f7829fa9ed3cbdac0d3b16af2d743aed1ba8df"},
+]
+
+[[package]]
+name = "jaraco-classes"
+version = "3.3.0"
+description = "Utility functions for Python class constructs"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "jaraco.classes-3.3.0-py3-none-any.whl", hash = "sha256:10afa92b6743f25c0cf5f37c6bb6e18e2c5bb84a16527ccfc0040ea377e7aaeb"},
+    {file = "jaraco.classes-3.3.0.tar.gz", hash = "sha256:c063dd08e89217cee02c8d5e5ec560f2c8ce6cdc2fcdc2e68f7b2e5547ed3621"},
+]
+
+[package.dependencies]
+more-itertools = "*"
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
+
+[[package]]
+name = "jedi"
+version = "0.19.1"
+description = "An autocompletion tool for Python that can be used for text editors."
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"},
+    {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"},
+]
+
+[package.dependencies]
+parso = ">=0.8.3,<0.9.0"
+
+[package.extras]
+docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"]
+qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
+testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
+
+[[package]]
+name = "jeepney"
+version = "0.8.0"
+description = "Low-level, pure Python DBus protocol wrapper."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "jeepney-0.8.0-py3-none-any.whl", hash = "sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755"},
+    {file = "jeepney-0.8.0.tar.gz", hash = "sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806"},
+]
+
+[package.extras]
+test = ["async-timeout", "pytest", "pytest-asyncio (>=0.17)", "pytest-trio", "testpath", "trio"]
+trio = ["async_generator", "trio"]
+
+[[package]]
+name = "jinja2"
+version = "3.1.2"
+description = "A very fast and expressive template engine."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
+    {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
+[[package]]
+name = "jsonschema"
+version = "4.20.0"
+description = "An implementation of JSON Schema validation for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "jsonschema-4.20.0-py3-none-any.whl", hash = "sha256:ed6231f0429ecf966f5bc8dfef245998220549cbbcf140f913b7464c52c3b6b3"},
+    {file = "jsonschema-4.20.0.tar.gz", hash = "sha256:4f614fd46d8d61258610998997743ec5492a648b33cf478c1ddc23ed4598a5fa"},
+]
+
+[package.dependencies]
+attrs = ">=22.2.0"
+jsonschema-specifications = ">=2023.03.6"
+referencing = ">=0.28.4"
+rpds-py = ">=0.7.1"
+
+[package.extras]
+format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"]
+format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"]
+
+[[package]]
+name = "jsonschema-specifications"
+version = "2023.11.2"
+description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "jsonschema_specifications-2023.11.2-py3-none-any.whl", hash = "sha256:e74ba7c0a65e8cb49dc26837d6cfe576557084a8b423ed16a420984228104f93"},
+    {file = "jsonschema_specifications-2023.11.2.tar.gz", hash = "sha256:9472fc4fea474cd74bea4a2b190daeccb5a9e4db2ea80efcf7a1b582fc9a81b8"},
+]
+
+[package.dependencies]
+referencing = ">=0.31.0"
+
+[[package]]
+name = "jupyter-cache"
+version = "0.6.1"
+description = "A defined interface for working with a cache of jupyter notebooks."
+optional = false
+python-versions = "~=3.8"
+files = [
+    {file = "jupyter-cache-0.6.1.tar.gz", hash = "sha256:26f83901143edf4af2f3ff5a91e2d2ad298e46e2cee03c8071d37a23a63ccbfc"},
+    {file = "jupyter_cache-0.6.1-py3-none-any.whl", hash = "sha256:2fce7d4975805c77f75bdfc1bc2e82bc538b8e5b1af27f2f5e06d55b9f996a82"},
+]
+
+[package.dependencies]
+attrs = "*"
+click = "*"
+importlib-metadata = "*"
+nbclient = ">=0.2,<0.8"
+nbformat = "*"
+pyyaml = "*"
+sqlalchemy = ">=1.3.12,<3"
+tabulate = "*"
+
+[package.extras]
+cli = ["click-log"]
+code-style = ["pre-commit (>=2.12,<4.0)"]
+rtd = ["ipykernel", "jupytext", "myst-nb", "nbdime", "sphinx-book-theme", "sphinx-copybutton"]
+testing = ["coverage", "ipykernel", "jupytext", "matplotlib", "nbdime", "nbformat (>=5.1)", "numpy", "pandas", "pytest (>=6,<8)", "pytest-cov", "pytest-regressions", "sympy"]
+
+[[package]]
+name = "jupyter-client"
+version = "8.6.0"
+description = "Jupyter protocol implementation and client libraries"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "jupyter_client-8.6.0-py3-none-any.whl", hash = "sha256:909c474dbe62582ae62b758bca86d6518c85234bdee2d908c778db6d72f39d99"},
+    {file = "jupyter_client-8.6.0.tar.gz", hash = "sha256:0642244bb83b4764ae60d07e010e15f0e2d275ec4e918a8f7b80fbbef3ca60c7"},
+]
+
+[package.dependencies]
+importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""}
+jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0"
+python-dateutil = ">=2.8.2"
+pyzmq = ">=23.0"
+tornado = ">=6.2"
+traitlets = ">=5.3"
+
+[package.extras]
+docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"]
+test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"]
+
+[[package]]
+name = "jupyter-core"
+version = "5.5.0"
+description = "Jupyter core package. A base package on which Jupyter projects rely."
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "jupyter_core-5.5.0-py3-none-any.whl", hash = "sha256:e11e02cd8ae0a9de5c6c44abf5727df9f2581055afe00b22183f621ba3585805"},
+    {file = "jupyter_core-5.5.0.tar.gz", hash = "sha256:880b86053bf298a8724994f95e99b99130659022a4f7f45f563084b6223861d3"},
+]
+
+[package.dependencies]
+platformdirs = ">=2.5"
+pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""}
+traitlets = ">=5.3"
+
+[package.extras]
+docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"]
+test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"]
+
+[[package]]
+name = "jupytext"
+version = "1.16.0"
+description = "Jupyter notebooks as Markdown documents, Julia, Python or R scripts"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "jupytext-1.16.0-py3-none-any.whl", hash = "sha256:c2b951ac72871f39cd6cd242b56bc43219b7ed8169598bae5359811fb1f54d28"},
+    {file = "jupytext-1.16.0.tar.gz", hash = "sha256:94c7e67775e90e1792c39ab7fca4e0459bf7c35656123e8dc2e9e1b3e953baf8"},
+]
+
+[package.dependencies]
+markdown-it-py = ">=1.0.0"
+mdit-py-plugins = "*"
+nbformat = "*"
+packaging = "*"
+pyyaml = "*"
+toml = "*"
+
+[package.extras]
+dev = ["jupytext[test-cov,test-external]"]
+docs = ["myst-parser", "sphinx", "sphinx-copybutton", "sphinx-rtd-theme"]
+test = ["pytest", "pytest-randomly", "pytest-xdist"]
+test-cov = ["jupytext[test-integration]", "pytest-cov (>=2.6.1)"]
+test-external = ["autopep8", "black", "flake8", "gitpython", "isort", "jupyter-fs (<0.4.0)", "jupytext[test-integration]", "pre-commit", "sphinx-gallery (<0.8)"]
+test-functional = ["jupytext[test]"]
+test-integration = ["ipykernel", "jupyter-server (!=2.11)", "jupytext[test-functional]", "nbconvert"]
+test-ui = ["calysto-bash"]
+
+[[package]]
+name = "keyring"
+version = "24.3.0"
+description = "Store and access your passwords safely."
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "keyring-24.3.0-py3-none-any.whl", hash = "sha256:4446d35d636e6a10b8bce7caa66913dd9eca5fd222ca03a3d42c38608ac30836"},
+    {file = "keyring-24.3.0.tar.gz", hash = "sha256:e730ecffd309658a08ee82535a3b5ec4b4c8669a9be11efb66249d8e0aeb9a25"},
+]
+
+[package.dependencies]
+importlib-metadata = {version = ">=4.11.4", markers = "python_version < \"3.12\""}
+"jaraco.classes" = "*"
+jeepney = {version = ">=0.4.2", markers = "sys_platform == \"linux\""}
+pywin32-ctypes = {version = ">=0.2.0", markers = "sys_platform == \"win32\""}
+SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""}
+
+[package.extras]
+completion = ["shtab (>=1.1.0)"]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
+
+[[package]]
+name = "keyrings-alt"
+version = "5.0.0"
+description = "Alternate keyring implementations"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "keyrings.alt-5.0.0-py3-none-any.whl", hash = "sha256:4b3fd67bbcdd5aa137e1537cc47b694dda134e290740918750a6a73bcf665b87"},
+    {file = "keyrings.alt-5.0.0.tar.gz", hash = "sha256:9d446cb47bbcea90ffa2ecc3e8003acf41573fc201bf44b4bf13bd0e11484828"},
+]
+
+[package.dependencies]
+"jaraco.classes" = "*"
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["backports.unittest-mock", "gdata", "keyring (>=20)", "pycryptodome", "pycryptodomex", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "python-keyczar"]
+
+[[package]]
+name = "kiwisolver"
+version = "1.4.5"
+description = "A fast implementation of the Cassowary constraint solver"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"},
+    {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"},
+    {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"},
+    {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"},
+    {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"},
+    {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"},
+    {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"},
+    {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"},
+    {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"},
+    {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"},
+    {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"},
+    {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"},
+    {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"},
+    {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"},
+    {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"},
+    {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"},
+    {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"},
+    {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"},
+    {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"},
+    {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"},
+    {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"},
+    {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"},
+    {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"},
+    {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"},
+    {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"},
+    {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"},
+    {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"},
+    {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"},
+    {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"},
+    {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"},
+    {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"},
+    {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"},
+    {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"},
+    {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"},
+    {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"},
+]
+
+[[package]]
+name = "liccheck"
+version = "0.9.2"
+description = "Check python packages from requirement.txt and report issues"
+optional = false
+python-versions = ">=3.5"
+files = [
+    {file = "liccheck-0.9.2-py2.py3-none-any.whl", hash = "sha256:15cbedd042515945fe9d58b62e0a5af2f2a7795def216f163bb35b3016a16637"},
+    {file = "liccheck-0.9.2.tar.gz", hash = "sha256:bdc2190f8e95af3c8f9c19edb784ba7d41ecb2bf9189422eae6112bf84c08cd5"},
+]
+
+[package.dependencies]
+semantic-version = ">=2.7.0"
+toml = "*"
+
+[[package]]
+name = "loguru"
+version = "0.7.2"
+description = "Python logging made (stupidly) simple"
+optional = false
+python-versions = ">=3.5"
+files = [
+    {file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"},
+    {file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"},
+]
+
+[package.dependencies]
+colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""}
+win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""}
+
+[package.extras]
+dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.4.1)", "mypy (==v1.5.1)", "pre-commit (==3.4.0)", "pytest (==6.1.2)", "pytest (==7.4.0)", "pytest-cov (==2.12.1)", "pytest-cov (==4.1.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.0.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.3.0)", "tox (==3.27.1)", "tox (==4.11.0)"]
+
+[[package]]
+name = "looseversion"
+version = "1.3.0"
+description = "Version numbering for anarchists and software realists"
+optional = false
+python-versions = "*"
+files = [
+    {file = "looseversion-1.3.0-py2.py3-none-any.whl", hash = "sha256:781ef477b45946fc03dd4c84ea87734b21137ecda0e1e122bcb3c8d16d2a56e0"},
+    {file = "looseversion-1.3.0.tar.gz", hash = "sha256:ebde65f3f6bb9531a81016c6fef3eb95a61181adc47b7f949e9c0ea47911669e"},
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "2.2.0"
+description = "Python port of markdown-it. Markdown parsing, done right!"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"},
+    {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"},
+]
+
+[package.dependencies]
+mdurl = ">=0.1,<1.0"
+
+[package.extras]
+benchmarking = ["psutil", "pytest", "pytest-benchmark"]
+code-style = ["pre-commit (>=3.0,<4.0)"]
+compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"]
+linkify = ["linkify-it-py (>=1,<3)"]
+plugins = ["mdit-py-plugins"]
+profiling = ["gprof2dot"]
+rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
+testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
+
+[[package]]
+name = "markupsafe"
+version = "2.1.3"
+description = "Safely add untrusted strings to HTML/XML markup."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"},
+    {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
+    {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
+    {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"},
+    {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"},
+    {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"},
+    {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"},
+    {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"},
+    {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"},
+    {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"},
+    {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"},
+    {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"},
+    {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"},
+    {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"},
+    {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"},
+    {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"},
+    {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"},
+]
+
+[[package]]
+name = "matplotlib"
+version = "3.8.2"
+description = "Python plotting package"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "matplotlib-3.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:09796f89fb71a0c0e1e2f4bdaf63fb2cefc84446bb963ecdeb40dfee7dfa98c7"},
+    {file = "matplotlib-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9c6976748a25e8b9be51ea028df49b8e561eed7809146da7a47dbecebab367"},
+    {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b78e4f2cedf303869b782071b55fdde5987fda3038e9d09e58c91cc261b5ad18"},
+    {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e208f46cf6576a7624195aa047cb344a7f802e113bb1a06cfd4bee431de5e31"},
+    {file = "matplotlib-3.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:46a569130ff53798ea5f50afce7406e91fdc471ca1e0e26ba976a8c734c9427a"},
+    {file = "matplotlib-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:830f00640c965c5b7f6bc32f0d4ce0c36dfe0379f7dd65b07a00c801713ec40a"},
+    {file = "matplotlib-3.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d86593ccf546223eb75a39b44c32788e6f6440d13cfc4750c1c15d0fcb850b63"},
+    {file = "matplotlib-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a5430836811b7652991939012f43d2808a2db9b64ee240387e8c43e2e5578c8"},
+    {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9576723858a78751d5aacd2497b8aef29ffea6d1c95981505877f7ac28215c6"},
+    {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba9cbd8ac6cf422f3102622b20f8552d601bf8837e49a3afed188d560152788"},
+    {file = "matplotlib-3.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:03f9d160a29e0b65c0790bb07f4f45d6a181b1ac33eb1bb0dd225986450148f0"},
+    {file = "matplotlib-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:3773002da767f0a9323ba1a9b9b5d00d6257dbd2a93107233167cfb581f64717"},
+    {file = "matplotlib-3.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627"},
+    {file = "matplotlib-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4"},
+    {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d"},
+    {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331"},
+    {file = "matplotlib-3.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213"},
+    {file = "matplotlib-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630"},
+    {file = "matplotlib-3.8.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:deaed9ad4da0b1aea77fe0aa0cebb9ef611c70b3177be936a95e5d01fa05094f"},
+    {file = "matplotlib-3.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:172f4d0fbac3383d39164c6caafd3255ce6fa58f08fc392513a0b1d3b89c4f89"},
+    {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7d36c2209d9136cd8e02fab1c0ddc185ce79bc914c45054a9f514e44c787917"},
+    {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5864bdd7da445e4e5e011b199bb67168cdad10b501750367c496420f2ad00843"},
+    {file = "matplotlib-3.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ef8345b48e95cee45ff25192ed1f4857273117917a4dcd48e3905619bcd9c9b8"},
+    {file = "matplotlib-3.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:7c48d9e221b637c017232e3760ed30b4e8d5dfd081daf327e829bf2a72c731b4"},
+    {file = "matplotlib-3.8.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:aa11b3c6928a1e496c1a79917d51d4cd5d04f8a2e75f21df4949eeefdf697f4b"},
+    {file = "matplotlib-3.8.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1095fecf99eeb7384dabad4bf44b965f929a5f6079654b681193edf7169ec20"},
+    {file = "matplotlib-3.8.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:bddfb1db89bfaa855912261c805bd0e10218923cc262b9159a49c29a7a1c1afa"},
+    {file = "matplotlib-3.8.2.tar.gz", hash = "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1"},
+]
+
+[package.dependencies]
+contourpy = ">=1.0.1"
+cycler = ">=0.10"
+fonttools = ">=4.22.0"
+importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""}
+kiwisolver = ">=1.3.1"
+numpy = ">=1.21,<2"
+packaging = ">=20.0"
+pillow = ">=8"
+pyparsing = ">=2.3.1"
+python-dateutil = ">=2.7"
+
+[[package]]
+name = "matplotlib-inline"
+version = "0.1.6"
+description = "Inline Matplotlib backend for Jupyter"
+optional = false
+python-versions = ">=3.5"
+files = [
+    {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"},
+    {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"},
+]
+
+[package.dependencies]
+traitlets = "*"
+
+[[package]]
+name = "mdit-py-plugins"
+version = "0.3.5"
+description = "Collection of plugins for markdown-it-py"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "mdit-py-plugins-0.3.5.tar.gz", hash = "sha256:eee0adc7195e5827e17e02d2a258a2ba159944a0748f59c5099a4a27f78fcf6a"},
+    {file = "mdit_py_plugins-0.3.5-py3-none-any.whl", hash = "sha256:ca9a0714ea59a24b2b044a1831f48d817dd0c817e84339f20e7889f392d77c4e"},
+]
+
+[package.dependencies]
+markdown-it-py = ">=1.0.0,<3.0.0"
+
+[package.extras]
+code-style = ["pre-commit"]
+rtd = ["attrs", "myst-parser (>=0.16.1,<0.17.0)", "sphinx-book-theme (>=0.1.0,<0.2.0)"]
+testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+description = "Markdown URL utilities"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
+    {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
+]
+
+[[package]]
+name = "more-itertools"
+version = "10.1.0"
+description = "More routines for operating on iterables, beyond itertools"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "more-itertools-10.1.0.tar.gz", hash = "sha256:626c369fa0eb37bac0291bce8259b332fd59ac792fa5497b59837309cd5b114a"},
+    {file = "more_itertools-10.1.0-py3-none-any.whl", hash = "sha256:64e0735fcfdc6f3464ea133afe8ea4483b1c5fe3a3d69852e6503b43a0b222e6"},
+]
+
+[[package]]
+name = "msgpack"
+version = "1.0.7"
+description = "MessagePack serializer"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "msgpack-1.0.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04ad6069c86e531682f9e1e71b71c1c3937d6014a7c3e9edd2aa81ad58842862"},
+    {file = "msgpack-1.0.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cca1b62fe70d761a282496b96a5e51c44c213e410a964bdffe0928e611368329"},
+    {file = "msgpack-1.0.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e50ebce52f41370707f1e21a59514e3375e3edd6e1832f5e5235237db933c98b"},
+    {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b4f35de6a304b5533c238bee86b670b75b03d31b7797929caa7a624b5dda6"},
+    {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28efb066cde83c479dfe5a48141a53bc7e5f13f785b92ddde336c716663039ee"},
+    {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cb14ce54d9b857be9591ac364cb08dc2d6a5c4318c1182cb1d02274029d590d"},
+    {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b573a43ef7c368ba4ea06050a957c2a7550f729c31f11dd616d2ac4aba99888d"},
+    {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ccf9a39706b604d884d2cb1e27fe973bc55f2890c52f38df742bc1d79ab9f5e1"},
+    {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cb70766519500281815dfd7a87d3a178acf7ce95390544b8c90587d76b227681"},
+    {file = "msgpack-1.0.7-cp310-cp310-win32.whl", hash = "sha256:b610ff0f24e9f11c9ae653c67ff8cc03c075131401b3e5ef4b82570d1728f8a9"},
+    {file = "msgpack-1.0.7-cp310-cp310-win_amd64.whl", hash = "sha256:a40821a89dc373d6427e2b44b572efc36a2778d3f543299e2f24eb1a5de65415"},
+    {file = "msgpack-1.0.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:576eb384292b139821c41995523654ad82d1916da6a60cff129c715a6223ea84"},
+    {file = "msgpack-1.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:730076207cb816138cf1af7f7237b208340a2c5e749707457d70705715c93b93"},
+    {file = "msgpack-1.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:85765fdf4b27eb5086f05ac0491090fc76f4f2b28e09d9350c31aac25a5aaff8"},
+    {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3476fae43db72bd11f29a5147ae2f3cb22e2f1a91d575ef130d2bf49afd21c46"},
+    {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d4c80667de2e36970ebf74f42d1088cc9ee7ef5f4e8c35eee1b40eafd33ca5b"},
+    {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b0bf0effb196ed76b7ad883848143427a73c355ae8e569fa538365064188b8e"},
+    {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f9a7c509542db4eceed3dcf21ee5267ab565a83555c9b88a8109dcecc4709002"},
+    {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:84b0daf226913133f899ea9b30618722d45feffa67e4fe867b0b5ae83a34060c"},
+    {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ec79ff6159dffcc30853b2ad612ed572af86c92b5168aa3fc01a67b0fa40665e"},
+    {file = "msgpack-1.0.7-cp311-cp311-win32.whl", hash = "sha256:3e7bf4442b310ff154b7bb9d81eb2c016b7d597e364f97d72b1acc3817a0fdc1"},
+    {file = "msgpack-1.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:3f0c8c6dfa6605ab8ff0611995ee30d4f9fcff89966cf562733b4008a3d60d82"},
+    {file = "msgpack-1.0.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f0936e08e0003f66bfd97e74ee530427707297b0d0361247e9b4f59ab78ddc8b"},
+    {file = "msgpack-1.0.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98bbd754a422a0b123c66a4c341de0474cad4a5c10c164ceed6ea090f3563db4"},
+    {file = "msgpack-1.0.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b291f0ee7961a597cbbcc77709374087fa2a9afe7bdb6a40dbbd9b127e79afee"},
+    {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebbbba226f0a108a7366bf4b59bf0f30a12fd5e75100c630267d94d7f0ad20e5"},
+    {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e2d69948e4132813b8d1131f29f9101bc2c915f26089a6d632001a5c1349672"},
+    {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdf38ba2d393c7911ae989c3bbba510ebbcdf4ecbdbfec36272abe350c454075"},
+    {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:993584fc821c58d5993521bfdcd31a4adf025c7d745bbd4d12ccfecf695af5ba"},
+    {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:52700dc63a4676669b341ba33520f4d6e43d3ca58d422e22ba66d1736b0a6e4c"},
+    {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e45ae4927759289c30ccba8d9fdce62bb414977ba158286b5ddaf8df2cddb5c5"},
+    {file = "msgpack-1.0.7-cp312-cp312-win32.whl", hash = "sha256:27dcd6f46a21c18fa5e5deed92a43d4554e3df8d8ca5a47bf0615d6a5f39dbc9"},
+    {file = "msgpack-1.0.7-cp312-cp312-win_amd64.whl", hash = "sha256:7687e22a31e976a0e7fc99c2f4d11ca45eff652a81eb8c8085e9609298916dcf"},
+    {file = "msgpack-1.0.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5b6ccc0c85916998d788b295765ea0e9cb9aac7e4a8ed71d12e7d8ac31c23c95"},
+    {file = "msgpack-1.0.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:235a31ec7db685f5c82233bddf9858748b89b8119bf4538d514536c485c15fe0"},
+    {file = "msgpack-1.0.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cab3db8bab4b7e635c1c97270d7a4b2a90c070b33cbc00c99ef3f9be03d3e1f7"},
+    {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bfdd914e55e0d2c9e1526de210f6fe8ffe9705f2b1dfcc4aecc92a4cb4b533d"},
+    {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36e17c4592231a7dbd2ed09027823ab295d2791b3b1efb2aee874b10548b7524"},
+    {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38949d30b11ae5f95c3c91917ee7a6b239f5ec276f271f28638dec9156f82cfc"},
+    {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ff1d0899f104f3921d94579a5638847f783c9b04f2d5f229392ca77fba5b82fc"},
+    {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dc43f1ec66eb8440567186ae2f8c447d91e0372d793dfe8c222aec857b81a8cf"},
+    {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dd632777ff3beaaf629f1ab4396caf7ba0bdd075d948a69460d13d44357aca4c"},
+    {file = "msgpack-1.0.7-cp38-cp38-win32.whl", hash = "sha256:4e71bc4416de195d6e9b4ee93ad3f2f6b2ce11d042b4d7a7ee00bbe0358bd0c2"},
+    {file = "msgpack-1.0.7-cp38-cp38-win_amd64.whl", hash = "sha256:8f5b234f567cf76ee489502ceb7165c2a5cecec081db2b37e35332b537f8157c"},
+    {file = "msgpack-1.0.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfef2bb6ef068827bbd021017a107194956918ab43ce4d6dc945ffa13efbc25f"},
+    {file = "msgpack-1.0.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:484ae3240666ad34cfa31eea7b8c6cd2f1fdaae21d73ce2974211df099a95d81"},
+    {file = "msgpack-1.0.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3967e4ad1aa9da62fd53e346ed17d7b2e922cba5ab93bdd46febcac39be636fc"},
+    {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dd178c4c80706546702c59529ffc005681bd6dc2ea234c450661b205445a34d"},
+    {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6ffbc252eb0d229aeb2f9ad051200668fc3a9aaa8994e49f0cb2ffe2b7867e7"},
+    {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:822ea70dc4018c7e6223f13affd1c5c30c0f5c12ac1f96cd8e9949acddb48a61"},
+    {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:384d779f0d6f1b110eae74cb0659d9aa6ff35aaf547b3955abf2ab4c901c4819"},
+    {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f64e376cd20d3f030190e8c32e1c64582eba56ac6dc7d5b0b49a9d44021b52fd"},
+    {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ed82f5a7af3697b1c4786053736f24a0efd0a1b8a130d4c7bfee4b9ded0f08f"},
+    {file = "msgpack-1.0.7-cp39-cp39-win32.whl", hash = "sha256:f26a07a6e877c76a88e3cecac8531908d980d3d5067ff69213653649ec0f60ad"},
+    {file = "msgpack-1.0.7-cp39-cp39-win_amd64.whl", hash = "sha256:1dc93e8e4653bdb5910aed79f11e165c85732067614f180f70534f056da97db3"},
+    {file = "msgpack-1.0.7.tar.gz", hash = "sha256:572efc93db7a4d27e404501975ca6d2d9775705c2d922390d878fcf768d92c87"},
+]
+
+[[package]]
+name = "mypy"
+version = "1.7.1"
+description = "Optional static typing for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "mypy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:12cce78e329838d70a204293e7b29af9faa3ab14899aec397798a4b41be7f340"},
+    {file = "mypy-1.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1484b8fa2c10adf4474f016e09d7a159602f3239075c7bf9f1627f5acf40ad49"},
+    {file = "mypy-1.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31902408f4bf54108bbfb2e35369877c01c95adc6192958684473658c322c8a5"},
+    {file = "mypy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f2c2521a8e4d6d769e3234350ba7b65ff5d527137cdcde13ff4d99114b0c8e7d"},
+    {file = "mypy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:fcd2572dd4519e8a6642b733cd3a8cfc1ef94bafd0c1ceed9c94fe736cb65b6a"},
+    {file = "mypy-1.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b901927f16224d0d143b925ce9a4e6b3a758010673eeded9b748f250cf4e8f7"},
+    {file = "mypy-1.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2f7f6985d05a4e3ce8255396df363046c28bea790e40617654e91ed580ca7c51"},
+    {file = "mypy-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:944bdc21ebd620eafefc090cdf83158393ec2b1391578359776c00de00e8907a"},
+    {file = "mypy-1.7.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9c7ac372232c928fff0645d85f273a726970c014749b924ce5710d7d89763a28"},
+    {file = "mypy-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:f6efc9bd72258f89a3816e3a98c09d36f079c223aa345c659622f056b760ab42"},
+    {file = "mypy-1.7.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6dbdec441c60699288adf051f51a5d512b0d818526d1dcfff5a41f8cd8b4aaf1"},
+    {file = "mypy-1.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4fc3d14ee80cd22367caaaf6e014494415bf440980a3045bf5045b525680ac33"},
+    {file = "mypy-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c6e4464ed5f01dc44dc9821caf67b60a4e5c3b04278286a85c067010653a0eb"},
+    {file = "mypy-1.7.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:d9b338c19fa2412f76e17525c1b4f2c687a55b156320acb588df79f2e6fa9fea"},
+    {file = "mypy-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:204e0d6de5fd2317394a4eff62065614c4892d5a4d1a7ee55b765d7a3d9e3f82"},
+    {file = "mypy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:84860e06ba363d9c0eeabd45ac0fde4b903ad7aa4f93cd8b648385a888e23200"},
+    {file = "mypy-1.7.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8c5091ebd294f7628eb25ea554852a52058ac81472c921150e3a61cdd68f75a7"},
+    {file = "mypy-1.7.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40716d1f821b89838589e5b3106ebbc23636ffdef5abc31f7cd0266db936067e"},
+    {file = "mypy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cf3f0c5ac72139797953bd50bc6c95ac13075e62dbfcc923571180bebb662e9"},
+    {file = "mypy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:78e25b2fd6cbb55ddfb8058417df193f0129cad5f4ee75d1502248e588d9e0d7"},
+    {file = "mypy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75c4d2a6effd015786c87774e04331b6da863fc3fc4e8adfc3b40aa55ab516fe"},
+    {file = "mypy-1.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2643d145af5292ee956aa0a83c2ce1038a3bdb26e033dadeb2f7066fb0c9abce"},
+    {file = "mypy-1.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75aa828610b67462ffe3057d4d8a4112105ed211596b750b53cbfe182f44777a"},
+    {file = "mypy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ee5d62d28b854eb61889cde4e1dbc10fbaa5560cb39780c3995f6737f7e82120"},
+    {file = "mypy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:72cf32ce7dd3562373f78bd751f73c96cfb441de147cc2448a92c1a308bd0ca6"},
+    {file = "mypy-1.7.1-py3-none-any.whl", hash = "sha256:f7c5d642db47376a0cc130f0de6d055056e010debdaf0707cd2b0fc7e7ef30ea"},
+    {file = "mypy-1.7.1.tar.gz", hash = "sha256:fcb6d9afb1b6208b4c712af0dafdc650f518836065df0d4fb1d800f5d6773db2"},
+]
+
+[package.dependencies]
+mypy-extensions = ">=1.0.0"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+typing-extensions = ">=4.1.0"
+
+[package.extras]
+dmypy = ["psutil (>=4.0)"]
+install-types = ["pip"]
+mypyc = ["setuptools (>=50)"]
+reports = ["lxml"]
+
+[[package]]
+name = "mypy-extensions"
+version = "1.0.0"
+description = "Type system extensions for programs checked with the mypy type checker."
+optional = false
+python-versions = ">=3.5"
+files = [
+    {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
+    {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
+]
+
+[[package]]
+name = "myst-nb"
+version = "0.17.2"
+description = "A Jupyter Notebook Sphinx reader built on top of the MyST markdown parser."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "myst-nb-0.17.2.tar.gz", hash = "sha256:0f61386515fab07c73646adca97fff2f69f41e90d313a260217c5bbe419d858b"},
+    {file = "myst_nb-0.17.2-py3-none-any.whl", hash = "sha256:132ca4d0f5c308fdd4b6fdaba077712e28e119ccdafd04d6e41b51aac5483494"},
+]
+
+[package.dependencies]
+importlib_metadata = "*"
+ipykernel = "*"
+ipython = "*"
+jupyter-cache = ">=0.5,<0.7"
+myst-parser = ">=0.18.0,<0.19.0"
+nbclient = "*"
+nbformat = ">=5.0,<6.0"
+pyyaml = "*"
+sphinx = ">=4,<6"
+typing-extensions = "*"
+
+[package.extras]
+code-style = ["pre-commit"]
+rtd = ["alabaster", "altair", "bokeh", "coconut (>=1.4.3,<2.3.0)", "ipykernel (>=5.5,<6.0)", "ipywidgets", "jupytext (>=1.11.2,<1.12.0)", "matplotlib", "numpy", "pandas", "plotly", "sphinx-book-theme (>=0.3.0,<0.4.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0,<0.5.0)", "sphinxcontrib-bibtex", "sympy"]
+testing = ["beautifulsoup4", "coverage (>=6.4,<8.0)", "ipykernel (>=5.5,<6.0)", "ipython (!=8.1.0,<8.5)", "ipywidgets (>=8)", "jupytext (>=1.11.2,<1.12.0)", "matplotlib (>=3.5.3,<3.6)", "nbdime", "numpy", "pandas", "pytest (>=7.1,<8.0)", "pytest-cov (>=3,<5)", "pytest-param-files (>=0.3.3,<0.4.0)", "pytest-regressions", "sympy (>=1.10.1)"]
+
+[[package]]
+name = "myst-parser"
+version = "0.18.1"
+description = "An extended commonmark compliant parser, with bridges to docutils & sphinx."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "myst-parser-0.18.1.tar.gz", hash = "sha256:79317f4bb2c13053dd6e64f9da1ba1da6cd9c40c8a430c447a7b146a594c246d"},
+    {file = "myst_parser-0.18.1-py3-none-any.whl", hash = "sha256:61b275b85d9f58aa327f370913ae1bec26ebad372cc99f3ab85c8ec3ee8d9fb8"},
+]
+
+[package.dependencies]
+docutils = ">=0.15,<0.20"
+jinja2 = "*"
+markdown-it-py = ">=1.0.0,<3.0.0"
+mdit-py-plugins = ">=0.3.1,<0.4.0"
+pyyaml = "*"
+sphinx = ">=4,<6"
+typing-extensions = "*"
+
+[package.extras]
+code-style = ["pre-commit (>=2.12,<3.0)"]
+linkify = ["linkify-it-py (>=1.0,<2.0)"]
+rtd = ["ipython", "sphinx-book-theme", "sphinx-design", "sphinxcontrib.mermaid (>=0.7.1,<0.8.0)", "sphinxext-opengraph (>=0.6.3,<0.7.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"]
+testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx (<5.2)", "sphinx-pytest"]
+
+[[package]]
+name = "nbclient"
+version = "0.7.4"
+description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor."
+optional = false
+python-versions = ">=3.7.0"
+files = [
+    {file = "nbclient-0.7.4-py3-none-any.whl", hash = "sha256:c817c0768c5ff0d60e468e017613e6eae27b6fa31e43f905addd2d24df60c125"},
+    {file = "nbclient-0.7.4.tar.gz", hash = "sha256:d447f0e5a4cfe79d462459aec1b3dc5c2e9152597262be8ee27f7d4c02566a0d"},
+]
+
+[package.dependencies]
+jupyter-client = ">=6.1.12"
+jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0"
+nbformat = ">=5.1"
+traitlets = ">=5.3"
+
+[package.extras]
+dev = ["pre-commit"]
+docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling"]
+test = ["flaky", "ipykernel", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"]
+
+[[package]]
+name = "nbformat"
+version = "5.9.2"
+description = "The Jupyter Notebook format"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "nbformat-5.9.2-py3-none-any.whl", hash = "sha256:1c5172d786a41b82bcfd0c23f9e6b6f072e8fb49c39250219e4acfff1efe89e9"},
+    {file = "nbformat-5.9.2.tar.gz", hash = "sha256:5f98b5ba1997dff175e77e0c17d5c10a96eaed2cbd1de3533d1fc35d5e111192"},
+]
+
+[package.dependencies]
+fastjsonschema = "*"
+jsonschema = ">=2.6"
+jupyter-core = "*"
+traitlets = ">=5.1"
+
+[package.extras]
+docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"]
+test = ["pep440", "pre-commit", "pytest", "testpath"]
+
+[[package]]
+name = "nest-asyncio"
+version = "1.5.8"
+description = "Patch asyncio to allow nested event loops"
+optional = false
+python-versions = ">=3.5"
+files = [
+    {file = "nest_asyncio-1.5.8-py3-none-any.whl", hash = "sha256:accda7a339a70599cb08f9dd09a67e0c2ef8d8d6f4c07f96ab203f2ae254e48d"},
+    {file = "nest_asyncio-1.5.8.tar.gz", hash = "sha256:25aa2ca0d2a5b5531956b9e273b45cf664cae2b145101d73b86b199978d48fdb"},
+]
+
+[[package]]
+name = "nodeenv"
+version = "1.8.0"
+description = "Node.js virtual environment builder"
+optional = false
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
+files = [
+    {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"},
+    {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"},
+]
+
+[package.dependencies]
+setuptools = "*"
+
+[[package]]
+name = "numpy"
+version = "1.26.2"
+description = "Fundamental package for array computing in Python"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "numpy-1.26.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3703fc9258a4a122d17043e57b35e5ef1c5a5837c3db8be396c82e04c1cf9b0f"},
+    {file = "numpy-1.26.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cc392fdcbd21d4be6ae1bb4475a03ce3b025cd49a9be5345d76d7585aea69440"},
+    {file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36340109af8da8805d8851ef1d74761b3b88e81a9bd80b290bbfed61bd2b4f75"},
+    {file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcc008217145b3d77abd3e4d5ef586e3bdfba8fe17940769f8aa09b99e856c00"},
+    {file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3ced40d4e9e18242f70dd02d739e44698df3dcb010d31f495ff00a31ef6014fe"},
+    {file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b272d4cecc32c9e19911891446b72e986157e6a1809b7b56518b4f3755267523"},
+    {file = "numpy-1.26.2-cp310-cp310-win32.whl", hash = "sha256:22f8fc02fdbc829e7a8c578dd8d2e15a9074b630d4da29cda483337e300e3ee9"},
+    {file = "numpy-1.26.2-cp310-cp310-win_amd64.whl", hash = "sha256:26c9d33f8e8b846d5a65dd068c14e04018d05533b348d9eaeef6c1bd787f9919"},
+    {file = "numpy-1.26.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b96e7b9c624ef3ae2ae0e04fa9b460f6b9f17ad8b4bec6d7756510f1f6c0c841"},
+    {file = "numpy-1.26.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aa18428111fb9a591d7a9cc1b48150097ba6a7e8299fb56bdf574df650e7d1f1"},
+    {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06fa1ed84aa60ea6ef9f91ba57b5ed963c3729534e6e54055fc151fad0423f0a"},
+    {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96ca5482c3dbdd051bcd1fce8034603d6ebfc125a7bd59f55b40d8f5d246832b"},
+    {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:854ab91a2906ef29dc3925a064fcd365c7b4da743f84b123002f6139bcb3f8a7"},
+    {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f43740ab089277d403aa07567be138fc2a89d4d9892d113b76153e0e412409f8"},
+    {file = "numpy-1.26.2-cp311-cp311-win32.whl", hash = "sha256:a2bbc29fcb1771cd7b7425f98b05307776a6baf43035d3b80c4b0f29e9545186"},
+    {file = "numpy-1.26.2-cp311-cp311-win_amd64.whl", hash = "sha256:2b3fca8a5b00184828d12b073af4d0fc5fdd94b1632c2477526f6bd7842d700d"},
+    {file = "numpy-1.26.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a4cd6ed4a339c21f1d1b0fdf13426cb3b284555c27ac2f156dfdaaa7e16bfab0"},
+    {file = "numpy-1.26.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5d5244aabd6ed7f312268b9247be47343a654ebea52a60f002dc70c769048e75"},
+    {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a3cdb4d9c70e6b8c0814239ead47da00934666f668426fc6e94cce869e13fd7"},
+    {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa317b2325f7aa0a9471663e6093c210cb2ae9c0ad824732b307d2c51983d5b6"},
+    {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:174a8880739c16c925799c018f3f55b8130c1f7c8e75ab0a6fa9d41cab092fd6"},
+    {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f79b231bf5c16b1f39c7f4875e1ded36abee1591e98742b05d8a0fb55d8a3eec"},
+    {file = "numpy-1.26.2-cp312-cp312-win32.whl", hash = "sha256:4a06263321dfd3598cacb252f51e521a8cb4b6df471bb12a7ee5cbab20ea9167"},
+    {file = "numpy-1.26.2-cp312-cp312-win_amd64.whl", hash = "sha256:b04f5dc6b3efdaab541f7857351aac359e6ae3c126e2edb376929bd3b7f92d7e"},
+    {file = "numpy-1.26.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4eb8df4bf8d3d90d091e0146f6c28492b0be84da3e409ebef54349f71ed271ef"},
+    {file = "numpy-1.26.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1a13860fdcd95de7cf58bd6f8bc5a5ef81c0b0625eb2c9a783948847abbef2c2"},
+    {file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64308ebc366a8ed63fd0bf426b6a9468060962f1a4339ab1074c228fa6ade8e3"},
+    {file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baf8aab04a2c0e859da118f0b38617e5ee65d75b83795055fb66c0d5e9e9b818"},
+    {file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d73a3abcac238250091b11caef9ad12413dab01669511779bc9b29261dd50210"},
+    {file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b361d369fc7e5e1714cf827b731ca32bff8d411212fccd29ad98ad622449cc36"},
+    {file = "numpy-1.26.2-cp39-cp39-win32.whl", hash = "sha256:bd3f0091e845164a20bd5a326860c840fe2af79fa12e0469a12768a3ec578d80"},
+    {file = "numpy-1.26.2-cp39-cp39-win_amd64.whl", hash = "sha256:2beef57fb031dcc0dc8fa4fe297a742027b954949cabb52a2a376c144e5e6060"},
+    {file = "numpy-1.26.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1cc3d5029a30fb5f06704ad6b23b35e11309491c999838c31f124fee32107c79"},
+    {file = "numpy-1.26.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94cc3c222bb9fb5a12e334d0479b97bb2df446fbe622b470928f5284ffca3f8d"},
+    {file = "numpy-1.26.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe6b44fb8fcdf7eda4ef4461b97b3f63c466b27ab151bec2366db8b197387841"},
+    {file = "numpy-1.26.2.tar.gz", hash = "sha256:f65738447676ab5777f11e6bbbdb8ce11b785e105f690bc45966574816b6d3ea"},
+]
+
+[[package]]
+name = "opencv-python"
+version = "4.8.1.78"
+description = "Wrapper package for OpenCV python bindings."
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "opencv-python-4.8.1.78.tar.gz", hash = "sha256:cc7adbbcd1112877a39274106cb2752e04984bc01a031162952e97450d6117f6"},
+    {file = "opencv_python-4.8.1.78-cp37-abi3-macosx_10_16_x86_64.whl", hash = "sha256:91d5f6f5209dc2635d496f6b8ca6573ecdad051a09e6b5de4c399b8e673c60da"},
+    {file = "opencv_python-4.8.1.78-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:bc31f47e05447da8b3089faa0a07ffe80e114c91ce0b171e6424f9badbd1c5cd"},
+    {file = "opencv_python-4.8.1.78-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9814beca408d3a0eca1bae7e3e5be68b07c17ecceb392b94170881216e09b319"},
+    {file = "opencv_python-4.8.1.78-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4c406bdb41eb21ea51b4e90dfbc989c002786c3f601c236a99c59a54670a394"},
+    {file = "opencv_python-4.8.1.78-cp37-abi3-win32.whl", hash = "sha256:a7aac3900fbacf55b551e7b53626c3dad4c71ce85643645c43e91fcb19045e47"},
+    {file = "opencv_python-4.8.1.78-cp37-abi3-win_amd64.whl", hash = "sha256:b983197f97cfa6fcb74e1da1802c7497a6f94ed561aba6980f1f33123f904956"},
+]
+
+[package.dependencies]
+numpy = [
+    {version = ">=1.21.0", markers = "python_version == \"3.9\" and platform_system == \"Darwin\" and platform_machine == \"arm64\""},
+    {version = ">=1.23.5", markers = "python_version >= \"3.11\""},
+    {version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\" and python_version < \"3.11\""},
+    {version = ">=1.21.2", markers = "platform_system != \"Darwin\" and python_version >= \"3.10\" and python_version < \"3.11\""},
+    {version = ">=1.19.3", markers = "platform_system == \"Linux\" and platform_machine == \"aarch64\" and python_version >= \"3.8\" and python_version < \"3.10\" or python_version > \"3.9\" and python_version < \"3.10\" or python_version >= \"3.9\" and platform_system != \"Darwin\" and python_version < \"3.10\" or python_version >= \"3.9\" and platform_machine != \"arm64\" and python_version < \"3.10\""},
+]
+
+[[package]]
+name = "openpyxl"
+version = "3.1.2"
+description = "A Python library to read/write Excel 2010 xlsx/xlsm files"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "openpyxl-3.1.2-py2.py3-none-any.whl", hash = "sha256:f91456ead12ab3c6c2e9491cf33ba6d08357d802192379bb482f1033ade496f5"},
+    {file = "openpyxl-3.1.2.tar.gz", hash = "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184"},
+]
+
+[package.dependencies]
+et-xmlfile = "*"
+
+[[package]]
+name = "openscm-units"
+version = "0.5.2"
+description = "OpenSCM-Units is a repository for handling of units related to simple climate modelling."
+optional = false
+python-versions = "*"
+files = [
+    {file = "openscm-units-0.5.2.tar.gz", hash = "sha256:a9e199ee3356cb5ce4f95a11b13d5411cd172c108bb76267be052070947e9aef"},
+    {file = "openscm_units-0.5.2-py2.py3-none-any.whl", hash = "sha256:3acf2f4da43ddc2fbe2f7f5d3ee468c39b65f621ff252f311b32ae4781f405ed"},
+]
+
+[package.dependencies]
+globalwarmingpotentials = "*"
+pandas = "*"
+pint = "*"
+
+[package.extras]
+deploy = ["setuptools (>=38.6.0)", "twine (>=1.11.0)", "wheel (>=0.31.0)"]
+dev = ["bandit", "black", "black-nb", "codecov", "coverage", "dephell-changelogs", "flake8", "ipykernel", "isort", "mypy", "nbdime", "nbsphinx", "nbval", "notebook", "numpy", "pydocstyle", "pylint (>=2.4.4)", "pytest (>=4.0)", "pytest-cov", "seaborn", "setuptools (>=38.6.0)", "sphinx (>=1.4)", "sphinx-rtd-theme", "twine (>=1.11.0)", "wheel (>=0.31.0)"]
+docs = ["ipykernel", "nbsphinx", "sphinx (>=1.4)", "sphinx-rtd-theme"]
+notebooks = ["notebook", "seaborn"]
+tests = ["codecov", "coverage", "nbval", "pytest (>=4.0)", "pytest-cov"]
+
+[[package]]
+name = "outcome"
+version = "1.3.0.post0"
+description = "Capture the outcome of Python function calls."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"},
+    {file = "outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8"},
+]
+
+[package.dependencies]
+attrs = ">=19.2.0"
+
+[[package]]
+name = "packaging"
+version = "23.2"
+description = "Core utilities for Python packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
+    {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
+]
+
+[[package]]
+name = "pandas"
+version = "2.1.3"
+description = "Powerful data structures for data analysis, time series, and statistics"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "pandas-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:acf08a73b5022b479c1be155d4988b72f3020f308f7a87c527702c5f8966d34f"},
+    {file = "pandas-2.1.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3cc4469ff0cf9aa3a005870cb49ab8969942b7156e0a46cc3f5abd6b11051dfb"},
+    {file = "pandas-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35172bff95f598cc5866c047f43c7f4df2c893acd8e10e6653a4b792ed7f19bb"},
+    {file = "pandas-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59dfe0e65a2f3988e940224e2a70932edc964df79f3356e5f2997c7d63e758b4"},
+    {file = "pandas-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0296a66200dee556850d99b24c54c7dfa53a3264b1ca6f440e42bad424caea03"},
+    {file = "pandas-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:465571472267a2d6e00657900afadbe6097c8e1dc43746917db4dfc862e8863e"},
+    {file = "pandas-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:04d4c58e1f112a74689da707be31cf689db086949c71828ef5da86727cfe3f82"},
+    {file = "pandas-2.1.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7fa2ad4ff196768ae63a33f8062e6838efed3a319cf938fdf8b95e956c813042"},
+    {file = "pandas-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4441ac94a2a2613e3982e502ccec3bdedefe871e8cea54b8775992485c5660ef"},
+    {file = "pandas-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ded6ff28abbf0ea7689f251754d3789e1edb0c4d0d91028f0b980598418a58"},
+    {file = "pandas-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fca5680368a5139d4920ae3dc993eb5106d49f814ff24018b64d8850a52c6ed2"},
+    {file = "pandas-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:de21e12bf1511190fc1e9ebc067f14ca09fccfb189a813b38d63211d54832f5f"},
+    {file = "pandas-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a5d53c725832e5f1645e7674989f4c106e4b7249c1d57549023ed5462d73b140"},
+    {file = "pandas-2.1.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7cf4cf26042476e39394f1f86868d25b265ff787c9b2f0d367280f11afbdee6d"},
+    {file = "pandas-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72c84ec1b1d8e5efcbff5312abe92bfb9d5b558f11e0cf077f5496c4f4a3c99e"},
+    {file = "pandas-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f539e113739a3e0cc15176bf1231a553db0239bfa47a2c870283fd93ba4f683"},
+    {file = "pandas-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc77309da3b55732059e484a1efc0897f6149183c522390772d3561f9bf96c00"},
+    {file = "pandas-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:08637041279b8981a062899da0ef47828df52a1838204d2b3761fbd3e9fcb549"},
+    {file = "pandas-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b99c4e51ef2ed98f69099c72c75ec904dd610eb41a32847c4fcbc1a975f2d2b8"},
+    {file = "pandas-2.1.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f7ea8ae8004de0381a2376662c0505bb0a4f679f4c61fbfd122aa3d1b0e5f09d"},
+    {file = "pandas-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcd76d67ca2d48f56e2db45833cf9d58f548f97f61eecd3fdc74268417632b8a"},
+    {file = "pandas-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1329dbe93a880a3d7893149979caa82d6ba64a25e471682637f846d9dbc10dd2"},
+    {file = "pandas-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:321ecdb117bf0f16c339cc6d5c9a06063854f12d4d9bc422a84bb2ed3207380a"},
+    {file = "pandas-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:11a771450f36cebf2a4c9dbd3a19dfa8c46c4b905a3ea09dc8e556626060fe71"},
+    {file = "pandas-2.1.3.tar.gz", hash = "sha256:22929f84bca106921917eb73c1521317ddd0a4c71b395bcf767a106e3494209f"},
+]
+
+[package.dependencies]
+numpy = [
+    {version = ">=1.22.4,<2", markers = "python_version < \"3.11\""},
+    {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""},
+    {version = ">=1.26.0,<2", markers = "python_version >= \"3.12\""},
+]
+python-dateutil = ">=2.8.2"
+pytz = ">=2020.1"
+tzdata = ">=2022.1"
+
+[package.extras]
+all = ["PyQt5 (>=5.15.6)", "SQLAlchemy (>=1.4.36)", "beautifulsoup4 (>=4.11.1)", "bottleneck (>=1.3.4)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=0.8.1)", "fsspec (>=2022.05.0)", "gcsfs (>=2022.05.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.8.0)", "matplotlib (>=3.6.1)", "numba (>=0.55.2)", "numexpr (>=2.8.0)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pandas-gbq (>=0.17.5)", "psycopg2 (>=2.9.3)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.5)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "pyxlsb (>=1.0.9)", "qtpy (>=2.2.0)", "s3fs (>=2022.05.0)", "scipy (>=1.8.1)", "tables (>=3.7.0)", "tabulate (>=0.8.10)", "xarray (>=2022.03.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)", "zstandard (>=0.17.0)"]
+aws = ["s3fs (>=2022.05.0)"]
+clipboard = ["PyQt5 (>=5.15.6)", "qtpy (>=2.2.0)"]
+compression = ["zstandard (>=0.17.0)"]
+computation = ["scipy (>=1.8.1)", "xarray (>=2022.03.0)"]
+consortium-standard = ["dataframe-api-compat (>=0.1.7)"]
+excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pyxlsb (>=1.0.9)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)"]
+feather = ["pyarrow (>=7.0.0)"]
+fss = ["fsspec (>=2022.05.0)"]
+gcp = ["gcsfs (>=2022.05.0)", "pandas-gbq (>=0.17.5)"]
+hdf5 = ["tables (>=3.7.0)"]
+html = ["beautifulsoup4 (>=4.11.1)", "html5lib (>=1.1)", "lxml (>=4.8.0)"]
+mysql = ["SQLAlchemy (>=1.4.36)", "pymysql (>=1.0.2)"]
+output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.8.10)"]
+parquet = ["pyarrow (>=7.0.0)"]
+performance = ["bottleneck (>=1.3.4)", "numba (>=0.55.2)", "numexpr (>=2.8.0)"]
+plot = ["matplotlib (>=3.6.1)"]
+postgresql = ["SQLAlchemy (>=1.4.36)", "psycopg2 (>=2.9.3)"]
+spss = ["pyreadstat (>=1.1.5)"]
+sql-other = ["SQLAlchemy (>=1.4.36)"]
+test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"]
+xml = ["lxml (>=4.8.0)"]
+
+[[package]]
+name = "parso"
+version = "0.8.3"
+description = "A Python Parser"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"},
+    {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"},
+]
+
+[package.extras]
+qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
+testing = ["docopt", "pytest (<6.0.0)"]
+
+[[package]]
+name = "pathspec"
+version = "0.11.2"
+description = "Utility library for gitignore style pattern matching of file paths."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"},
+    {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
+]
+
+[[package]]
+name = "patool"
+version = "1.15.0"
+description = "portable archive file manager"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "patool-1.15.0-py2.py3-none-any.whl", hash = "sha256:b14fd047571f71220de5d220bac9974fa2f423cce3c42cf0a85f54f155c30f09"},
+    {file = "patool-1.15.0.tar.gz", hash = "sha256:d94814a1c92d111089001f6a67b058de29ae7033e172503af1acb452048c8a69"},
+]
+
+[[package]]
+name = "pdfminer-six"
+version = "20221105"
+description = "PDF parser and analyzer"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "pdfminer.six-20221105-py3-none-any.whl", hash = "sha256:1eaddd712d5b2732f8ac8486824533514f8ba12a0787b3d5fe1e686cd826532d"},
+    {file = "pdfminer.six-20221105.tar.gz", hash = "sha256:8448ab7b939d18b64820478ecac5394f482d7a79f5f7eaa7703c6c959c175e1d"},
+]
+
+[package.dependencies]
+charset-normalizer = ">=2.0.0"
+cryptography = ">=36.0.0"
+
+[package.extras]
+dev = ["black", "mypy (==0.931)", "nox", "pytest"]
+docs = ["sphinx", "sphinx-argparse"]
+image = ["Pillow"]
+
+[[package]]
+name = "pexpect"
+version = "4.9.0"
+description = "Pexpect allows easy control of interactive console applications."
+optional = false
+python-versions = "*"
+files = [
+    {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"},
+    {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"},
+]
+
+[package.dependencies]
+ptyprocess = ">=0.5"
+
+[[package]]
+name = "pillow"
+version = "10.1.0"
+description = "Python Imaging Library (Fork)"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "Pillow-10.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1ab05f3db77e98f93964697c8efc49c7954b08dd61cff526b7f2531a22410106"},
+    {file = "Pillow-10.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6932a7652464746fcb484f7fc3618e6503d2066d853f68a4bd97193a3996e273"},
+    {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f63b5a68daedc54c7c3464508d8c12075e56dcfbd42f8c1bf40169061ae666"},
+    {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0949b55eb607898e28eaccb525ab104b2d86542a85c74baf3a6dc24002edec2"},
+    {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ae88931f93214777c7a3aa0a8f92a683f83ecde27f65a45f95f22d289a69e593"},
+    {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b0eb01ca85b2361b09480784a7931fc648ed8b7836f01fb9241141b968feb1db"},
+    {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d27b5997bdd2eb9fb199982bb7eb6164db0426904020dc38c10203187ae2ff2f"},
+    {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7df5608bc38bd37ef585ae9c38c9cd46d7c81498f086915b0f97255ea60c2818"},
+    {file = "Pillow-10.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:41f67248d92a5e0a2076d3517d8d4b1e41a97e2df10eb8f93106c89107f38b57"},
+    {file = "Pillow-10.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1fb29c07478e6c06a46b867e43b0bcdb241b44cc52be9bc25ce5944eed4648e7"},
+    {file = "Pillow-10.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2cdc65a46e74514ce742c2013cd4a2d12e8553e3a2563c64879f7c7e4d28bce7"},
+    {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50d08cd0a2ecd2a8657bd3d82c71efd5a58edb04d9308185d66c3a5a5bed9610"},
+    {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:062a1610e3bc258bff2328ec43f34244fcec972ee0717200cb1425214fe5b839"},
+    {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:61f1a9d247317fa08a308daaa8ee7b3f760ab1809ca2da14ecc88ae4257d6172"},
+    {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a646e48de237d860c36e0db37ecaecaa3619e6f3e9d5319e527ccbc8151df061"},
+    {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:47e5bf85b80abc03be7455c95b6d6e4896a62f6541c1f2ce77a7d2bb832af262"},
+    {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a92386125e9ee90381c3369f57a2a50fa9e6aa8b1cf1d9c4b200d41a7dd8e992"},
+    {file = "Pillow-10.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0f7c276c05a9767e877a0b4c5050c8bee6a6d960d7f0c11ebda6b99746068c2a"},
+    {file = "Pillow-10.1.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:a89b8312d51715b510a4fe9fc13686283f376cfd5abca8cd1c65e4c76e21081b"},
+    {file = "Pillow-10.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d"},
+    {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d929a19f5469b3f4df33a3df2983db070ebb2088a1e145e18facbc28cae5b27"},
+    {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a92109192b360634a4489c0c756364c0c3a2992906752165ecb50544c251312"},
+    {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:0248f86b3ea061e67817c47ecbe82c23f9dd5d5226200eb9090b3873d3ca32de"},
+    {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9882a7451c680c12f232a422730f986a1fcd808da0fd428f08b671237237d651"},
+    {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1c3ac5423c8c1da5928aa12c6e258921956757d976405e9467c5f39d1d577a4b"},
+    {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:806abdd8249ba3953c33742506fe414880bad78ac25cc9a9b1c6ae97bedd573f"},
+    {file = "Pillow-10.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:eaed6977fa73408b7b8a24e8b14e59e1668cfc0f4c40193ea7ced8e210adf996"},
+    {file = "Pillow-10.1.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793"},
+    {file = "Pillow-10.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7a7e3daa202beb61821c06d2517428e8e7c1aab08943e92ec9e5755c2fc9ba5e"},
+    {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24fadc71218ad2b8ffe437b54876c9382b4a29e030a05a9879f615091f42ffc2"},
+    {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a"},
+    {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:912e3812a1dbbc834da2b32299b124b5ddcb664ed354916fd1ed6f193f0e2d01"},
+    {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7dbaa3c7de82ef37e7708521be41db5565004258ca76945ad74a8e998c30af8d"},
+    {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9d7bc666bd8c5a4225e7ac71f2f9d12466ec555e89092728ea0f5c0c2422ea80"},
+    {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baada14941c83079bf84c037e2d8b7506ce201e92e3d2fa0d1303507a8538212"},
+    {file = "Pillow-10.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:2ef6721c97894a7aa77723740a09547197533146fba8355e86d6d9a4a1056b14"},
+    {file = "Pillow-10.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0a026c188be3b443916179f5d04548092e253beb0c3e2ee0a4e2cdad72f66099"},
+    {file = "Pillow-10.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04f6f6149f266a100374ca3cc368b67fb27c4af9f1cc8cb6306d849dcdf12616"},
+    {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb40c011447712d2e19cc261c82655f75f32cb724788df315ed992a4d65696bb"},
+    {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a8413794b4ad9719346cd9306118450b7b00d9a15846451549314a58ac42219"},
+    {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c9aeea7b63edb7884b031a35305629a7593272b54f429a9869a4f63a1bf04c34"},
+    {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b4005fee46ed9be0b8fb42be0c20e79411533d1fd58edabebc0dd24626882cfd"},
+    {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0152565c6aa6ebbfb1e5d8624140a440f2b99bf7afaafbdbf6430426497f28"},
+    {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d921bc90b1defa55c9917ca6b6b71430e4286fc9e44c55ead78ca1a9f9eba5f2"},
+    {file = "Pillow-10.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfe96560c6ce2f4c07d6647af2d0f3c54cc33289894ebd88cfbb3bcd5391e256"},
+    {file = "Pillow-10.1.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:937bdc5a7f5343d1c97dc98149a0be7eb9704e937fe3dc7140e229ae4fc572a7"},
+    {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1c25762197144e211efb5f4e8ad656f36c8d214d390585d1d21281f46d556ba"},
+    {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:afc8eef765d948543a4775f00b7b8c079b3321d6b675dde0d02afa2ee23000b4"},
+    {file = "Pillow-10.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:883f216eac8712b83a63f41b76ddfb7b2afab1b74abbb413c5df6680f071a6b9"},
+    {file = "Pillow-10.1.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b920e4d028f6442bea9a75b7491c063f0b9a3972520731ed26c83e254302eb1e"},
+    {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c41d960babf951e01a49c9746f92c5a7e0d939d1652d7ba30f6b3090f27e412"},
+    {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1fafabe50a6977ac70dfe829b2d5735fd54e190ab55259ec8aea4aaea412fa0b"},
+    {file = "Pillow-10.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3b834f4b16173e5b92ab6566f0473bfb09f939ba14b23b8da1f54fa63e4b623f"},
+    {file = "Pillow-10.1.0.tar.gz", hash = "sha256:e6bf8de6c36ed96c86ea3b6e1d5273c53f46ef518a062464cd7ef5dd2cf92e38"},
+]
+
+[package.extras]
+docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"]
+tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
+
+[[package]]
+name = "pint"
+version = "0.22"
+description = "Physical quantities module"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "Pint-0.22-py3-none-any.whl", hash = "sha256:6e2b3c5c2b4d9b516608bc860a417a39d66eb99c958f36540cf931d2c2e9f80f"},
+    {file = "Pint-0.22.tar.gz", hash = "sha256:2d139f6abbcf3016cad7d3cec05707fe908ac4f99cf59aedfd6ee667b7a64433"},
+]
+
+[package.dependencies]
+typing-extensions = "*"
+
+[package.extras]
+babel = ["babel (<=2.8)"]
+dask = ["dask"]
+mip = ["mip (>=1.13)"]
+numpy = ["numpy (>=1.19.5)"]
+pandas = ["pint-pandas (>=0.3)"]
+test = ["pytest", "pytest-cov", "pytest-mpl", "pytest-subtests"]
+uncertainties = ["uncertainties (>=3.1.6)"]
+xarray = ["xarray"]
+
+[[package]]
+name = "pint-xarray"
+version = "0.3"
+description = "Physical units interface to xarray using Pint"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "pint-xarray-0.3.tar.gz", hash = "sha256:3545dfa78bee3f98eba29b8bd17500e3b5cb7c7b03a2c2781c4d4d59b6a82841"},
+    {file = "pint_xarray-0.3-py3-none-any.whl", hash = "sha256:a7d87c792a2e981cbff464bd1c875e872ef7a0c882a9395cfbc34512b3dcb1ab"},
+]
+
+[package.dependencies]
+numpy = ">=1.17"
+pint = ">=0.16"
+xarray = ">=0.16.1"
+
+[[package]]
+name = "platformdirs"
+version = "4.0.0"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"},
+    {file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"},
+]
+
+[package.extras]
+docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
+
+[[package]]
+name = "pluggy"
+version = "1.3.0"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"},
+    {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"},
+]
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "pooch"
+version = "1.8.0"
+description = "\"Pooch manages your Python library's sample data files: it automatically downloads and stores them in a local directory, with support for versioning and corruption checks.\""
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "pooch-1.8.0-py3-none-any.whl", hash = "sha256:1bfba436d9e2ad5199ccad3583cca8c241b8736b5bb23fe67c213d52650dbb66"},
+    {file = "pooch-1.8.0.tar.gz", hash = "sha256:f59981fd5b9b5d032dcde8f4a11eaa492c2ac6343fae3596a2fdae35fc54b0a0"},
+]
+
+[package.dependencies]
+packaging = ">=20.0"
+platformdirs = ">=2.5.0"
+requests = ">=2.19.0"
+
+[package.extras]
+progress = ["tqdm (>=4.41.0,<5.0.0)"]
+sftp = ["paramiko (>=2.7.0)"]
+xxhash = ["xxhash (>=1.4.3)"]
+
+[[package]]
+name = "pre-commit"
+version = "3.5.0"
+description = "A framework for managing and maintaining multi-language pre-commit hooks."
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"},
+    {file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"},
+]
+
+[package.dependencies]
+cfgv = ">=2.0.0"
+identify = ">=1.0.0"
+nodeenv = ">=0.11.1"
+pyyaml = ">=5.1"
+virtualenv = ">=20.10.0"
+
+[[package]]
+name = "primap2"
+version = "0.9.8"
+description = "The next generation of the PRIMAP climate policy analysis suite."
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "primap2-0.9.8-py3-none-any.whl", hash = "sha256:ebe6890a14b1f4e2040218e0a121862eeeae048440ccbc7e0af6d347c6e2ba45"},
+    {file = "primap2-0.9.8.tar.gz", hash = "sha256:7bbe90e6fb3b519b9e98858dbed28c6b9651fe8abccecf787b56f562c310f449"},
+]
+
+[package.dependencies]
+bottleneck = "*"
+h5netcdf = ">=0.10"
+h5py = "*"
+loguru = "*"
+matplotlib = "*"
+numpy = "*"
+openpyxl = "*"
+openscm-units = ">=0.5.1"
+pandas = "*"
+pint = ">=0.20.1"
+pint-xarray = ">=0.2"
+"ruamel.yaml" = "*"
+scipy = "*"
+strictyaml = "*"
+xarray = "*"
+
+[package.extras]
+datalad = ["datalad"]
+dev = ["Sphinx (>=4.2)", "build", "coverage", "flake8", "ipykernel", "jupyter", "mypy", "nbsphinx", "numpydoc", "pip", "pre-commit", "pytest", "pytest-cov", "setuptools", "sphinx-autosummary-accessors", "sphinx-rtd-theme", "tbump", "tox", "twine", "wheel", "xdoctest"]
+test = ["pytest", "pytest-cov", "xdoctest"]
+
+[[package]]
+name = "prompt-toolkit"
+version = "3.0.41"
+description = "Library for building powerful interactive command lines in Python"
+optional = false
+python-versions = ">=3.7.0"
+files = [
+    {file = "prompt_toolkit-3.0.41-py3-none-any.whl", hash = "sha256:f36fe301fafb7470e86aaf90f036eef600a3210be4decf461a5b1ca8403d3cb2"},
+    {file = "prompt_toolkit-3.0.41.tar.gz", hash = "sha256:941367d97fc815548822aa26c2a269fdc4eb21e9ec05fc5d447cf09bad5d75f0"},
+]
+
+[package.dependencies]
+wcwidth = "*"
+
+[[package]]
+name = "psutil"
+version = "5.9.6"
+description = "Cross-platform lib for process and system monitoring in Python."
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+files = [
+    {file = "psutil-5.9.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d"},
+    {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c"},
+    {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28"},
+    {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017"},
+    {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c"},
+    {file = "psutil-5.9.6-cp27-none-win32.whl", hash = "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9"},
+    {file = "psutil-5.9.6-cp27-none-win_amd64.whl", hash = "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac"},
+    {file = "psutil-5.9.6-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a"},
+    {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c"},
+    {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4"},
+    {file = "psutil-5.9.6-cp36-cp36m-win32.whl", hash = "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602"},
+    {file = "psutil-5.9.6-cp36-cp36m-win_amd64.whl", hash = "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa"},
+    {file = "psutil-5.9.6-cp37-abi3-win32.whl", hash = "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c"},
+    {file = "psutil-5.9.6-cp37-abi3-win_amd64.whl", hash = "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a"},
+    {file = "psutil-5.9.6-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57"},
+    {file = "psutil-5.9.6.tar.gz", hash = "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a"},
+]
+
+[package.extras]
+test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"]
+
+[[package]]
+name = "ptyprocess"
+version = "0.7.0"
+description = "Run a subprocess in a pseudo terminal"
+optional = false
+python-versions = "*"
+files = [
+    {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"},
+    {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"},
+]
+
+[[package]]
+name = "pure-eval"
+version = "0.2.2"
+description = "Safely evaluate AST nodes without side effects"
+optional = false
+python-versions = "*"
+files = [
+    {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"},
+    {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"},
+]
+
+[package.extras]
+tests = ["pytest"]
+
+[[package]]
+name = "pyarrow"
+version = "14.0.1"
+description = "Python library for Apache Arrow"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "pyarrow-14.0.1-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:96d64e5ba7dceb519a955e5eeb5c9adcfd63f73a56aea4722e2cc81364fc567a"},
+    {file = "pyarrow-14.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a8ae88c0038d1bc362a682320112ee6774f006134cd5afc291591ee4bc06505"},
+    {file = "pyarrow-14.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f6f053cb66dc24091f5511e5920e45c83107f954a21032feadc7b9e3a8e7851"},
+    {file = "pyarrow-14.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:906b0dc25f2be12e95975722f1e60e162437023f490dbd80d0deb7375baf3171"},
+    {file = "pyarrow-14.0.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:78d4a77a46a7de9388b653af1c4ce539350726cd9af62e0831e4f2bd0c95a2f4"},
+    {file = "pyarrow-14.0.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:06ca79080ef89d6529bb8e5074d4b4f6086143b2520494fcb7cf8a99079cde93"},
+    {file = "pyarrow-14.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:32542164d905002c42dff896efdac79b3bdd7291b1b74aa292fac8450d0e4dcd"},
+    {file = "pyarrow-14.0.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:c7331b4ed3401b7ee56f22c980608cf273f0380f77d0f73dd3c185f78f5a6220"},
+    {file = "pyarrow-14.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:922e8b49b88da8633d6cac0e1b5a690311b6758d6f5d7c2be71acb0f1e14cd61"},
+    {file = "pyarrow-14.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58c889851ca33f992ea916b48b8540735055201b177cb0dcf0596a495a667b00"},
+    {file = "pyarrow-14.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30d8494870d9916bb53b2a4384948491444741cb9a38253c590e21f836b01222"},
+    {file = "pyarrow-14.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:be28e1a07f20391bb0b15ea03dcac3aade29fc773c5eb4bee2838e9b2cdde0cb"},
+    {file = "pyarrow-14.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:981670b4ce0110d8dcb3246410a4aabf5714db5d8ea63b15686bce1c914b1f83"},
+    {file = "pyarrow-14.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:4756a2b373a28f6166c42711240643fb8bd6322467e9aacabd26b488fa41ec23"},
+    {file = "pyarrow-14.0.1-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:cf87e2cec65dd5cf1aa4aba918d523ef56ef95597b545bbaad01e6433851aa10"},
+    {file = "pyarrow-14.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:470ae0194fbfdfbf4a6b65b4f9e0f6e1fa0ea5b90c1ee6b65b38aecee53508c8"},
+    {file = "pyarrow-14.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6263cffd0c3721c1e348062997babdf0151301f7353010c9c9a8ed47448f82ab"},
+    {file = "pyarrow-14.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8089d7e77d1455d529dbd7cff08898bbb2666ee48bc4085203af1d826a33cc"},
+    {file = "pyarrow-14.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:fada8396bc739d958d0b81d291cfd201126ed5e7913cb73de6bc606befc30226"},
+    {file = "pyarrow-14.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:2a145dab9ed7849fc1101bf03bcdc69913547f10513fdf70fc3ab6c0a50c7eee"},
+    {file = "pyarrow-14.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:05fe7994745b634c5fb16ce5717e39a1ac1fac3e2b0795232841660aa76647cd"},
+    {file = "pyarrow-14.0.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:a8eeef015ae69d104c4c3117a6011e7e3ecd1abec79dc87fd2fac6e442f666ee"},
+    {file = "pyarrow-14.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3c76807540989fe8fcd02285dd15e4f2a3da0b09d27781abec3adc265ddbeba1"},
+    {file = "pyarrow-14.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:450e4605e3c20e558485f9161a79280a61c55efe585d51513c014de9ae8d393f"},
+    {file = "pyarrow-14.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:323cbe60210173ffd7db78bfd50b80bdd792c4c9daca8843ef3cd70b186649db"},
+    {file = "pyarrow-14.0.1-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:0140c7e2b740e08c5a459439d87acd26b747fc408bde0a8806096ee0baaa0c15"},
+    {file = "pyarrow-14.0.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:e592e482edd9f1ab32f18cd6a716c45b2c0f2403dc2af782f4e9674952e6dd27"},
+    {file = "pyarrow-14.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:d264ad13605b61959f2ae7c1d25b1a5b8505b112715c961418c8396433f213ad"},
+    {file = "pyarrow-14.0.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:01e44de9749cddc486169cb632f3c99962318e9dacac7778315a110f4bf8a450"},
+    {file = "pyarrow-14.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d0351fecf0e26e152542bc164c22ea2a8e8c682726fce160ce4d459ea802d69c"},
+    {file = "pyarrow-14.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33c1f6110c386464fd2e5e4ea3624466055bbe681ff185fd6c9daa98f30a3f9a"},
+    {file = "pyarrow-14.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11e045dfa09855b6d3e7705a37c42e2dc2c71d608fab34d3c23df2e02df9aec3"},
+    {file = "pyarrow-14.0.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:097828b55321897db0e1dbfc606e3ff8101ae5725673498cbfa7754ee0da80e4"},
+    {file = "pyarrow-14.0.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1daab52050a1c48506c029e6fa0944a7b2436334d7e44221c16f6f1b2cc9c510"},
+    {file = "pyarrow-14.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:3f6d5faf4f1b0d5a7f97be987cf9e9f8cd39902611e818fe134588ee99bf0283"},
+    {file = "pyarrow-14.0.1.tar.gz", hash = "sha256:b8b3f4fe8d4ec15e1ef9b599b94683c5216adaed78d5cb4c606180546d1e2ee1"},
+]
+
+[package.dependencies]
+numpy = ">=1.16.6"
+
+[[package]]
+name = "pycountry"
+version = "22.3.5"
+description = "ISO country, subdivision, language, currency and script definitions and their translations"
+optional = false
+python-versions = ">=3.6, <4"
+files = [
+    {file = "pycountry-22.3.5.tar.gz", hash = "sha256:b2163a246c585894d808f18783e19137cb70a0c18fb36748dc01fc6f109c1646"},
+]
+
+[package.dependencies]
+setuptools = "*"
+
+[[package]]
+name = "pycparser"
+version = "2.21"
+description = "C parser in Python"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+    {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
+    {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
+]
+
+[[package]]
+name = "pygments"
+version = "2.17.2"
+description = "Pygments is a syntax highlighting package written in Python."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"},
+    {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"},
+]
+
+[package.extras]
+plugins = ["importlib-metadata"]
+windows-terminal = ["colorama (>=0.4.6)"]
+
+[[package]]
+name = "pyparsing"
+version = "3.1.1"
+description = "pyparsing module - Classes and methods to define and execute parsing grammars"
+optional = false
+python-versions = ">=3.6.8"
+files = [
+    {file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"},
+    {file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"},
+]
+
+[package.extras]
+diagrams = ["jinja2", "railroad-diagrams"]
+
+[[package]]
+name = "pypdf"
+version = "3.17.1"
+description = "A pure-python PDF library capable of splitting, merging, cropping, and transforming PDF files"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "pypdf-3.17.1-py3-none-any.whl", hash = "sha256:df3a7e90f1d3e4c9fe88a6b45c2ae58e61fe48a0fe0bc6de1544596e479a3f97"},
+    {file = "pypdf-3.17.1.tar.gz", hash = "sha256:c79ad4db16c9a86071a3556fb5d619022b36b8880ba3ef416558ea95fbec4cb9"},
+]
+
+[package.dependencies]
+typing_extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.10\""}
+
+[package.extras]
+crypto = ["PyCryptodome", "cryptography"]
+dev = ["black", "flit", "pip-tools", "pre-commit (<2.18.0)", "pytest-cov", "pytest-socket", "pytest-timeout", "pytest-xdist", "wheel"]
+docs = ["myst_parser", "sphinx", "sphinx_rtd_theme"]
+full = ["Pillow (>=8.0.0)", "PyCryptodome", "cryptography"]
+image = ["Pillow (>=8.0.0)"]
+
+[[package]]
+name = "pysocks"
+version = "1.7.1"
+description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information."
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+    {file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"},
+    {file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"},
+    {file = "PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"},
+]
+
+[[package]]
+name = "pytest"
+version = "7.4.3"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"},
+    {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
+
+[[package]]
+name = "pytest-cov"
+version = "4.1.0"
+description = "Pytest plugin for measuring coverage."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"},
+    {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"},
+]
+
+[package.dependencies]
+coverage = {version = ">=5.2.1", extras = ["toml"]}
+pytest = ">=4.6"
+
+[package.extras]
+testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"]
+
+[[package]]
+name = "python-dateutil"
+version = "2.8.2"
+description = "Extensions to the standard Python datetime module"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+files = [
+    {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
+    {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
+]
+
+[package.dependencies]
+six = ">=1.5"
+
+[[package]]
+name = "python-gitlab"
+version = "4.2.0"
+description = "A python wrapper for the GitLab API"
+optional = false
+python-versions = ">=3.8.0"
+files = [
+    {file = "python-gitlab-4.2.0.tar.gz", hash = "sha256:f870d76f98c95d05c43399d73b1eaab59c671b32793830cd2f9ddf32cc93541e"},
+    {file = "python_gitlab-4.2.0-py3-none-any.whl", hash = "sha256:fa265266f24740ee654de51860ff78c9c3e422bb8a8c7ea8eedf353c75f57609"},
+]
+
+[package.dependencies]
+requests = ">=2.25.0"
+requests-toolbelt = ">=0.10.1"
+
+[package.extras]
+autocompletion = ["argcomplete (>=1.10.0,<3)"]
+yaml = ["PyYaml (>=6.0.1)"]
+
+[[package]]
+name = "pytz"
+version = "2023.3.post1"
+description = "World timezone definitions, modern and historical"
+optional = false
+python-versions = "*"
+files = [
+    {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"},
+    {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"},
+]
+
+[[package]]
+name = "pywin32"
+version = "306"
+description = "Python for Window Extensions"
+optional = false
+python-versions = "*"
+files = [
+    {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"},
+    {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"},
+    {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"},
+    {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"},
+    {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"},
+    {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"},
+    {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"},
+    {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"},
+    {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"},
+    {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"},
+    {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"},
+    {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"},
+    {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"},
+    {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"},
+]
+
+[[package]]
+name = "pywin32-ctypes"
+version = "0.2.2"
+description = "A (partial) reimplementation of pywin32 using ctypes/cffi"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "pywin32-ctypes-0.2.2.tar.gz", hash = "sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60"},
+    {file = "pywin32_ctypes-0.2.2-py3-none-any.whl", hash = "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7"},
+]
+
+[[package]]
+name = "pyyaml"
+version = "6.0.1"
+description = "YAML parser and emitter for Python"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
+    {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
+    {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
+    {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
+    {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
+    {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
+    {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
+    {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
+    {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
+    {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
+    {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
+    {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
+    {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
+    {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
+    {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
+    {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
+    {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
+    {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
+    {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
+    {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
+    {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
+    {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
+    {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
+    {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
+    {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
+    {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
+    {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
+    {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
+    {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
+    {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
+    {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
+    {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
+    {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
+    {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
+    {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
+    {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
+    {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
+    {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
+    {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
+    {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
+    {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
+    {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
+    {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
+    {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
+    {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
+    {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
+    {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
+    {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
+    {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
+    {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
+]
+
+[[package]]
+name = "pyzmq"
+version = "25.1.1"
+description = "Python bindings for 0MQ"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "pyzmq-25.1.1-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:381469297409c5adf9a0e884c5eb5186ed33137badcbbb0560b86e910a2f1e76"},
+    {file = "pyzmq-25.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:955215ed0604dac5b01907424dfa28b40f2b2292d6493445dd34d0dfa72586a8"},
+    {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:985bbb1316192b98f32e25e7b9958088431d853ac63aca1d2c236f40afb17c83"},
+    {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:afea96f64efa98df4da6958bae37f1cbea7932c35878b185e5982821bc883369"},
+    {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76705c9325d72a81155bb6ab48d4312e0032bf045fb0754889133200f7a0d849"},
+    {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:77a41c26205d2353a4c94d02be51d6cbdf63c06fbc1295ea57dad7e2d3381b71"},
+    {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:12720a53e61c3b99d87262294e2b375c915fea93c31fc2336898c26d7aed34cd"},
+    {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:57459b68e5cd85b0be8184382cefd91959cafe79ae019e6b1ae6e2ba8a12cda7"},
+    {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:292fe3fc5ad4a75bc8df0dfaee7d0babe8b1f4ceb596437213821f761b4589f9"},
+    {file = "pyzmq-25.1.1-cp310-cp310-win32.whl", hash = "sha256:35b5ab8c28978fbbb86ea54958cd89f5176ce747c1fb3d87356cf698048a7790"},
+    {file = "pyzmq-25.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:11baebdd5fc5b475d484195e49bae2dc64b94a5208f7c89954e9e354fc609d8f"},
+    {file = "pyzmq-25.1.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:d20a0ddb3e989e8807d83225a27e5c2eb2260eaa851532086e9e0fa0d5287d83"},
+    {file = "pyzmq-25.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e1c1be77bc5fb77d923850f82e55a928f8638f64a61f00ff18a67c7404faf008"},
+    {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d89528b4943d27029a2818f847c10c2cecc79fa9590f3cb1860459a5be7933eb"},
+    {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:90f26dc6d5f241ba358bef79be9ce06de58d477ca8485e3291675436d3827cf8"},
+    {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2b92812bd214018e50b6380ea3ac0c8bb01ac07fcc14c5f86a5bb25e74026e9"},
+    {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:2f957ce63d13c28730f7fd6b72333814221c84ca2421298f66e5143f81c9f91f"},
+    {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:047a640f5c9c6ade7b1cc6680a0e28c9dd5a0825135acbd3569cc96ea00b2505"},
+    {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7f7e58effd14b641c5e4dec8c7dab02fb67a13df90329e61c869b9cc607ef752"},
+    {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c2910967e6ab16bf6fbeb1f771c89a7050947221ae12a5b0b60f3bca2ee19bca"},
+    {file = "pyzmq-25.1.1-cp311-cp311-win32.whl", hash = "sha256:76c1c8efb3ca3a1818b837aea423ff8a07bbf7aafe9f2f6582b61a0458b1a329"},
+    {file = "pyzmq-25.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:44e58a0554b21fc662f2712814a746635ed668d0fbc98b7cb9d74cb798d202e6"},
+    {file = "pyzmq-25.1.1-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:e1ffa1c924e8c72778b9ccd386a7067cddf626884fd8277f503c48bb5f51c762"},
+    {file = "pyzmq-25.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1af379b33ef33757224da93e9da62e6471cf4a66d10078cf32bae8127d3d0d4a"},
+    {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cff084c6933680d1f8b2f3b4ff5bbb88538a4aac00d199ac13f49d0698727ecb"},
+    {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2400a94f7dd9cb20cd012951a0cbf8249e3d554c63a9c0cdfd5cbb6c01d2dec"},
+    {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d81f1ddae3858b8299d1da72dd7d19dd36aab654c19671aa8a7e7fb02f6638a"},
+    {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:255ca2b219f9e5a3a9ef3081512e1358bd4760ce77828e1028b818ff5610b87b"},
+    {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a882ac0a351288dd18ecae3326b8a49d10c61a68b01419f3a0b9a306190baf69"},
+    {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:724c292bb26365659fc434e9567b3f1adbdb5e8d640c936ed901f49e03e5d32e"},
+    {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ca1ed0bb2d850aa8471387882247c68f1e62a4af0ce9c8a1dbe0d2bf69e41fb"},
+    {file = "pyzmq-25.1.1-cp312-cp312-win32.whl", hash = "sha256:b3451108ab861040754fa5208bca4a5496c65875710f76789a9ad27c801a0075"},
+    {file = "pyzmq-25.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:eadbefd5e92ef8a345f0525b5cfd01cf4e4cc651a2cffb8f23c0dd184975d787"},
+    {file = "pyzmq-25.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:db0b2af416ba735c6304c47f75d348f498b92952f5e3e8bff449336d2728795d"},
+    {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c133e93b405eb0d36fa430c94185bdd13c36204a8635470cccc200723c13bb"},
+    {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:273bc3959bcbff3f48606b28229b4721716598d76b5aaea2b4a9d0ab454ec062"},
+    {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cbc8df5c6a88ba5ae385d8930da02201165408dde8d8322072e3e5ddd4f68e22"},
+    {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:18d43df3f2302d836f2a56f17e5663e398416e9dd74b205b179065e61f1a6edf"},
+    {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:73461eed88a88c866656e08f89299720a38cb4e9d34ae6bf5df6f71102570f2e"},
+    {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:34c850ce7976d19ebe7b9d4b9bb8c9dfc7aac336c0958e2651b88cbd46682123"},
+    {file = "pyzmq-25.1.1-cp36-cp36m-win32.whl", hash = "sha256:d2045d6d9439a0078f2a34b57c7b18c4a6aef0bee37f22e4ec9f32456c852c71"},
+    {file = "pyzmq-25.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:458dea649f2f02a0b244ae6aef8dc29325a2810aa26b07af8374dc2a9faf57e3"},
+    {file = "pyzmq-25.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7cff25c5b315e63b07a36f0c2bab32c58eafbe57d0dce61b614ef4c76058c115"},
+    {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1579413ae492b05de5a6174574f8c44c2b9b122a42015c5292afa4be2507f28"},
+    {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3d0a409d3b28607cc427aa5c30a6f1e4452cc44e311f843e05edb28ab5e36da0"},
+    {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:21eb4e609a154a57c520e3d5bfa0d97e49b6872ea057b7c85257b11e78068222"},
+    {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:034239843541ef7a1aee0c7b2cb7f6aafffb005ede965ae9cbd49d5ff4ff73cf"},
+    {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f8115e303280ba09f3898194791a153862cbf9eef722ad8f7f741987ee2a97c7"},
+    {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1a5d26fe8f32f137e784f768143728438877d69a586ddeaad898558dc971a5ae"},
+    {file = "pyzmq-25.1.1-cp37-cp37m-win32.whl", hash = "sha256:f32260e556a983bc5c7ed588d04c942c9a8f9c2e99213fec11a031e316874c7e"},
+    {file = "pyzmq-25.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:abf34e43c531bbb510ae7e8f5b2b1f2a8ab93219510e2b287a944432fad135f3"},
+    {file = "pyzmq-25.1.1-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:87e34f31ca8f168c56d6fbf99692cc8d3b445abb5bfd08c229ae992d7547a92a"},
+    {file = "pyzmq-25.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c9c6c9b2c2f80747a98f34ef491c4d7b1a8d4853937bb1492774992a120f475d"},
+    {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5619f3f5a4db5dbb572b095ea3cb5cc035335159d9da950830c9c4db2fbb6995"},
+    {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a34d2395073ef862b4032343cf0c32a712f3ab49d7ec4f42c9661e0294d106f"},
+    {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25f0e6b78220aba09815cd1f3a32b9c7cb3e02cb846d1cfc526b6595f6046618"},
+    {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3669cf8ee3520c2f13b2e0351c41fea919852b220988d2049249db10046a7afb"},
+    {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2d163a18819277e49911f7461567bda923461c50b19d169a062536fffe7cd9d2"},
+    {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:df27ffddff4190667d40de7beba4a950b5ce78fe28a7dcc41d6f8a700a80a3c0"},
+    {file = "pyzmq-25.1.1-cp38-cp38-win32.whl", hash = "sha256:a382372898a07479bd34bda781008e4a954ed8750f17891e794521c3e21c2e1c"},
+    {file = "pyzmq-25.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:52533489f28d62eb1258a965f2aba28a82aa747202c8fa5a1c7a43b5db0e85c1"},
+    {file = "pyzmq-25.1.1-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:03b3f49b57264909aacd0741892f2aecf2f51fb053e7d8ac6767f6c700832f45"},
+    {file = "pyzmq-25.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:330f9e188d0d89080cde66dc7470f57d1926ff2fb5576227f14d5be7ab30b9fa"},
+    {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2ca57a5be0389f2a65e6d3bb2962a971688cbdd30b4c0bd188c99e39c234f414"},
+    {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d457aed310f2670f59cc5b57dcfced452aeeed77f9da2b9763616bd57e4dbaae"},
+    {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c56d748ea50215abef7030c72b60dd723ed5b5c7e65e7bc2504e77843631c1a6"},
+    {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8f03d3f0d01cb5a018debeb412441996a517b11c5c17ab2001aa0597c6d6882c"},
+    {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:820c4a08195a681252f46926de10e29b6bbf3e17b30037bd4250d72dd3ddaab8"},
+    {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17ef5f01d25b67ca8f98120d5fa1d21efe9611604e8eb03a5147360f517dd1e2"},
+    {file = "pyzmq-25.1.1-cp39-cp39-win32.whl", hash = "sha256:04ccbed567171579ec2cebb9c8a3e30801723c575601f9a990ab25bcac6b51e2"},
+    {file = "pyzmq-25.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:e61f091c3ba0c3578411ef505992d356a812fb200643eab27f4f70eed34a29ef"},
+    {file = "pyzmq-25.1.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ade6d25bb29c4555d718ac6d1443a7386595528c33d6b133b258f65f963bb0f6"},
+    {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0c95ddd4f6e9fca4e9e3afaa4f9df8552f0ba5d1004e89ef0a68e1f1f9807c7"},
+    {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48e466162a24daf86f6b5ca72444d2bf39a5e58da5f96370078be67c67adc978"},
+    {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abc719161780932c4e11aaebb203be3d6acc6b38d2f26c0f523b5b59d2fc1996"},
+    {file = "pyzmq-25.1.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1ccf825981640b8c34ae54231b7ed00271822ea1c6d8ba1090ebd4943759abf5"},
+    {file = "pyzmq-25.1.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c2f20ce161ebdb0091a10c9ca0372e023ce24980d0e1f810f519da6f79c60800"},
+    {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:deee9ca4727f53464daf089536e68b13e6104e84a37820a88b0a057b97bba2d2"},
+    {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:aa8d6cdc8b8aa19ceb319aaa2b660cdaccc533ec477eeb1309e2a291eaacc43a"},
+    {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:019e59ef5c5256a2c7378f2fb8560fc2a9ff1d315755204295b2eab96b254d0a"},
+    {file = "pyzmq-25.1.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:b9af3757495c1ee3b5c4e945c1df7be95562277c6e5bccc20a39aec50f826cd0"},
+    {file = "pyzmq-25.1.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:548d6482dc8aadbe7e79d1b5806585c8120bafa1ef841167bc9090522b610fa6"},
+    {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:057e824b2aae50accc0f9a0570998adc021b372478a921506fddd6c02e60308e"},
+    {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2243700cc5548cff20963f0ca92d3e5e436394375ab8a354bbea2b12911b20b0"},
+    {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79986f3b4af059777111409ee517da24a529bdbd46da578b33f25580adcff728"},
+    {file = "pyzmq-25.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:11d58723d44d6ed4dd677c5615b2ffb19d5c426636345567d6af82be4dff8a55"},
+    {file = "pyzmq-25.1.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:49d238cf4b69652257db66d0c623cd3e09b5d2e9576b56bc067a396133a00d4a"},
+    {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fedbdc753827cf014c01dbbee9c3be17e5a208dcd1bf8641ce2cd29580d1f0d4"},
+    {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc16ac425cc927d0a57d242589f87ee093884ea4804c05a13834d07c20db203c"},
+    {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11c1d2aed9079c6b0c9550a7257a836b4a637feb334904610f06d70eb44c56d2"},
+    {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e8a701123029cc240cea61dd2d16ad57cab4691804143ce80ecd9286b464d180"},
+    {file = "pyzmq-25.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:61706a6b6c24bdece85ff177fec393545a3191eeda35b07aaa1458a027ad1304"},
+    {file = "pyzmq-25.1.1.tar.gz", hash = "sha256:259c22485b71abacdfa8bf79720cd7bcf4b9d128b30ea554f01ae71fdbfdaa23"},
+]
+
+[package.dependencies]
+cffi = {version = "*", markers = "implementation_name == \"pypy\""}
+
+[[package]]
+name = "referencing"
+version = "0.31.1"
+description = "JSON Referencing + Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "referencing-0.31.1-py3-none-any.whl", hash = "sha256:c19c4d006f1757e3dd75c4f784d38f8698d87b649c54f9ace14e5e8c9667c01d"},
+    {file = "referencing-0.31.1.tar.gz", hash = "sha256:81a1471c68c9d5e3831c30ad1dd9815c45b558e596653db751a2bfdd17b3b9ec"},
+]
+
+[package.dependencies]
+attrs = ">=22.2.0"
+rpds-py = ">=0.7.0"
+
+[[package]]
+name = "requests"
+version = "2.31.0"
+description = "Python HTTP for Humans."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
+    {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
+]
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+charset-normalizer = ">=2,<4"
+idna = ">=2.5,<4"
+urllib3 = ">=1.21.1,<3"
+
+[package.extras]
+socks = ["PySocks (>=1.5.6,!=1.5.7)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+
+[[package]]
+name = "requests-toolbelt"
+version = "1.0.0"
+description = "A utility belt for advanced users of python-requests"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+    {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"},
+    {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"},
+]
+
+[package.dependencies]
+requests = ">=2.0.1,<3.0.0"
+
+[[package]]
+name = "rich"
+version = "13.7.0"
+description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
+optional = false
+python-versions = ">=3.7.0"
+files = [
+    {file = "rich-13.7.0-py3-none-any.whl", hash = "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235"},
+    {file = "rich-13.7.0.tar.gz", hash = "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa"},
+]
+
+[package.dependencies]
+markdown-it-py = ">=2.2.0"
+pygments = ">=2.13.0,<3.0.0"
+
+[package.extras]
+jupyter = ["ipywidgets (>=7.5.1,<9)"]
+
+[[package]]
+name = "rpds-py"
+version = "0.13.2"
+description = "Python bindings to Rust's persistent data structures (rpds)"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "rpds_py-0.13.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1ceebd0ae4f3e9b2b6b553b51971921853ae4eebf3f54086be0565d59291e53d"},
+    {file = "rpds_py-0.13.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:46e1ed994a0920f350a4547a38471217eb86f57377e9314fbaaa329b71b7dfe3"},
+    {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee353bb51f648924926ed05e0122b6a0b1ae709396a80eb583449d5d477fcdf7"},
+    {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:530190eb0cd778363bbb7596612ded0bb9fef662daa98e9d92a0419ab27ae914"},
+    {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d311e44dd16d2434d5506d57ef4d7036544fc3c25c14b6992ef41f541b10fb"},
+    {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e72f750048b32d39e87fc85c225c50b2a6715034848dbb196bf3348aa761fa1"},
+    {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db09b98c7540df69d4b47218da3fbd7cb466db0fb932e971c321f1c76f155266"},
+    {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2ac26f50736324beb0282c819668328d53fc38543fa61eeea2c32ea8ea6eab8d"},
+    {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:12ecf89bd54734c3c2c79898ae2021dca42750c7bcfb67f8fb3315453738ac8f"},
+    {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a44c8440183b43167fd1a0819e8356692bf5db1ad14ce140dbd40a1485f2dea"},
+    {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bcef4f2d3dc603150421de85c916da19471f24d838c3c62a4f04c1eb511642c1"},
+    {file = "rpds_py-0.13.2-cp310-none-win32.whl", hash = "sha256:ee6faebb265e28920a6f23a7d4c362414b3f4bb30607141d718b991669e49ddc"},
+    {file = "rpds_py-0.13.2-cp310-none-win_amd64.whl", hash = "sha256:ac96d67b37f28e4b6ecf507c3405f52a40658c0a806dffde624a8fcb0314d5fd"},
+    {file = "rpds_py-0.13.2-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:b5f6328e8e2ae8238fc767703ab7b95785521c42bb2b8790984e3477d7fa71ad"},
+    {file = "rpds_py-0.13.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:729408136ef8d45a28ee9a7411917c9e3459cf266c7e23c2f7d4bb8ef9e0da42"},
+    {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65cfed9c807c27dee76407e8bb29e6f4e391e436774bcc769a037ff25ad8646e"},
+    {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aefbdc934115d2f9278f153952003ac52cd2650e7313750390b334518c589568"},
+    {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d48db29bd47814671afdd76c7652aefacc25cf96aad6daefa82d738ee87461e2"},
+    {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3c55d7f2d817183d43220738270efd3ce4e7a7b7cbdaefa6d551ed3d6ed89190"},
+    {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6aadae3042f8e6db3376d9e91f194c606c9a45273c170621d46128f35aef7cd0"},
+    {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5feae2f9aa7270e2c071f488fab256d768e88e01b958f123a690f1cc3061a09c"},
+    {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:51967a67ea0d7b9b5cd86036878e2d82c0b6183616961c26d825b8c994d4f2c8"},
+    {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d0c10d803549427f427085ed7aebc39832f6e818a011dcd8785e9c6a1ba9b3e"},
+    {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:603d5868f7419081d616dab7ac3cfa285296735e7350f7b1e4f548f6f953ee7d"},
+    {file = "rpds_py-0.13.2-cp311-none-win32.whl", hash = "sha256:b8996ffb60c69f677245f5abdbcc623e9442bcc91ed81b6cd6187129ad1fa3e7"},
+    {file = "rpds_py-0.13.2-cp311-none-win_amd64.whl", hash = "sha256:5379e49d7e80dca9811b36894493d1c1ecb4c57de05c36f5d0dd09982af20211"},
+    {file = "rpds_py-0.13.2-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8a776a29b77fe0cc28fedfd87277b0d0f7aa930174b7e504d764e0b43a05f381"},
+    {file = "rpds_py-0.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2a1472956c5bcc49fb0252b965239bffe801acc9394f8b7c1014ae9258e4572b"},
+    {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f252dfb4852a527987a9156cbcae3022a30f86c9d26f4f17b8c967d7580d65d2"},
+    {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f0d320e70b6b2300ff6029e234e79fe44e9dbbfc7b98597ba28e054bd6606a57"},
+    {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ade2ccb937060c299ab0dfb2dea3d2ddf7e098ed63ee3d651ebfc2c8d1e8632a"},
+    {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9d121be0217787a7d59a5c6195b0842d3f701007333426e5154bf72346aa658"},
+    {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fa6bd071ec6d90f6e7baa66ae25820d57a8ab1b0a3c6d3edf1834d4b26fafa2"},
+    {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c918621ee0a3d1fe61c313f2489464f2ae3d13633e60f520a8002a5e910982ee"},
+    {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:25b28b3d33ec0a78e944aaaed7e5e2a94ac811bcd68b557ca48a0c30f87497d2"},
+    {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:31e220a040b89a01505128c2f8a59ee74732f666439a03e65ccbf3824cdddae7"},
+    {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:15253fff410873ebf3cfba1cc686a37711efcd9b8cb30ea21bb14a973e393f60"},
+    {file = "rpds_py-0.13.2-cp312-none-win32.whl", hash = "sha256:b981a370f8f41c4024c170b42fbe9e691ae2dbc19d1d99151a69e2c84a0d194d"},
+    {file = "rpds_py-0.13.2-cp312-none-win_amd64.whl", hash = "sha256:4c4e314d36d4f31236a545696a480aa04ea170a0b021e9a59ab1ed94d4c3ef27"},
+    {file = "rpds_py-0.13.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:80e5acb81cb49fd9f2d5c08f8b74ffff14ee73b10ca88297ab4619e946bcb1e1"},
+    {file = "rpds_py-0.13.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:efe093acc43e869348f6f2224df7f452eab63a2c60a6c6cd6b50fd35c4e075ba"},
+    {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c2a61c0e4811012b0ba9f6cdcb4437865df5d29eab5d6018ba13cee1c3064a0"},
+    {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:751758d9dd04d548ec679224cc00e3591f5ebf1ff159ed0d4aba6a0746352452"},
+    {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ba8858933f0c1a979781272a5f65646fca8c18c93c99c6ddb5513ad96fa54b1"},
+    {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bfdfbe6a36bc3059fff845d64c42f2644cf875c65f5005db54f90cdfdf1df815"},
+    {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa0379c1935c44053c98826bc99ac95f3a5355675a297ac9ce0dfad0ce2d50ca"},
+    {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5593855b5b2b73dd8413c3fdfa5d95b99d657658f947ba2c4318591e745d083"},
+    {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2a7bef6977043673750a88da064fd513f89505111014b4e00fbdd13329cd4e9a"},
+    {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:3ab96754d23372009638a402a1ed12a27711598dd49d8316a22597141962fe66"},
+    {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:e06cfea0ece444571d24c18ed465bc93afb8c8d8d74422eb7026662f3d3f779b"},
+    {file = "rpds_py-0.13.2-cp38-none-win32.whl", hash = "sha256:5493569f861fb7b05af6d048d00d773c6162415ae521b7010197c98810a14cab"},
+    {file = "rpds_py-0.13.2-cp38-none-win_amd64.whl", hash = "sha256:b07501b720cf060c5856f7b5626e75b8e353b5f98b9b354a21eb4bfa47e421b1"},
+    {file = "rpds_py-0.13.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:881df98f0a8404d32b6de0fd33e91c1b90ed1516a80d4d6dc69d414b8850474c"},
+    {file = "rpds_py-0.13.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d79c159adea0f1f4617f54aa156568ac69968f9ef4d1e5fefffc0a180830308e"},
+    {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38d4f822ee2f338febcc85aaa2547eb5ba31ba6ff68d10b8ec988929d23bb6b4"},
+    {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5d75d6d220d55cdced2f32cc22f599475dbe881229aeddba6c79c2e9df35a2b3"},
+    {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d97e9ae94fb96df1ee3cb09ca376c34e8a122f36927230f4c8a97f469994bff"},
+    {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67a429520e97621a763cf9b3ba27574779c4e96e49a27ff8a1aa99ee70beb28a"},
+    {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:188435794405c7f0573311747c85a96b63c954a5f2111b1df8018979eca0f2f0"},
+    {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:38f9bf2ad754b4a45b8210a6c732fe876b8a14e14d5992a8c4b7c1ef78740f53"},
+    {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a6ba2cb7d676e9415b9e9ac7e2aae401dc1b1e666943d1f7bc66223d3d73467b"},
+    {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:eaffbd8814bb1b5dc3ea156a4c5928081ba50419f9175f4fc95269e040eff8f0"},
+    {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a4c1058cdae6237d97af272b326e5f78ee7ee3bbffa6b24b09db4d828810468"},
+    {file = "rpds_py-0.13.2-cp39-none-win32.whl", hash = "sha256:b5267feb19070bef34b8dea27e2b504ebd9d31748e3ecacb3a4101da6fcb255c"},
+    {file = "rpds_py-0.13.2-cp39-none-win_amd64.whl", hash = "sha256:ddf23960cb42b69bce13045d5bc66f18c7d53774c66c13f24cf1b9c144ba3141"},
+    {file = "rpds_py-0.13.2-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:97163a1ab265a1073a6372eca9f4eeb9f8c6327457a0b22ddfc4a17dcd613e74"},
+    {file = "rpds_py-0.13.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:25ea41635d22b2eb6326f58e608550e55d01df51b8a580ea7e75396bafbb28e9"},
+    {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d59d4d451ba77f08cb4cd9268dec07be5bc65f73666302dbb5061989b17198"},
+    {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7c564c58cf8f248fe859a4f0fe501b050663f3d7fbc342172f259124fb59933"},
+    {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61dbc1e01dc0c5875da2f7ae36d6e918dc1b8d2ce04e871793976594aad8a57a"},
+    {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdb82eb60d31b0c033a8e8ee9f3fc7dfbaa042211131c29da29aea8531b4f18f"},
+    {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d204957169f0b3511fb95395a9da7d4490fb361763a9f8b32b345a7fe119cb45"},
+    {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c45008ca79bad237cbc03c72bc5205e8c6f66403773929b1b50f7d84ef9e4d07"},
+    {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:79bf58c08f0756adba691d480b5a20e4ad23f33e1ae121584cf3a21717c36dfa"},
+    {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e86593bf8637659e6a6ed58854b6c87ec4e9e45ee8a4adfd936831cef55c2d21"},
+    {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d329896c40d9e1e5c7715c98529e4a188a1f2df51212fd65102b32465612b5dc"},
+    {file = "rpds_py-0.13.2-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4a5375c5fff13f209527cd886dc75394f040c7d1ecad0a2cb0627f13ebe78a12"},
+    {file = "rpds_py-0.13.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:06d218e4464d31301e943b65b2c6919318ea6f69703a351961e1baaf60347276"},
+    {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1f41d32a2ddc5a94df4b829b395916a4b7f103350fa76ba6de625fcb9e773ac"},
+    {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6bc568b05e02cd612be53900c88aaa55012e744930ba2eeb56279db4c6676eb3"},
+    {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d94d78418203904730585efa71002286ac4c8ac0689d0eb61e3c465f9e608ff"},
+    {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bed0252c85e21cf73d2d033643c945b460d6a02fc4a7d644e3b2d6f5f2956c64"},
+    {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:244e173bb6d8f3b2f0c4d7370a1aa341f35da3e57ffd1798e5b2917b91731fd3"},
+    {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7f55cd9cf1564b7b03f238e4c017ca4794c05b01a783e9291065cb2858d86ce4"},
+    {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:f03a1b3a4c03e3e0161642ac5367f08479ab29972ea0ffcd4fa18f729cd2be0a"},
+    {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:f5f4424cb87a20b016bfdc157ff48757b89d2cc426256961643d443c6c277007"},
+    {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c82bbf7e03748417c3a88c1b0b291288ce3e4887a795a3addaa7a1cfd9e7153e"},
+    {file = "rpds_py-0.13.2-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c0095b8aa3e432e32d372e9a7737e65b58d5ed23b9620fea7cb81f17672f1fa1"},
+    {file = "rpds_py-0.13.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:4c2d26aa03d877c9730bf005621c92da263523a1e99247590abbbe252ccb7824"},
+    {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96f2975fb14f39c5fe75203f33dd3010fe37d1c4e33177feef1107b5ced750e3"},
+    {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4dcc5ee1d0275cb78d443fdebd0241e58772a354a6d518b1d7af1580bbd2c4e8"},
+    {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61d42d2b08430854485135504f672c14d4fc644dd243a9c17e7c4e0faf5ed07e"},
+    {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d3a61e928feddc458a55110f42f626a2a20bea942ccedb6fb4cee70b4830ed41"},
+    {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7de12b69d95072394998c622cfd7e8cea8f560db5fca6a62a148f902a1029f8b"},
+    {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:87a90f5545fd61f6964e65eebde4dc3fa8660bb7d87adb01d4cf17e0a2b484ad"},
+    {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:9c95a1a290f9acf7a8f2ebbdd183e99215d491beea52d61aa2a7a7d2c618ddc6"},
+    {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:35f53c76a712e323c779ca39b9a81b13f219a8e3bc15f106ed1e1462d56fcfe9"},
+    {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:96fb0899bb2ab353f42e5374c8f0789f54e0a94ef2f02b9ac7149c56622eaf31"},
+    {file = "rpds_py-0.13.2.tar.gz", hash = "sha256:f8eae66a1304de7368932b42d801c67969fd090ddb1a7a24f27b435ed4bed68f"},
+]
+
+[[package]]
+name = "ruamel-yaml"
+version = "0.18.5"
+description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "ruamel.yaml-0.18.5-py3-none-any.whl", hash = "sha256:a013ac02f99a69cdd6277d9664689eb1acba07069f912823177c5eced21a6ada"},
+    {file = "ruamel.yaml-0.18.5.tar.gz", hash = "sha256:61917e3a35a569c1133a8f772e1226961bf5a1198bea7e23f06a0841dea1ab0e"},
+]
+
+[package.dependencies]
+"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.13\""}
+
+[package.extras]
+docs = ["mercurial (>5.7)", "ryd"]
+jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"]
+
+[[package]]
+name = "ruamel-yaml-clib"
+version = "0.2.8"
+description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"},
+    {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"},
+    {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"},
+    {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f"},
+    {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334"},
+    {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d"},
+    {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"},
+    {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"},
+    {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"},
+    {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"},
+    {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"},
+    {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"},
+    {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"},
+    {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"},
+    {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"},
+    {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"},
+    {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"},
+    {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"},
+    {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"},
+    {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62"},
+    {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9"},
+    {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d"},
+    {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa"},
+    {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win_amd64.whl", hash = "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b"},
+    {file = "ruamel.yaml.clib-0.2.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed"},
+    {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942"},
+    {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875"},
+    {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6"},
+    {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3"},
+    {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7"},
+    {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3"},
+    {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win32.whl", hash = "sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b"},
+    {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675"},
+    {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"},
+    {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"},
+    {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1"},
+    {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"},
+    {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28"},
+    {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d"},
+    {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win32.whl", hash = "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe"},
+    {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"},
+    {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"},
+    {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"},
+    {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c"},
+    {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"},
+    {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b"},
+    {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880"},
+    {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win32.whl", hash = "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5"},
+    {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15"},
+    {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"},
+]
+
+[[package]]
+name = "ruff"
+version = "0.0.264"
+description = "An extremely fast Python linter, written in Rust."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "ruff-0.0.264-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:ec2fa192c035b8b68cc2b91049c561cd69543e2b8c4d157d9aa7727320bedcca"},
+    {file = "ruff-0.0.264-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:d97ba8db0fb601ffe9ee996ebb97c698e427a2fd4514fefbe7b803111354f783"},
+    {file = "ruff-0.0.264-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4564e0f245eb515c6ed63988c21e9c40bcfd485cd1ec63bdd790f9a81d301f15"},
+    {file = "ruff-0.0.264-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:323ae6c1702b26c96d0fbf939c5959c37e79021f86b70f63634df918bc77f36e"},
+    {file = "ruff-0.0.264-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18a29ed37bf8cfe6dce8a2db56c313a64c0804095108753621f3c3321e0c9c5f"},
+    {file = "ruff-0.0.264-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d628de91e2be7a83128526636097d2dd890669a06143f826f6c591d79aeefbc4"},
+    {file = "ruff-0.0.264-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91c6eb4f979b661a2dd850d9ac803842bb7b66d4926de84f09c787af82590f73"},
+    {file = "ruff-0.0.264-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04ec5d75e4bca754cedd20d53e2ba4920d6259e7579abfb2e8e30c3c80e41b17"},
+    {file = "ruff-0.0.264-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71fd865ebacc1083259b3fb7e3eb45235a86e62e21830b8a6b067be0ec54aa2e"},
+    {file = "ruff-0.0.264-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:cd4f60ffc3eb15802c554a9c8581bf2117c4d3d06fbc57e0ba58f04cb1aaa47f"},
+    {file = "ruff-0.0.264-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:05ee163a046fc593d150179d23f4af447fb82f3e59cd34e031ea0868c65bb8e8"},
+    {file = "ruff-0.0.264-py3-none-musllinux_1_2_i686.whl", hash = "sha256:484e395d1984ab9e1e66bd42e7a5192decfee86998d07d36ee50b2fadccc8734"},
+    {file = "ruff-0.0.264-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:67326fdc9ac0a1b13e229c6e24e8d115863c52cd710faaaaa588851535281d6c"},
+    {file = "ruff-0.0.264-py3-none-win32.whl", hash = "sha256:5a8658ebcc37d62f72840cbdf564171c1a2b6831db482b4d917962541a2f4a44"},
+    {file = "ruff-0.0.264-py3-none-win_amd64.whl", hash = "sha256:068a82a29d80848a56e3d9d4308e6e0ca8b2ecdaf5ac342a292545a59b7f2c21"},
+    {file = "ruff-0.0.264-py3-none-win_arm64.whl", hash = "sha256:3e2c38449548e122f2612843a7c04e22b4fd491656955c57b8cb05df11639ad6"},
+    {file = "ruff-0.0.264.tar.gz", hash = "sha256:8fcd4b693ca1374eb7a5796581c90689f884f98f388740d94f0702fd30f8f78f"},
+]
+
+[[package]]
+name = "scipy"
+version = "1.11.4"
+description = "Fundamental algorithms for scientific computing in Python"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "scipy-1.11.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc9a714581f561af0848e6b69947fda0614915f072dfd14142ed1bfe1b806710"},
+    {file = "scipy-1.11.4-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:cf00bd2b1b0211888d4dc75656c0412213a8b25e80d73898083f402b50f47e41"},
+    {file = "scipy-1.11.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9999c008ccf00e8fbcce1236f85ade5c569d13144f77a1946bef8863e8f6eb4"},
+    {file = "scipy-1.11.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:933baf588daa8dc9a92c20a0be32f56d43faf3d1a60ab11b3f08c356430f6e56"},
+    {file = "scipy-1.11.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8fce70f39076a5aa62e92e69a7f62349f9574d8405c0a5de6ed3ef72de07f446"},
+    {file = "scipy-1.11.4-cp310-cp310-win_amd64.whl", hash = "sha256:6550466fbeec7453d7465e74d4f4b19f905642c89a7525571ee91dd7adabb5a3"},
+    {file = "scipy-1.11.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f313b39a7e94f296025e3cffc2c567618174c0b1dde173960cf23808f9fae4be"},
+    {file = "scipy-1.11.4-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:1b7c3dca977f30a739e0409fb001056484661cb2541a01aba0bb0029f7b68db8"},
+    {file = "scipy-1.11.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00150c5eae7b610c32589dda259eacc7c4f1665aedf25d921907f4d08a951b1c"},
+    {file = "scipy-1.11.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:530f9ad26440e85766509dbf78edcfe13ffd0ab7fec2560ee5c36ff74d6269ff"},
+    {file = "scipy-1.11.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5e347b14fe01003d3b78e196e84bd3f48ffe4c8a7b8a1afbcb8f5505cb710993"},
+    {file = "scipy-1.11.4-cp311-cp311-win_amd64.whl", hash = "sha256:acf8ed278cc03f5aff035e69cb511741e0418681d25fbbb86ca65429c4f4d9cd"},
+    {file = "scipy-1.11.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:028eccd22e654b3ea01ee63705681ee79933652b2d8f873e7949898dda6d11b6"},
+    {file = "scipy-1.11.4-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2c6ff6ef9cc27f9b3db93a6f8b38f97387e6e0591600369a297a50a8e96e835d"},
+    {file = "scipy-1.11.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b030c6674b9230d37c5c60ab456e2cf12f6784596d15ce8da9365e70896effc4"},
+    {file = "scipy-1.11.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad669df80528aeca5f557712102538f4f37e503f0c5b9541655016dd0932ca79"},
+    {file = "scipy-1.11.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce7fff2e23ab2cc81ff452a9444c215c28e6305f396b2ba88343a567feec9660"},
+    {file = "scipy-1.11.4-cp312-cp312-win_amd64.whl", hash = "sha256:36750b7733d960d7994888f0d148d31ea3017ac15eef664194b4ef68d36a4a97"},
+    {file = "scipy-1.11.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e619aba2df228a9b34718efb023966da781e89dd3d21637b27f2e54db0410d7"},
+    {file = "scipy-1.11.4-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:f3cd9e7b3c2c1ec26364856f9fbe78695fe631150f94cd1c22228456404cf1ec"},
+    {file = "scipy-1.11.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d10e45a6c50211fe256da61a11c34927c68f277e03138777bdebedd933712fea"},
+    {file = "scipy-1.11.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91af76a68eeae0064887a48e25c4e616fa519fa0d38602eda7e0f97d65d57937"},
+    {file = "scipy-1.11.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6df1468153a31cf55ed5ed39647279beb9cfb5d3f84369453b49e4b8502394fd"},
+    {file = "scipy-1.11.4-cp39-cp39-win_amd64.whl", hash = "sha256:ee410e6de8f88fd5cf6eadd73c135020bfbbbdfcd0f6162c36a7638a1ea8cc65"},
+    {file = "scipy-1.11.4.tar.gz", hash = "sha256:90a2b78e7f5733b9de748f589f09225013685f9b218275257f8a8168ededaeaa"},
+]
+
+[package.dependencies]
+numpy = ">=1.21.6,<1.28.0"
+
+[package.extras]
+dev = ["click", "cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"]
+doc = ["jupytext", "matplotlib (>2)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"]
+test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
+
+[[package]]
+name = "secretstorage"
+version = "3.3.3"
+description = "Python bindings to FreeDesktop.org Secret Service API"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "SecretStorage-3.3.3-py3-none-any.whl", hash = "sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99"},
+    {file = "SecretStorage-3.3.3.tar.gz", hash = "sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77"},
+]
+
+[package.dependencies]
+cryptography = ">=2.0"
+jeepney = ">=0.6"
+
+[[package]]
+name = "selenium"
+version = "4.15.2"
+description = ""
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "selenium-4.15.2-py3-none-any.whl", hash = "sha256:9e82cd1ac647fb73cf0d4a6e280284102aaa3c9d94f0fa6e6cc4b5db6a30afbf"},
+    {file = "selenium-4.15.2.tar.gz", hash = "sha256:22eab5a1724c73d51b240a69ca702997b717eee4ba1f6065bf5d6b44dba01d48"},
+]
+
+[package.dependencies]
+certifi = ">=2021.10.8"
+trio = ">=0.17,<1.0"
+trio-websocket = ">=0.9,<1.0"
+urllib3 = {version = ">=1.26,<3", extras = ["socks"]}
+
+[[package]]
+name = "semantic-version"
+version = "2.10.0"
+description = "A library implementing the 'SemVer' scheme."
+optional = false
+python-versions = ">=2.7"
+files = [
+    {file = "semantic_version-2.10.0-py2.py3-none-any.whl", hash = "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177"},
+    {file = "semantic_version-2.10.0.tar.gz", hash = "sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c"},
+]
+
+[package.extras]
+dev = ["Django (>=1.11)", "check-manifest", "colorama (<=0.4.1)", "coverage", "flake8", "nose2", "readme-renderer (<25.0)", "tox", "wheel", "zest.releaser[recommended]"]
+doc = ["Sphinx", "sphinx-rtd-theme"]
+
+[[package]]
+name = "setuptools"
+version = "69.0.2"
+description = "Easily download, build, install, upgrade, and uninstall Python packages"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"},
+    {file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"},
+]
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
+testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
+
+[[package]]
+name = "six"
+version = "1.16.0"
+description = "Python 2 and 3 compatibility utilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+    {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
+    {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+]
+
+[[package]]
+name = "sniffio"
+version = "1.3.0"
+description = "Sniff out which async library your code is running under"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"},
+    {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"},
+]
+
+[[package]]
+name = "snowballstemmer"
+version = "2.2.0"
+description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
+optional = false
+python-versions = "*"
+files = [
+    {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
+    {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
+]
+
+[[package]]
+name = "sortedcontainers"
+version = "2.4.0"
+description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set"
+optional = false
+python-versions = "*"
+files = [
+    {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"},
+    {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"},
+]
+
+[[package]]
+name = "soupsieve"
+version = "2.5"
+description = "A modern CSS selector implementation for Beautiful Soup."
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"},
+    {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"},
+]
+
+[[package]]
+name = "sphinx"
+version = "5.3.0"
+description = "Python documentation generator"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "Sphinx-5.3.0.tar.gz", hash = "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5"},
+    {file = "sphinx-5.3.0-py3-none-any.whl", hash = "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d"},
+]
+
+[package.dependencies]
+alabaster = ">=0.7,<0.8"
+babel = ">=2.9"
+colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
+docutils = ">=0.14,<0.20"
+imagesize = ">=1.3"
+importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""}
+Jinja2 = ">=3.0"
+packaging = ">=21.0"
+Pygments = ">=2.12"
+requests = ">=2.5.0"
+snowballstemmer = ">=2.0"
+sphinxcontrib-applehelp = "*"
+sphinxcontrib-devhelp = "*"
+sphinxcontrib-htmlhelp = ">=2.0.0"
+sphinxcontrib-jsmath = "*"
+sphinxcontrib-qthelp = "*"
+sphinxcontrib-serializinghtml = ">=1.1.5"
+
+[package.extras]
+docs = ["sphinxcontrib-websupport"]
+lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"]
+test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"]
+
+[[package]]
+name = "sphinx-autodoc-typehints"
+version = "1.23.0"
+description = "Type hints (PEP 484) support for the Sphinx autodoc extension"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "sphinx_autodoc_typehints-1.23.0-py3-none-any.whl", hash = "sha256:ac099057e66b09e51b698058ba7dd76e57e1fe696cd91b54e121d3dad188f91d"},
+    {file = "sphinx_autodoc_typehints-1.23.0.tar.gz", hash = "sha256:5d44e2996633cdada499b6d27a496ddf9dbc95dd1f0f09f7b37940249e61f6e9"},
+]
+
+[package.dependencies]
+sphinx = ">=5.3"
+
+[package.extras]
+docs = ["furo (>=2022.12.7)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23.4)"]
+testing = ["covdefaults (>=2.2.2)", "coverage (>=7.2.2)", "diff-cover (>=7.5)", "nptyping (>=2.5)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "sphobjinv (>=2.3.1)", "typing-extensions (>=4.5)"]
+type-comment = ["typed-ast (>=1.5.4)"]
+
+[[package]]
+name = "sphinx-autodocgen"
+version = "1.3"
+description = "Sphinx AutoDocGen extension"
+optional = false
+python-versions = ">=3.6, <4"
+files = [
+    {file = "sphinx_autodocgen-1.3-py2.py3-none-any.whl", hash = "sha256:d04f63b824b7a0c72c6d51127e24f03bd58322fabcc18ac9ba9b8200052280d0"},
+]
+
+[package.dependencies]
+sphinx = "*"
+
+[[package]]
+name = "sphinx-copybutton"
+version = "0.5.2"
+description = "Add a copy button to each of your code cells."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"},
+    {file = "sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e"},
+]
+
+[package.dependencies]
+sphinx = ">=1.8"
+
+[package.extras]
+code-style = ["pre-commit (==2.12.1)"]
+rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"]
+
+[[package]]
+name = "sphinx-rtd-theme"
+version = "1.3.0"
+description = "Read the Docs theme for Sphinx"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
+files = [
+    {file = "sphinx_rtd_theme-1.3.0-py2.py3-none-any.whl", hash = "sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0"},
+    {file = "sphinx_rtd_theme-1.3.0.tar.gz", hash = "sha256:590b030c7abb9cf038ec053b95e5380b5c70d61591eb0b552063fbe7c41f0931"},
+]
+
+[package.dependencies]
+docutils = "<0.19"
+sphinx = ">=1.6,<8"
+sphinxcontrib-jquery = ">=4,<5"
+
+[package.extras]
+dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"]
+
+[[package]]
+name = "sphinxcontrib-applehelp"
+version = "1.0.7"
+description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "sphinxcontrib_applehelp-1.0.7-py3-none-any.whl", hash = "sha256:094c4d56209d1734e7d252f6e0b3ccc090bd52ee56807a5d9315b19c122ab15d"},
+    {file = "sphinxcontrib_applehelp-1.0.7.tar.gz", hash = "sha256:39fdc8d762d33b01a7d8f026a3b7d71563ea3b72787d5f00ad8465bd9d6dfbfa"},
+]
+
+[package.dependencies]
+Sphinx = ">=5"
+
+[package.extras]
+lint = ["docutils-stubs", "flake8", "mypy"]
+test = ["pytest"]
+
+[[package]]
+name = "sphinxcontrib-devhelp"
+version = "1.0.5"
+description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "sphinxcontrib_devhelp-1.0.5-py3-none-any.whl", hash = "sha256:fe8009aed765188f08fcaadbb3ea0d90ce8ae2d76710b7e29ea7d047177dae2f"},
+    {file = "sphinxcontrib_devhelp-1.0.5.tar.gz", hash = "sha256:63b41e0d38207ca40ebbeabcf4d8e51f76c03e78cd61abe118cf4435c73d4212"},
+]
+
+[package.dependencies]
+Sphinx = ">=5"
+
+[package.extras]
+lint = ["docutils-stubs", "flake8", "mypy"]
+test = ["pytest"]
+
+[[package]]
+name = "sphinxcontrib-htmlhelp"
+version = "2.0.4"
+description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "sphinxcontrib_htmlhelp-2.0.4-py3-none-any.whl", hash = "sha256:8001661c077a73c29beaf4a79968d0726103c5605e27db92b9ebed8bab1359e9"},
+    {file = "sphinxcontrib_htmlhelp-2.0.4.tar.gz", hash = "sha256:6c26a118a05b76000738429b724a0568dbde5b72391a688577da08f11891092a"},
+]
+
+[package.dependencies]
+Sphinx = ">=5"
+
+[package.extras]
+lint = ["docutils-stubs", "flake8", "mypy"]
+test = ["html5lib", "pytest"]
+
+[[package]]
+name = "sphinxcontrib-jquery"
+version = "4.1"
+description = "Extension to include jQuery on newer Sphinx releases"
+optional = false
+python-versions = ">=2.7"
+files = [
+    {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"},
+    {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"},
+]
+
+[package.dependencies]
+Sphinx = ">=1.8"
+
+[[package]]
+name = "sphinxcontrib-jsmath"
+version = "1.0.1"
+description = "A sphinx extension which renders display math in HTML via JavaScript"
+optional = false
+python-versions = ">=3.5"
+files = [
+    {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"},
+    {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"},
+]
+
+[package.extras]
+test = ["flake8", "mypy", "pytest"]
+
+[[package]]
+name = "sphinxcontrib-qthelp"
+version = "1.0.6"
+description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "sphinxcontrib_qthelp-1.0.6-py3-none-any.whl", hash = "sha256:bf76886ee7470b934e363da7a954ea2825650013d367728588732c7350f49ea4"},
+    {file = "sphinxcontrib_qthelp-1.0.6.tar.gz", hash = "sha256:62b9d1a186ab7f5ee3356d906f648cacb7a6bdb94d201ee7adf26db55092982d"},
+]
+
+[package.dependencies]
+Sphinx = ">=5"
+
+[package.extras]
+lint = ["docutils-stubs", "flake8", "mypy"]
+test = ["pytest"]
+
+[[package]]
+name = "sphinxcontrib-serializinghtml"
+version = "1.1.9"
+description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "sphinxcontrib_serializinghtml-1.1.9-py3-none-any.whl", hash = "sha256:9b36e503703ff04f20e9675771df105e58aa029cfcbc23b8ed716019b7416ae1"},
+    {file = "sphinxcontrib_serializinghtml-1.1.9.tar.gz", hash = "sha256:0c64ff898339e1fac29abd2bf5f11078f3ec413cfe9c046d3120d7ca65530b54"},
+]
+
+[package.dependencies]
+Sphinx = ">=5"
+
+[package.extras]
+lint = ["docutils-stubs", "flake8", "mypy"]
+test = ["pytest"]
+
+[[package]]
+name = "sqlalchemy"
+version = "2.0.23"
+description = "Database Abstraction Library"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "SQLAlchemy-2.0.23-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:638c2c0b6b4661a4fd264f6fb804eccd392745c5887f9317feb64bb7cb03b3ea"},
+    {file = "SQLAlchemy-2.0.23-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3b5036aa326dc2df50cba3c958e29b291a80f604b1afa4c8ce73e78e1c9f01d"},
+    {file = "SQLAlchemy-2.0.23-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:787af80107fb691934a01889ca8f82a44adedbf5ef3d6ad7d0f0b9ac557e0c34"},
+    {file = "SQLAlchemy-2.0.23-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c14eba45983d2f48f7546bb32b47937ee2cafae353646295f0e99f35b14286ab"},
+    {file = "SQLAlchemy-2.0.23-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0666031df46b9badba9bed00092a1ffa3aa063a5e68fa244acd9f08070e936d3"},
+    {file = "SQLAlchemy-2.0.23-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:89a01238fcb9a8af118eaad3ffcc5dedaacbd429dc6fdc43fe430d3a941ff965"},
+    {file = "SQLAlchemy-2.0.23-cp310-cp310-win32.whl", hash = "sha256:cabafc7837b6cec61c0e1e5c6d14ef250b675fa9c3060ed8a7e38653bd732ff8"},
+    {file = "SQLAlchemy-2.0.23-cp310-cp310-win_amd64.whl", hash = "sha256:87a3d6b53c39cd173990de2f5f4b83431d534a74f0e2f88bd16eabb5667e65c6"},
+    {file = "SQLAlchemy-2.0.23-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d5578e6863eeb998980c212a39106ea139bdc0b3f73291b96e27c929c90cd8e1"},
+    {file = "SQLAlchemy-2.0.23-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62d9e964870ea5ade4bc870ac4004c456efe75fb50404c03c5fd61f8bc669a72"},
+    {file = "SQLAlchemy-2.0.23-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c80c38bd2ea35b97cbf7c21aeb129dcbebbf344ee01a7141016ab7b851464f8e"},
+    {file = "SQLAlchemy-2.0.23-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75eefe09e98043cff2fb8af9796e20747ae870c903dc61d41b0c2e55128f958d"},
+    {file = "SQLAlchemy-2.0.23-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd45a5b6c68357578263d74daab6ff9439517f87da63442d244f9f23df56138d"},
+    {file = "SQLAlchemy-2.0.23-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a86cb7063e2c9fb8e774f77fbf8475516d270a3e989da55fa05d08089d77f8c4"},
+    {file = "SQLAlchemy-2.0.23-cp311-cp311-win32.whl", hash = "sha256:b41f5d65b54cdf4934ecede2f41b9c60c9f785620416e8e6c48349ab18643855"},
+    {file = "SQLAlchemy-2.0.23-cp311-cp311-win_amd64.whl", hash = "sha256:9ca922f305d67605668e93991aaf2c12239c78207bca3b891cd51a4515c72e22"},
+    {file = "SQLAlchemy-2.0.23-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d0f7fb0c7527c41fa6fcae2be537ac137f636a41b4c5a4c58914541e2f436b45"},
+    {file = "SQLAlchemy-2.0.23-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7c424983ab447dab126c39d3ce3be5bee95700783204a72549c3dceffe0fc8f4"},
+    {file = "SQLAlchemy-2.0.23-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f508ba8f89e0a5ecdfd3761f82dda2a3d7b678a626967608f4273e0dba8f07ac"},
+    {file = "SQLAlchemy-2.0.23-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6463aa765cf02b9247e38b35853923edbf2f6fd1963df88706bc1d02410a5577"},
+    {file = "SQLAlchemy-2.0.23-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e599a51acf3cc4d31d1a0cf248d8f8d863b6386d2b6782c5074427ebb7803bda"},
+    {file = "SQLAlchemy-2.0.23-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fd54601ef9cc455a0c61e5245f690c8a3ad67ddb03d3b91c361d076def0b4c60"},
+    {file = "SQLAlchemy-2.0.23-cp312-cp312-win32.whl", hash = "sha256:42d0b0290a8fb0165ea2c2781ae66e95cca6e27a2fbe1016ff8db3112ac1e846"},
+    {file = "SQLAlchemy-2.0.23-cp312-cp312-win_amd64.whl", hash = "sha256:227135ef1e48165f37590b8bfc44ed7ff4c074bf04dc8d6f8e7f1c14a94aa6ca"},
+    {file = "SQLAlchemy-2.0.23-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:14aebfe28b99f24f8a4c1346c48bc3d63705b1f919a24c27471136d2f219f02d"},
+    {file = "SQLAlchemy-2.0.23-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e983fa42164577d073778d06d2cc5d020322425a509a08119bdcee70ad856bf"},
+    {file = "SQLAlchemy-2.0.23-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e0dc9031baa46ad0dd5a269cb7a92a73284d1309228be1d5935dac8fb3cae24"},
+    {file = "SQLAlchemy-2.0.23-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5f94aeb99f43729960638e7468d4688f6efccb837a858b34574e01143cf11f89"},
+    {file = "SQLAlchemy-2.0.23-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:63bfc3acc970776036f6d1d0e65faa7473be9f3135d37a463c5eba5efcdb24c8"},
+    {file = "SQLAlchemy-2.0.23-cp37-cp37m-win32.whl", hash = "sha256:f48ed89dd11c3c586f45e9eec1e437b355b3b6f6884ea4a4c3111a3358fd0c18"},
+    {file = "SQLAlchemy-2.0.23-cp37-cp37m-win_amd64.whl", hash = "sha256:1e018aba8363adb0599e745af245306cb8c46b9ad0a6fc0a86745b6ff7d940fc"},
+    {file = "SQLAlchemy-2.0.23-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:64ac935a90bc479fee77f9463f298943b0e60005fe5de2aa654d9cdef46c54df"},
+    {file = "SQLAlchemy-2.0.23-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c4722f3bc3c1c2fcc3702dbe0016ba31148dd6efcd2a2fd33c1b4897c6a19693"},
+    {file = "SQLAlchemy-2.0.23-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4af79c06825e2836de21439cb2a6ce22b2ca129bad74f359bddd173f39582bf5"},
+    {file = "SQLAlchemy-2.0.23-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:683ef58ca8eea4747737a1c35c11372ffeb84578d3aab8f3e10b1d13d66f2bc4"},
+    {file = "SQLAlchemy-2.0.23-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d4041ad05b35f1f4da481f6b811b4af2f29e83af253bf37c3c4582b2c68934ab"},
+    {file = "SQLAlchemy-2.0.23-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aeb397de65a0a62f14c257f36a726945a7f7bb60253462e8602d9b97b5cbe204"},
+    {file = "SQLAlchemy-2.0.23-cp38-cp38-win32.whl", hash = "sha256:42ede90148b73fe4ab4a089f3126b2cfae8cfefc955c8174d697bb46210c8306"},
+    {file = "SQLAlchemy-2.0.23-cp38-cp38-win_amd64.whl", hash = "sha256:964971b52daab357d2c0875825e36584d58f536e920f2968df8d581054eada4b"},
+    {file = "SQLAlchemy-2.0.23-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:616fe7bcff0a05098f64b4478b78ec2dfa03225c23734d83d6c169eb41a93e55"},
+    {file = "SQLAlchemy-2.0.23-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0e680527245895aba86afbd5bef6c316831c02aa988d1aad83c47ffe92655e74"},
+    {file = "SQLAlchemy-2.0.23-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9585b646ffb048c0250acc7dad92536591ffe35dba624bb8fd9b471e25212a35"},
+    {file = "SQLAlchemy-2.0.23-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4895a63e2c271ffc7a81ea424b94060f7b3b03b4ea0cd58ab5bb676ed02f4221"},
+    {file = "SQLAlchemy-2.0.23-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cc1d21576f958c42d9aec68eba5c1a7d715e5fc07825a629015fe8e3b0657fb0"},
+    {file = "SQLAlchemy-2.0.23-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:967c0b71156f793e6662dd839da54f884631755275ed71f1539c95bbada9aaab"},
+    {file = "SQLAlchemy-2.0.23-cp39-cp39-win32.whl", hash = "sha256:0a8c6aa506893e25a04233bc721c6b6cf844bafd7250535abb56cb6cc1368884"},
+    {file = "SQLAlchemy-2.0.23-cp39-cp39-win_amd64.whl", hash = "sha256:f3420d00d2cb42432c1d0e44540ae83185ccbbc67a6054dcc8ab5387add6620b"},
+    {file = "SQLAlchemy-2.0.23-py3-none-any.whl", hash = "sha256:31952bbc527d633b9479f5f81e8b9dfada00b91d6baba021a869095f1a97006d"},
+    {file = "SQLAlchemy-2.0.23.tar.gz", hash = "sha256:c1bda93cbbe4aa2aa0aa8655c5aeda505cd219ff3e8da91d1d329e143e4aff69"},
+]
+
+[package.dependencies]
+greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""}
+typing-extensions = ">=4.2.0"
+
+[package.extras]
+aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"]
+aioodbc = ["aioodbc", "greenlet (!=0.4.17)"]
+aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"]
+asyncio = ["greenlet (!=0.4.17)"]
+asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"]
+mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"]
+mssql = ["pyodbc"]
+mssql-pymssql = ["pymssql"]
+mssql-pyodbc = ["pyodbc"]
+mypy = ["mypy (>=0.910)"]
+mysql = ["mysqlclient (>=1.4.0)"]
+mysql-connector = ["mysql-connector-python"]
+oracle = ["cx-oracle (>=8)"]
+oracle-oracledb = ["oracledb (>=1.0.1)"]
+postgresql = ["psycopg2 (>=2.7)"]
+postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"]
+postgresql-pg8000 = ["pg8000 (>=1.29.1)"]
+postgresql-psycopg = ["psycopg (>=3.0.7)"]
+postgresql-psycopg2binary = ["psycopg2-binary"]
+postgresql-psycopg2cffi = ["psycopg2cffi"]
+postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"]
+pymysql = ["pymysql"]
+sqlcipher = ["sqlcipher3-binary"]
+
+[[package]]
+name = "stack-data"
+version = "0.6.3"
+description = "Extract data from python stack frames and tracebacks for informative displays"
+optional = false
+python-versions = "*"
+files = [
+    {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"},
+    {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"},
+]
+
+[package.dependencies]
+asttokens = ">=2.1.0"
+executing = ">=1.2.0"
+pure-eval = "*"
+
+[package.extras]
+tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
+
+[[package]]
+name = "strictyaml"
+version = "1.7.3"
+description = "Strict, typed YAML parser"
+optional = false
+python-versions = ">=3.7.0"
+files = [
+    {file = "strictyaml-1.7.3-py3-none-any.whl", hash = "sha256:fb5c8a4edb43bebb765959e420f9b3978d7f1af88c80606c03fb420888f5d1c7"},
+    {file = "strictyaml-1.7.3.tar.gz", hash = "sha256:22f854a5fcab42b5ddba8030a0e4be51ca89af0267961c8d6cfa86395586c407"},
+]
+
+[package.dependencies]
+python-dateutil = ">=2.6.0"
+
+[[package]]
+name = "tabulate"
+version = "0.9.0"
+description = "Pretty-print tabular data"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"},
+    {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"},
+]
+
+[package.extras]
+widechars = ["wcwidth"]
+
+[[package]]
+name = "toml"
+version = "0.10.2"
+description = "Python Library for Tom's Obvious, Minimal Language"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+    {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
+    {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
+]
+
+[[package]]
+name = "tomli"
+version = "2.0.1"
+description = "A lil' TOML parser"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+    {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+]
+
+[[package]]
+name = "tornado"
+version = "6.4"
+description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
+optional = false
+python-versions = ">= 3.8"
+files = [
+    {file = "tornado-6.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0"},
+    {file = "tornado-6.4-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263"},
+    {file = "tornado-6.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e"},
+    {file = "tornado-6.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579"},
+    {file = "tornado-6.4-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212"},
+    {file = "tornado-6.4-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2"},
+    {file = "tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78"},
+    {file = "tornado-6.4-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f"},
+    {file = "tornado-6.4-cp38-abi3-win32.whl", hash = "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052"},
+    {file = "tornado-6.4-cp38-abi3-win_amd64.whl", hash = "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63"},
+    {file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"},
+]
+
+[[package]]
+name = "towncrier"
+version = "23.11.0"
+description = "Building newsfiles for your project."
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "towncrier-23.11.0-py3-none-any.whl", hash = "sha256:2e519ca619426d189e3c98c99558fe8be50c9ced13ea1fc20a4a353a95d2ded7"},
+    {file = "towncrier-23.11.0.tar.gz", hash = "sha256:13937c247e3f8ae20ac44d895cf5f96a60ad46cfdcc1671759530d7837d9ee5d"},
+]
+
+[package.dependencies]
+click = "*"
+importlib-resources = {version = ">=5", markers = "python_version < \"3.10\""}
+incremental = "*"
+jinja2 = "*"
+tomli = {version = "*", markers = "python_version < \"3.11\""}
+
+[package.extras]
+dev = ["furo", "packaging", "sphinx (>=5)", "twisted"]
+
+[[package]]
+name = "tqdm"
+version = "4.66.1"
+description = "Fast, Extensible Progress Meter"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"},
+    {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[package.extras]
+dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"]
+notebook = ["ipywidgets (>=6)"]
+slack = ["slack-sdk"]
+telegram = ["requests"]
+
+[[package]]
+name = "traitlets"
+version = "5.14.0"
+description = "Traitlets Python configuration system"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "traitlets-5.14.0-py3-none-any.whl", hash = "sha256:f14949d23829023013c47df20b4a76ccd1a85effb786dc060f34de7948361b33"},
+    {file = "traitlets-5.14.0.tar.gz", hash = "sha256:fcdaa8ac49c04dfa0ed3ee3384ef6dfdb5d6f3741502be247279407679296772"},
+]
+
+[package.extras]
+docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"]
+test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"]
+
+[[package]]
+name = "treelib"
+version = "1.7.0"
+description = "A Python implementation of tree structure."
+optional = false
+python-versions = "*"
+files = [
+    {file = "treelib-1.7.0-py3-none-any.whl", hash = "sha256:c37795eaba19f73f3e1a905ef3f4f0cab660dc7617126e8ae99391e25c755416"},
+    {file = "treelib-1.7.0.tar.gz", hash = "sha256:9bff1af416b9e642a6cd0e0431d15edf26a24b8d0c8ae68afbd3801b5e30fb61"},
+]
+
+[package.dependencies]
+six = "*"
+
+[[package]]
+name = "trio"
+version = "0.23.1"
+description = "A friendly Python library for async concurrency and I/O"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "trio-0.23.1-py3-none-any.whl", hash = "sha256:bb4abb3f4af23f96679e7c8cdabb8b234520f2498550d2cf63ebfd95f2ce27fe"},
+    {file = "trio-0.23.1.tar.gz", hash = "sha256:16f89f7dcc8f7b9dcdec1fcd863e0c039af6d0f9a22f8dfd56f75d75ec73fd48"},
+]
+
+[package.dependencies]
+attrs = ">=20.1.0"
+cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""}
+exceptiongroup = {version = ">=1.0.0rc9", markers = "python_version < \"3.11\""}
+idna = "*"
+outcome = "*"
+sniffio = ">=1.3.0"
+sortedcontainers = "*"
+
+[[package]]
+name = "trio-websocket"
+version = "0.11.1"
+description = "WebSocket library for Trio"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "trio-websocket-0.11.1.tar.gz", hash = "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f"},
+    {file = "trio_websocket-0.11.1-py3-none-any.whl", hash = "sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638"},
+]
+
+[package.dependencies]
+exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
+trio = ">=0.11"
+wsproto = ">=0.14"
+
+[[package]]
+name = "typing-extensions"
+version = "4.8.0"
+description = "Backported and Experimental Type Hints for Python 3.8+"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"},
+    {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"},
+]
+
+[[package]]
+name = "tzdata"
+version = "2023.3"
+description = "Provider of IANA time zone data"
+optional = false
+python-versions = ">=2"
+files = [
+    {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"},
+    {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"},
+]
+
+[[package]]
+name = "unfccc-di-api"
+version = "4.0.0"
+description = "Python wrapper around the Flexible Query API of the UNFCCC."
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "unfccc_di_api-4.0.0-py3-none-any.whl", hash = "sha256:986ea2e07981dbd3af5ac5ceda36d5142d69eac929531c97b55ad1015fa5d182"},
+    {file = "unfccc_di_api-4.0.0.tar.gz", hash = "sha256:5ac6c4c81175c7a2c242724bf173040ce870dcf593b156f07aa02a8c05d96d79"},
+]
+
+[package.dependencies]
+pandas = "*"
+pooch = "*"
+pyarrow = "*"
+requests = "*"
+treelib = "*"
+
+[package.extras]
+dev = ["Sphinx (>=6)", "build", "coverage", "flake8", "ipykernel", "nbsphinx", "pip", "pre-commit", "pytest", "pytest-runner", "sphinx-rtd-theme", "tbump", "tox", "twine", "watchdog", "wheel"]
+test = ["pytest"]
+
+[[package]]
+name = "urllib3"
+version = "2.1.0"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"},
+    {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"},
+]
+
+[package.dependencies]
+pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""}
+
+[package.extras]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
+socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
+zstd = ["zstandard (>=0.18.0)"]
+
+[[package]]
+name = "virtualenv"
+version = "20.25.0"
+description = "Virtual Python Environment builder"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"},
+    {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"},
+]
+
+[package.dependencies]
+distlib = ">=0.3.7,<1"
+filelock = ">=3.12.2,<4"
+platformdirs = ">=3.9.1,<5"
+
+[package.extras]
+docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
+test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
+
+[[package]]
+name = "wcwidth"
+version = "0.2.12"
+description = "Measures the displayed width of unicode strings in a terminal"
+optional = false
+python-versions = "*"
+files = [
+    {file = "wcwidth-0.2.12-py2.py3-none-any.whl", hash = "sha256:f26ec43d96c8cbfed76a5075dac87680124fa84e0855195a6184da9c187f133c"},
+    {file = "wcwidth-0.2.12.tar.gz", hash = "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02"},
+]
+
+[[package]]
+name = "win32-setctime"
+version = "1.1.0"
+description = "A small Python utility to set file creation time on Windows"
+optional = false
+python-versions = ">=3.5"
+files = [
+    {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"},
+    {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"},
+]
+
+[package.extras]
+dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"]
+
+[[package]]
+name = "wsproto"
+version = "1.2.0"
+description = "WebSockets state-machine based protocol implementation"
+optional = false
+python-versions = ">=3.7.0"
+files = [
+    {file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"},
+    {file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"},
+]
+
+[package.dependencies]
+h11 = ">=0.9.0,<1"
+
+[[package]]
+name = "xarray"
+version = "2023.11.0"
+description = "N-D labeled arrays and datasets in Python"
+optional = false
+python-versions = ">=3.9"
+files = [
+    {file = "xarray-2023.11.0-py3-none-any.whl", hash = "sha256:933b5101e965120ed58e29525667ab34aafcea1886c236ade72a34d7bb465d9c"},
+    {file = "xarray-2023.11.0.tar.gz", hash = "sha256:9a45e10741844b5f948d8e1e768b460df7e90696d18e2eff2c1d47f5d9d50252"},
+]
+
+[package.dependencies]
+numpy = ">=1.22"
+packaging = ">=21.3"
+pandas = ">=1.4"
+
+[package.extras]
+accel = ["bottleneck", "flox", "numbagg", "opt-einsum", "scipy"]
+complete = ["xarray[accel,io,parallel,viz]"]
+io = ["cftime", "fsspec", "h5netcdf", "netCDF4", "pooch", "pydap", "scipy", "zarr"]
+parallel = ["dask[complete]"]
+viz = ["matplotlib", "nc-time-axis", "seaborn"]
+
+[[package]]
+name = "zipp"
+version = "3.17.0"
+description = "Backport of pathlib-compatible object wrapper for zip files"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"},
+    {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"},
+]
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
+
+[extras]
+plots = ["matplotlib"]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.9"
+content-hash = "8043af104d30423894a6db97a68468e72fe0530b735247ca8d19b81292ece705"

+ 214 - 7
pyproject.toml

@@ -1,11 +1,218 @@
+[tool.poetry]
+name = "unfccc-ghg-data"
+version = "0.1.0"
+description = "Reading country greenhouse gas data submitted to the United Nations Framework Convention on Climate Change (UNFCCC)in different submissions and formats and providing it in a standadized nc and csv format compatible with primap2. Data are read using different methods from APIs, xlsx and csv files as well as pdf files."
+authors = ["Johannes Gütschow <mail@johannes-guetschow.de>"]
+readme = "README.md"
+packages = [{include = "unfccc_ghg_data", from = "src"}]
+
+[tool.poetry.dependencies]
+python = "^3.9"
+matplotlib = { version = "^3.7.1", optional = true }
+doit = "^0.36.0"
+primap2 = "^0.9.8"
+pycountry = "^22.3.5"
+datalad = "^0.19.3"
+treelib = "^1.7.0"
+camelot-py = "^0.11.0"
+selenium = "^4.15.2"
+bs4 = "^0.0.1"
+requests = "^2.31.0"
+opencv-python = "^4.8.1.78"
+unfccc-di-api = "^4.0.0"
+
+[tool.poetry.extras]
+plots = ["matplotlib"]
+
+[tool.poetry.group.tests.dependencies]
+pytest = "^7.3.1"
+
+[tool.poetry.group.docs.dependencies]
+myst-nb = "^0.17.0"
+sphinx-rtd-theme = "^1.2.0"
+sphinx-autodoc-typehints = "^1.23.0"
+sphinx-autodocgen = "^1.3"
+jupytext = "^1.14.5"
+sphinx-copybutton = "^0.5.2"
+
+[tool.poetry.group.dev.dependencies]
+pytest-cov = "^4.0.0"
+coverage = "^7.2.0"
+black = "23.3.0"
+blackdoc = "0.3.8"
+mypy = "^1.2.0"
+ruff = "0.0.264"
+pre-commit = "^3.3.1"
+towncrier = "^23.6.0"
+liccheck = "^0.9.1"
+
 [build-system]
 [build-system]
-requires = [
-    "setuptools>=42",
-    "wheel",
-    "setuptools_scm[toml]>=3.4"
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
+
+[tool.coverage.run]
+source = ["src"]
+branch = true
+
+[tool.coverage.report]
+fail_under = 95
+skip_empty = true
+show_missing = true
+# Regexes for lines to exclude from consideration in addition to the defaults
+exclude_also = [
+    # Don't complain about missing type checking code:
+    "if TYPE_CHECKING",
 ]
 ]
-build-backend = "setuptools.build_meta"
 
 
-[tool.black]
-line-length = 88
+[tool.mypy]
+strict = true
+# prevent unimported libraries silently being treated as Any
+disallow_any_unimported = true
+# show error codes on failure with context
+show_error_codes = true
+show_error_context = true
+# warn if code can't be reached
+warn_unreachable = true
+# importing following uses default settings
+follow_imports = "normal"
 
 
+[tool.jupytext]
+formats = "ipynb,py:percent"
+
+[tool.pytest.ini_options]
+addopts = [
+    "--import-mode=importlib",
+]
+
+[tool.ruff]
+src = ["src"]
+target-version = "py39"
+select = [
+    "E",  # pycodestyle error
+    "W",  # pycodestyle warning
+    "F",  # pyflakes
+    "I",  # isort
+    "D",  # pydocstyle
+    "PL",  # pylint
+    "TRY",  # tryceratops
+    "NPY",  # numpy rules
+    "RUF",  # ruff specifics
+    "UP",  # pyupgrade
+    "S",  # flake8-bandit
+    # pandas support via pandas-vet. In some cases we will want to disable
+    # this because it can lead to too many false positives.
+    "PD",
+]
+unfixable = [
+    "PD002",  # Disable autofix for inplace as this often introduces bugs
+]
+ignore = [
+    "D200",  # One-line docstring should fit on one line with quotes
+    "D400",  # First line should end with a period
+]
+# Provide some leeway for long docstring, this is otherwise handled by black
+line-length = 110
+
+[tool.ruff.per-file-ignores]
+"test*.py" = [
+    "D",  # Documentation not needed in tests
+    "S101",  # S101 Use of `assert` detected
+    "PLR2004" # Magic value used in comparison
+]
+"docs/source/notebooks/*" = [
+    "D100",  # Missing docstring at the top of file
+    "E402",  # Module level import not at top of file
+    "S101",  # Use of `assert` detected
+]
+"scripts/*" = [
+    "S101" # S101 Use of `assert` detected
+]
+
+[tool.ruff.isort]
+known-first-party = ["src"]
+
+[tool.ruff.pydocstyle]
+convention = "numpy"
+
+[tool.towncrier]
+package = "unfccc-ghg-data"
+package_dir = "src"
+filename = "docs/source/changelog.md"
+directory = "changelog/"
+title_format = "## unfccc-ghg-data {version} ({project_date})"
+underlines = ["", "", ""]
+issue_format = "[#{issue}](https://github.com/JGuetschow/UNFCCC_non-AnnexI_data/pulls/{issue})"
+
+  [[tool.towncrier.type]]
+  directory = "breaking"
+  name = "Breaking Changes"
+  showcontent = true
+
+  [[tool.towncrier.type]]
+  directory = "deprecation"
+  name = "Deprecations"
+  showcontent = true
+
+  [[tool.towncrier.type]]
+  directory = "feature"
+  name = "Features"
+  showcontent = true
+
+  [[tool.towncrier.type]]
+  directory = "improvement"
+  name = "Improvements"
+  showcontent = true
+
+  [[tool.towncrier.type]]
+  directory = "fix"
+  name = "Bug Fixes"
+  showcontent = true
+
+  [[tool.towncrier.type]]
+  directory = "docs"
+  name = "Improved Documentation"
+  showcontent = true
+
+  [[tool.towncrier.type]]
+  directory = "trivial"
+  name = "Trivial/Internal Changes"
+  showcontent = false
+
+[tool.liccheck]
+authorized_licenses = [
+    "bsd",
+    "bsd license",
+    "BSD 3-Clause",
+    "CC0",
+    "apache",
+    "apache 2.0",
+    "apache software",
+    "apache software license",
+    "Apache License, Version 2.0",
+    "Historical Permission Notice and Disclaimer (HPND)",
+    "isc license",
+    "isc license (iscl)",
+    "gnu lgpl",
+    "lgpl with exceptions or zpl",
+    "LGPLv2+",
+    "GNU Lesser General Public License v2 (LGPLv2)",
+    "GNU Lesser General Public License v2 or later (LGPLv2+)",
+    "mit",
+    "mit license",
+    "Mozilla Public License 2.0 (MPL 2.0)",
+    "python software foundation",
+    "python software foundation license",
+    "zpl 2.1",
+]
+# This starting list is relatively conservative. Depending on the project, it
+# may make sense to move some of these into the authorized list
+unauthorized_licenses = [
+    "agpl",
+    "gnu agpl",
+    "gpl v3",
+    "gplv3",
+    "gpl v2",
+    "gplv2",
+    "gpl v1",
+    "gplv1",
+]

+ 0 - 1
requirements.txt

@@ -1 +0,0 @@
-.

+ 0 - 1
requirements_dev.txt

@@ -1 +0,0 @@
-.[dev]

+ 28 - 0
scripts/test-install.py

@@ -0,0 +1,28 @@
+"""
+Test that all of our modules can be imported
+
+Also test that associated constants are set correctly
+
+Thanks https://stackoverflow.com/a/25562415/10473080
+"""
+import importlib
+import pkgutil
+
+import unfccc_ghg_data
+
+
+def import_submodules(package_name):
+    """
+    Test import of submodules
+    """
+    package = importlib.import_module(package_name)
+
+    for _, name, is_pkg in pkgutil.walk_packages(package.__path__):
+        full_name = package.__name__ + "." + name
+        importlib.import_module(full_name)
+        if is_pkg:
+            import_submodules(full_name)
+
+
+import_submodules("unfccc_ghg_data")
+print(unfccc_ghg_data.__version__)

+ 0 - 79
setup.cfg

@@ -1,79 +0,0 @@
-[metadata]
-name = UNFCCC_GHG_data
-version = 0.2
-author = Johannes Gütschow
-author_email = mail@johannes-guetschow.de
-description = Tools to read GHG data submitted to the UNFCCC using various methods
-long_description = file: README.md
-long_description_content_type = text/md
-url = https://github.com/JGuetschow/UNFCCC_non-AnnexI_data
-#project_urls =
-classifiers =
-    Development Status :: 3 - Alpha
-    Intended Audience :: Science/Research
-    Topic :: Scientific/Engineering :: Atmospheric Science
-    License :: OSI Approved :: Apache Software License
-    Natural Language :: English
-    Programming Language :: Python :: 3
-    Programming Language :: Python :: 3.8
-    Programming Language :: Python :: 3.9
-    Programming Language :: Python :: 3.10
-license = Apache Software License 2.0
-license_file = LICENSE
-
-[options]
-packages =
-    UNFCCC_GHG_data
-    UNFCCC_GHG_data.UNFCCC_CRF_reader
-    UNFCCC_GHG_data.UNFCCC_CRF_reader.crf_specifications
-    UNFCCC_GHG_data.UNFCCC_reader
-    UNFCCC_GHG_data.UNFCCC_downloader
-    UNFCCC_GHG_data.UNFCCC_DI_reader
-    UNFCCC_GHG_data.helper
-#UNFCCC_GHG_data.datasets
-python_requires = >=3.8
-setup_requires =
-    setuptools_scm
-install_requires =
-    bs4
-    requests
-    pandas
-    selenium
-    primap2
-    countrynames
-    pycountry
-    datalad
-    treelib
-    camelot-py
-    opencv-python
-    ghostscript
-    unfccc_di_api >=4.0.0
-    dask
-
-[options.extras_require]
-dev =
-    pip
-    wheel
-    bs4
-    requests
-    pandas
-    selenium
-    primap2
-    countrynames
-    pycountry
-    datalad
-    treelib
-    camelot-py
-    opencv-python
-    ghostscript
-    ipykernel
-    jupyter
-    dask
-    ipympl
-    black
-
-
-[options.package_data]
-* =
-    *.csv
-    *.nc

+ 0 - 5
setup.py

@@ -1,5 +0,0 @@
-#!/usr/bin/env python
-
-import setuptools
-
-setuptools.setup()

+ 2 - 6
UNFCCC_GHG_data/__init__.py → src/unfccc_ghg_data/__init__.py

@@ -1,10 +1,6 @@
-####
+"""unfccc_ghg_data package"""
 
 
 from . import helper
 from . import helper
-from . import UNFCCC_reader
-from . import UNFCCC_CRF_reader
-from . import UNFCCC_DI_reader
-from . import UNFCCC_downloader
 
 
 __all__ = [
 __all__ = [
     "helper",
     "helper",
@@ -12,4 +8,4 @@ __all__ = [
     "UNFCCC_CRF_reader",
     "UNFCCC_CRF_reader",
     "UNFCCC_DI_reader",
     "UNFCCC_DI_reader",
     "UNFCCC_downloader"
     "UNFCCC_downloader"
-]
+]

+ 54 - 0
src/unfccc_ghg_data/helper/__init__.py

@@ -0,0 +1,54 @@
+"""
+helper functions and definitions
+
+helper functions and definitions used by the different readers and downloader in
+the unfccc_ghg_data package
+"""
+
+from .definitions import (
+    GWP_factors,
+    code_path,
+    custom_country_mapping,
+    custom_folders,
+    dataset_path,
+    dataset_path_UNFCCC,
+    downloaded_data_path,
+    downloaded_data_path_UNFCCC,
+    extracted_data_path,
+    extracted_data_path_UNFCCC,
+    gas_baskets,
+    legacy_data_path,
+    log_path,
+    root_path,
+)
+from .functions import (
+    convert_categories,
+    create_folder_mapping,
+    fix_rows,
+    get_country_code,
+    get_country_name,
+    process_data_for_country,
+)
+
+__all__ = [
+    "root_path",
+    "code_path",
+    "log_path",
+    "extracted_data_path",
+    "extracted_data_path_UNFCCC",
+    "legacy_data_path",
+    "downloaded_data_path",
+    "downloaded_data_path_UNFCCC",
+    "dataset_path",
+    "dataset_path_UNFCCC",
+    "custom_country_mapping",
+    "custom_folders",
+    "GWP_factors",
+    "gas_baskets",
+    "get_country_code",
+    "get_country_name",
+    "convert_categories",
+    "create_folder_mapping",
+    "process_data_for_country",
+    "fix_rows",
+]

+ 10 - 6
UNFCCC_GHG_data/helper/country_info.py → src/unfccc_ghg_data/helper/country_info.py

@@ -1,14 +1,18 @@
-# this script takes country as input (from doit) and
-# runs displays available submissions and datasets
+"""
+script to display information on country
+
+This script takes country as input (from doit) and displays available
+submissions and datasets both read and not read
+"""
 
 
 import argparse
 import argparse
-from UNFCCC_GHG_data.helper.functions import get_country_submissions
-from UNFCCC_GHG_data.helper.functions import get_country_datasets
+
+from unfccc_ghg_data.helper.functions import get_country_datasets, get_country_submissions
 
 
 # Find the right function and possible input and output files and
 # Find the right function and possible input and output files and
 # read the data using datalad run.
 # read the data using datalad run.
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
-parser.add_argument('--country', help='Country name or UNFCCC_GHG_data')
+parser.add_argument('--country', help='Country name or code')
 args = parser.parse_args()
 args = parser.parse_args()
 country = args.country
 country = args.country
 
 
@@ -19,4 +23,4 @@ print("")
 
 
 #print available datasets
 #print available datasets
 print("="*15 + " Available datasets " + "="*15)
 print("="*15 + " Available datasets " + "="*15)
-get_country_datasets(country, True)
+get_country_datasets(country, True)

+ 8 - 5
UNFCCC_GHG_data/helper/definitions.py → src/unfccc_ghg_data/helper/definitions.py

@@ -1,18 +1,21 @@
+"""definitions like folders, mappings etc."""
+
 import os
 import os
 from pathlib import Path
 from pathlib import Path
 
 
 
 
 def get_root_path() -> Path:
 def get_root_path() -> Path:
-    """ get the root_path from an environment variable """
+    """Get the root_path from an environment variable"""
     root_path_env = os.getenv('UNFCCC_GHG_ROOT_PATH', None)
     root_path_env = os.getenv('UNFCCC_GHG_ROOT_PATH', None)
     if root_path_env is None:
     if root_path_env is None:
-        raise ValueError('UNFCCC_GHG_ROOT_PATH environment variable needs to be set')
+        raise ValueError('UNFCCC_GHG_ROOT_PATH environment '
+                         'variable needs to be set') # noqa: TRY003
     else:
     else:
         root_path = Path(root_path_env).resolve()
         root_path = Path(root_path_env).resolve()
     return root_path
     return root_path
 
 
 root_path = get_root_path()
 root_path = get_root_path()
-code_path = root_path / "UNFCCC_GHG_data"
+code_path = root_path / "unfccc_ghg_data"
 log_path = root_path / "log"
 log_path = root_path / "log"
 extracted_data_path = root_path / "extracted_data"
 extracted_data_path = root_path / "extracted_data"
 extracted_data_path_UNFCCC = extracted_data_path / "UNFCCC"
 extracted_data_path_UNFCCC = extracted_data_path / "UNFCCC"
@@ -42,7 +45,7 @@ custom_folders = {
     'Bolivia_(Plurinational_State_of)': 'BOL',
     'Bolivia_(Plurinational_State_of)': 'BOL',
     'Türkiye': 'TUR',
     'Türkiye': 'TUR',
     'Iran_(Islamic_Republic_of)': 'IRN',
     'Iran_(Islamic_Republic_of)': 'IRN',
-    'Côte_dIvoire': 'CIV',
+    'Côte_d`Ivoire': 'CIV',
     'Democratic_Republic_of_the_Congo': "COD",
     'Democratic_Republic_of_the_Congo': "COD",
     'European_Union': 'EUA',
     'European_Union': 'EUA',
     'Taiwan': 'TWN',
     'Taiwan': 'TWN',
@@ -154,4 +157,4 @@ gas_baskets = {
                             'PFCS (AR5GWP100)'],
                             'PFCS (AR5GWP100)'],
     'KYOTOGHG (AR6GWP100)': ['CO2', 'CH4', 'N2O', 'SF6', 'NF3', 'HFCS (AR6GWP100)',
     'KYOTOGHG (AR6GWP100)': ['CO2', 'CH4', 'N2O', 'SF6', 'NF3', 'HFCS (AR6GWP100)',
                             'PFCS (AR6GWP100)'],
                             'PFCS (AR6GWP100)'],
-}
+}

+ 8 - 4
UNFCCC_GHG_data/helper/folder_mapping.py → src/unfccc_ghg_data/helper/folder_mapping.py

@@ -1,9 +1,13 @@
-# this script takes a folder as input (from doit) and
-# runs creates the mapping of subfolders to country codes
-# oir that folder
+""" create mapping of folder to countries
+
+this script takes a folder as input (from doit) and
+runs creates the mapping of subfolders to country codes
+for that folder
+"""
 
 
 import argparse
 import argparse
-from UNFCCC_GHG_data.helper import create_folder_mapping
+
+from unfccc_ghg_data.helper import create_folder_mapping
 
 
 # Find the right function and possible input and output files and
 # Find the right function and possible input and output files and
 # read the data using datalad run.
 # read the data using datalad run.

+ 97 - 57
UNFCCC_GHG_data/helper/functions.py → src/unfccc_ghg_data/helper/functions.py

@@ -1,30 +1,42 @@
-import copy
+""" common functions for unfccc_ghg_data
 
 
-import pycountry
+Functions used by the different readers and downloaders in the unfccc_ghg_data package
+"""
+
+import copy
 import json
 import json
 import re
 import re
-import xarray as xr
-import pandas as pd
-import numpy as np
-from datetime import date
 from copy import deepcopy
 from copy import deepcopy
-from typing import Dict, List, Optional
+from datetime import date
 from pathlib import Path
 from pathlib import Path
-from .definitions import custom_country_mapping, custom_folders
-from .definitions import root_path, downloaded_data_path, extracted_data_path
-from .definitions import legacy_data_path, code_path
-from .definitions import GWP_factors
+from typing import Optional
+
+import numpy as np
+import pandas as pd
+import pycountry
+import xarray as xr
+
+from .definitions import (
+    GWP_factors,
+    code_path,
+    custom_country_mapping,
+    custom_folders,
+    downloaded_data_path,
+    extracted_data_path,
+    legacy_data_path,
+    root_path,
+)
 
 
 
 
 def process_data_for_country(
 def process_data_for_country(
     data_country: xr.Dataset,
     data_country: xr.Dataset,
-    entities_to_ignore: List[str],
-    gas_baskets: Dict[str, List[str]],
-    filter_dims: Optional[Dict[str, List[str]]] = None,
+    entities_to_ignore: list[str],
+    gas_baskets: dict[str, list[str]],
+    filter_dims: Optional[dict[str, list[str]]] = None,
     cat_terminology_out: Optional[str] = None,
     cat_terminology_out: Optional[str] = None,
-    category_conversion: Dict[str, Dict] = None,
-    sectors_out: List[str] = None,
-    processing_info_country: Dict = None,
+    category_conversion: dict[str, dict] = None,
+    sectors_out: list[str] = None,
+    processing_info_country: dict = None,
 ) -> xr.Dataset:
 ) -> xr.Dataset:
     """
     """
     Process data from DI interface (where necessary).
     Process data from DI interface (where necessary).
@@ -32,8 +44,38 @@ def process_data_for_country(
     * country specific sector aggregation
     * country specific sector aggregation
     * Conversion to IPCC2006 categories
     * Conversion to IPCC2006 categories
     * general sector and gas basket aggregation (in new categories)
     * general sector and gas basket aggregation (in new categories)
+
+    Parameters
+    ----------
+    data_country: xr.Dataset
+        data to process
+    entities_to_ignore: list[str]
+        Which entities should be ignored. They will not be in the returned dataset
+    gas_baskets: dict[str, list[str]
+        Gas baskets to create. Each entry consists of the basket as key and a list of
+        gases that make up the basket as value
+    filter_dims: Optional[dict[str, list[str]]] = None
+        filter data before processing. Filter is in the format taken by PRIMAP2's
+        ds.pr.loc[] functionality
+    cat_terminology_out: Optional[str] = None
+        Category terminology for the output dataset
+    category_conversion: dict[str, dict] = None
+        Definition of category conversion. The dict has two possible fields:
+        * "conversion" where the value is a dict[str, str] with 1 to 1 category code
+        mapping (key is category from and value is category to)
+        * "aggregation" TODO
+    sectors_out: list[str] = None
+        Categories to return
+    processing_info_country
+        more detailed processing info TODO: explain format
+
+    Returns
+    -------
+    xr.Dataset: processed dataset
+
     """
     """
 
 
+
     # 0: gather information
     # 0: gather information
     countries = list(data_country.coords[data_country.attrs["area"]].values)
     countries = list(data_country.coords[data_country.attrs["area"]].values)
     if len(countries) > 1:
     if len(countries) > 1:
@@ -79,7 +121,7 @@ def process_data_for_country(
     # remove unused cats
     # remove unused cats
     data_country = data_country.dropna(f"category ({cat_terminology_in})", how="all")
     data_country = data_country.dropna(f"category ({cat_terminology_in})", how="all")
     # remove unused years
     # remove unused years
-    data_country = data_country.dropna(f"time", how="all")
+    data_country = data_country.dropna("time", how="all")
     # remove variables only containing nan
     # remove variables only containing nan
     nan_vars_country = [
     nan_vars_country = [
         var
         var
@@ -367,7 +409,7 @@ def process_data_for_country(
 
 
 def convert_categories(
 def convert_categories(
     ds_input: xr.Dataset,
     ds_input: xr.Dataset,
-    conversion: Dict[str, Dict[str, str]],
+    conversion: dict[str, dict[str, str]],
     # terminology_from: str,
     # terminology_from: str,
     terminology_to: str,
     terminology_to: str,
     debug: bool = False,
     debug: bool = False,
@@ -431,7 +473,7 @@ def convert_categories(
             nan_vars = [
             nan_vars = [
                 var
                 var
                 for var in data_agg.data_vars
                 for var in data_agg.data_vars
-                if data_agg[var].isnull().all().data == True
+                if data_agg[var].isnull().all().data is True
             ]
             ]
             data_agg = data_agg.drop(nan_vars)
             data_agg = data_agg.drop(nan_vars)
             if len(data_agg.data_vars) > 0:
             if len(data_agg.data_vars) > 0:
@@ -464,7 +506,7 @@ def convert_categories(
 def get_country_name(
 def get_country_name(
     country_code: str,
     country_code: str,
 ) -> str:
 ) -> str:
-    """get country name from code"""
+    """Get country name from code"""
     if country_code in custom_country_mapping:
     if country_code in custom_country_mapping:
         country_name = custom_country_mapping[country_code]
         country_name = custom_country_mapping[country_code]
     else:
     else:
@@ -488,6 +530,7 @@ def get_country_code(
     is not a three letter code a search will be performed
     is not a three letter code a search will be performed
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
     country_name: str
     country_name: str
         Country code or name to get the three-letter code for.
         Country code or name to get the three-letter code for.
@@ -502,7 +545,7 @@ def get_country_code(
         country_code = country_name
         country_code = country_name
     else:
     else:
         try:
         try:
-            # check if it's a 3 letter UNFCCC_GHG_data
+            # check if it's a 3 letter code
             country = pycountry.countries.get(alpha_3=country_name)
             country = pycountry.countries.get(alpha_3=country_name)
             country_code = country.alpha_3
             country_code = country.alpha_3
         except:
         except:
@@ -513,7 +556,7 @@ def get_country_code(
             except:
             except:
                 raise ValueError(
                 raise ValueError(
                     f"Country name {country_name} can not be mapped to "
                     f"Country name {country_name} can not be mapped to "
-                    f"any country UNFCCC_GHG_data. Try using the ISO3 UNFCCC_GHG_data directly."
+                    f"any country code. Try using the ISO3 code directly."
                 )
                 )
             if len(country) > 1:
             if len(country) > 1:
                 country_code = None
                 country_code = None
@@ -552,7 +595,6 @@ def create_folder_mapping(folder: str, extracted: bool = False) -> None:
         Nothing
         Nothing
 
 
     """
     """
-
     folder = root_path / folder
     folder = root_path / folder
     folder_mapping = {}
     folder_mapping = {}
     # if not extracted:
     # if not extracted:
@@ -595,16 +637,16 @@ def create_folder_mapping(folder: str, extracted: bool = False) -> None:
 def get_country_submissions(
 def get_country_submissions(
     country_name: str,
     country_name: str,
     print_sub: bool = True,
     print_sub: bool = True,
-) -> Dict[str, List[str]]:
+) -> dict[str, list[str]]:
     """
     """
-    Input is a three letter ISO UNFCCC_GHG_data for a country, or the countries name.
-    The function tries to map the country name to an ISO UNFCCC_GHG_data and then
+    Input is a three letter ISO code for a country, or the countries name.
+    The function tries to map the country name to an ISO code and then
     queries the folder mapping files for folders.
     queries the folder mapping files for folders.
 
 
     Parameters
     Parameters
     ----------
     ----------
         country_name: str
         country_name: str
-            String containing the country name or ISO 3 letter UNFCCC_GHG_data
+            String containing the country name or ISO 3 letter code
 
 
         print_sub: bool
         print_sub: bool
             If True information on submissions will be written to stdout
             If True information on submissions will be written to stdout
@@ -615,7 +657,6 @@ def get_country_submissions(
         Each value is a list of folders
         Each value is a list of folders
 
 
     """
     """
-
     data_folder = downloaded_data_path
     data_folder = downloaded_data_path
 
 
     country_code = get_country_code(country_name)
     country_code = get_country_code(country_name)
@@ -625,7 +666,7 @@ def get_country_submissions(
 
 
     country_submissions = {}
     country_submissions = {}
     if print_sub:
     if print_sub:
-        print(f"#" * 80)
+        print("#" * 80)
         print(f"The following submissions are available for {country_name}")
         print(f"The following submissions are available for {country_name}")
     for item in data_folder.iterdir():
     for item in data_folder.iterdir():
         if item.is_dir():
         if item.is_dir():
@@ -634,7 +675,7 @@ def get_country_submissions(
                 print("-" * 80)
                 print("-" * 80)
                 print(f"Data folder {item.name}")
                 print(f"Data folder {item.name}")
                 print("-" * 80)
                 print("-" * 80)
-            with open(item / "folder_mapping.json", "r") as mapping_file:
+            with open(item / "folder_mapping.json") as mapping_file:
                 folder_mapping = json.load(mapping_file)
                 folder_mapping = json.load(mapping_file)
             if country_code in folder_mapping:
             if country_code in folder_mapping:
                 country_folders = folder_mapping[country_code]
                 country_folders = folder_mapping[country_code]
@@ -664,11 +705,11 @@ def get_country_submissions(
 def get_country_datasets(
 def get_country_datasets(
     country_name: str,
     country_name: str,
     print_ds: bool = True,
     print_ds: bool = True,
-) -> Dict[str, List[str]]:
+) -> dict[str, list[str]]:
     """
     """
     Input is a three letter ISO code for a country, or the country's name.
     Input is a three letter ISO code for a country, or the country's name.
-    The function tries to map the country name to an ISO UNFCCC_GHG_data and then
-    checks the UNFCCC_GHG_data and data folders for content on the country.
+    The function tries to map the country name to an ISO code and then
+    checks the code and data folders for content on the country.
 
 
     Parameters
     Parameters
     ----------
     ----------
@@ -684,11 +725,10 @@ def get_country_datasets(
         Each value is a list of folders
         Each value is a list of folders
 
 
     """
     """
-
     data_folder = extracted_data_path
     data_folder = extracted_data_path
     data_folder_legacy = legacy_data_path
     data_folder_legacy = legacy_data_path
 
 
-    # obtain country UNFCCC_GHG_data
+    # obtain country code
     country_code = get_country_code(country_name)
     country_code = get_country_code(country_name)
 
 
     if print_ds:
     if print_ds:
@@ -697,7 +737,7 @@ def get_country_datasets(
     rep_data = {}
     rep_data = {}
     # data
     # data
     if print_ds:
     if print_ds:
-        print(f"#" * 80)
+        print("#" * 80)
         print(f"The following datasets are available for {country_name}")
         print(f"The following datasets are available for {country_name}")
     for item in data_folder.iterdir():
     for item in data_folder.iterdir():
         if item.is_dir():
         if item.is_dir():
@@ -706,7 +746,7 @@ def get_country_datasets(
                 print("-" * 80)
                 print("-" * 80)
                 print(f"Data folder {item.name}")
                 print(f"Data folder {item.name}")
                 print("-" * 80)
                 print("-" * 80)
-            with open(item / "folder_mapping.json", "r") as mapping_file:
+            with open(item / "folder_mapping.json") as mapping_file:
                 folder_mapping = json.load(mapping_file)
                 folder_mapping = json.load(mapping_file)
             if country_code not in folder_mapping:
             if country_code not in folder_mapping:
                 if print_ds:
                 if print_ds:
@@ -757,7 +797,7 @@ def get_country_datasets(
                         if code_file:
                         if code_file:
                             data_info = data_info + f"code: {code_file.name}"
                             data_info = data_info + f"code: {code_file.name}"
                         else:
                         else:
-                            data_info = data_info + f"code: not found"
+                            data_info = data_info + "code: not found"
 
 
                         cleaned_datasets_current_folder[key] = data_info
                         cleaned_datasets_current_folder[key] = data_info
 
 
@@ -775,7 +815,7 @@ def get_country_datasets(
 
 
     # legacy data
     # legacy data
     if print_ds:
     if print_ds:
-        print(f"#" * 80)
+        print("#" * 80)
         print(f"The following legacy datasets are available for {country_name}")
         print(f"The following legacy datasets are available for {country_name}")
     legacy_data = {}
     legacy_data = {}
     for item in data_folder_legacy.iterdir():
     for item in data_folder_legacy.iterdir():
@@ -785,7 +825,7 @@ def get_country_datasets(
                 print("-" * 80)
                 print("-" * 80)
                 print(f"Data folder {item.name}")
                 print(f"Data folder {item.name}")
                 print("-" * 80)
                 print("-" * 80)
-            with open(item / "folder_mapping.json", "r") as mapping_file:
+            with open(item / "folder_mapping.json") as mapping_file:
                 folder_mapping = json.load(mapping_file)
                 folder_mapping = json.load(mapping_file)
             if country_code not in folder_mapping:
             if country_code not in folder_mapping:
                 if print_ds:
                 if print_ds:
@@ -815,7 +855,7 @@ def get_country_datasets(
                     parts = dataset.split("_")
                     parts = dataset.split("_")
                     if parts[0] != country_code:
                     if parts[0] != country_code:
                         cleaned_datasets_current_folder[
                         cleaned_datasets_current_folder[
-                            f"Wrong UNFCCC_GHG_data: {parts[0]}"
+                            f"Wrong code: {parts[0]}"
                         ] = dataset
                         ] = dataset
                     else:
                     else:
                         terminology = "_".join(parts[3:])
                         terminology = "_".join(parts[3:])
@@ -865,42 +905,41 @@ def get_code_file(
     Parameters
     Parameters
     ----------
     ----------
         country_name: str
         country_name: str
-            String containing the country name or ISO 3 letter UNFCCC_GHG_data
+            String containing the country name or ISO 3 letter code
 
 
         submission: str
         submission: str
             String of the submission
             String of the submission
 
 
         print_info: bool = False
         print_info: bool = False
-            If True print information on UNFCCC_GHG_data found
+            If True print information on code found
 
 
     Returns
     Returns
     -------
     -------
-        returns a pathlib Path object for the UNFCCC_GHG_data file
+        returns a pathlib Path object for the code file
     """
     """
-
     code_file_path = None
     code_file_path = None
-    UNFCCC_reader_path = code_path / "UNFCCC_reader"
+    UNFCCC_reader_path = code_path / "unfccc_reader"
 
 
-    # CRF is an exception as it's read using the UNFCCC_CRF_reader module
+    # CRF is an exception as it's read using the unfccc_crf_reader module
     # so we return the path to that.
     # so we return the path to that.
     if submission[0:3] == "CRF":
     if submission[0:3] == "CRF":
-        return root_path / "UNFCCC_CRF_reader"
+        return root_path / "unfccc_crf_reader"
 
 
     if submission[0:2] == "DI":
     if submission[0:2] == "DI":
-        return root_path / "UNFCCC_DI_reader"
+        return root_path / "unfccc_di_reader"
 
 
-    # obtain country UNFCCC_GHG_data
+    # obtain country code
     country_code = get_country_code(country_name)
     country_code = get_country_code(country_name)
 
 
     if print_info:
     if print_info:
-        print(f"Country name {country_name} maps to ISO UNFCCC_GHG_data {country_code}")
+        print(f"Country name {country_name} maps to ISO code {country_code}")
 
 
-    with open(UNFCCC_reader_path / "folder_mapping.json", "r") as mapping_file:
+    with open(UNFCCC_reader_path / "folder_mapping.json") as mapping_file:
         folder_mapping = json.load(mapping_file)
         folder_mapping = json.load(mapping_file)
 
 
     if country_code not in folder_mapping:
     if country_code not in folder_mapping:
         if print_info:
         if print_info:
-            print("No UNFCCC_GHG_data available")
+            print("No code available")
             print("")
             print("")
     else:
     else:
         country_folder = UNFCCC_reader_path / folder_mapping[country_code]
         country_folder = UNFCCC_reader_path / folder_mapping[country_code]
@@ -910,7 +949,7 @@ def get_code_file(
             if file.match(code_file_name_candidate):
             if file.match(code_file_name_candidate):
                 if code_file_path is not None:
                 if code_file_path is not None:
                     raise ValueError(
                     raise ValueError(
-                        f"Found multiple UNFCCC_GHG_data candidates: "
+                        f"Found multiple code candidates: "
                         f"{code_file_path} and file.name. "
                         f"{code_file_path} and file.name. "
                         f"Please use only one file with name "
                         f"Please use only one file with name "
                         f"'read_ISO3_submission_XXX.YYY'."
                         f"'read_ISO3_submission_XXX.YYY'."
@@ -918,7 +957,7 @@ def get_code_file(
                 else:
                 else:
                     if print_info:
                     if print_info:
                         print(
                         print(
-                            f"Found UNFCCC_GHG_data file {file.relative_to(root_path)}"
+                            f"Found code file {file.relative_to(root_path)}"
                         )
                         )
                 code_file_path = file
                 code_file_path = file
 
 
@@ -972,7 +1011,8 @@ def fix_rows(
         new_row = new_row.str.replace("- ", "-")
         new_row = new_row.str.replace("- ", "-")
         # replace spaces in numbers
         # replace spaces in numbers
         pat = r"^(?P<first>[0-9\.,]*)\s(?P<last>[0-9\.,]*)$"
         pat = r"^(?P<first>[0-9\.,]*)\s(?P<last>[0-9\.,]*)$"
-        repl = lambda m: f"{m.group('first')}{m.group('last')}"
+        def repl(m):
+            return f"{m.group('first')}{m.group('last')}"
         new_row = new_row.str.replace(pat, repl, regex=True)
         new_row = new_row.str.replace(pat, repl, regex=True)
         data.loc[indices_to_merge[0]] = new_row
         data.loc[indices_to_merge[0]] = new_row
         data = data.drop(indices_to_merge[1:])
         data = data.drop(indices_to_merge[1:])

+ 1 - 1
UNFCCC_GHG_data/UNFCCC_CRF_reader/__init__.py → src/unfccc_ghg_data/unfccc_crf_reader/__init__.py

@@ -4,7 +4,7 @@ CRF reader module
 
 
 #from pathlib import Path
 #from pathlib import Path
 from . import crf_specifications
 from . import crf_specifications
-from .UNFCCC_CRF_reader_prod import read_crf_for_country, read_crf_for_country_datalad
+from .unfccc_crf_reader_prod import read_crf_for_country, read_crf_for_country_datalad
 
 
 __all__ = ["crf_specifications",
 __all__ = ["crf_specifications",
            "read_crf_for_country",
            "read_crf_for_country",

+ 10 - 7
UNFCCC_GHG_data/UNFCCC_CRF_reader/CRF_raw_for_year.py → src/unfccc_ghg_data/unfccc_crf_reader/crf_raw_for_year.py

@@ -9,14 +9,17 @@ submission are available in the downloaded data folder.
 # TODO: integrate into doit
 # TODO: integrate into doit
 
 
 import argparse
 import argparse
-import primap2 as pm2
-from pathlib import Path
 from datetime import date
 from datetime import date
-from UNFCCC_GHG_data.helper import dataset_path_UNFCCC
+from pathlib import Path
+
+import primap2 as pm2
 
 
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.util import all_crf_countries
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.UNFCCC_CRF_reader_prod import get_input_and_output_files_for_country
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.UNFCCC_CRF_reader_prod import submission_has_been_read
+from unfccc_ghg_data.helper import dataset_path_UNFCCC
+from unfccc_ghg_data.unfccc_crf_reader.unfccc_crf_reader_prod import (
+    get_input_and_output_files_for_country,
+    submission_has_been_read,
+)
+from unfccc_ghg_data.unfccc_crf_reader.util import all_crf_countries
 
 
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 parser.add_argument('--submission_year', help='Submission round to read', type=int)
 parser.add_argument('--submission_year', help='Submission round to read', type=int)
@@ -89,4 +92,4 @@ ds_all_CRF.pr.to_netcdf(output_folder / (output_filename + ".nc"),
 # show info
 # show info
 print(f"The following countries are included in the dataset: {included_countries}")
 print(f"The following countries are included in the dataset: {included_countries}")
 print(f"The following countries have updated submission not yet read "
 print(f"The following countries have updated submission not yet read "
-      f"and not included in the dataset: {outdated_countries}")
+      f"and not included in the dataset: {outdated_countries}")

+ 10 - 0
src/unfccc_ghg_data/unfccc_crf_reader/crf_specifications/__init__.py

@@ -0,0 +1,10 @@
+"""
+Define the CRF specifications here for easy access
+"""
+
+from .crf2021_specification import CRF2021
+from .crf2022_specification import CRF2022
+from .crf2023_aus_specification import CRF2023_AUS
+from .crf2023_specification import CRF2023
+
+__all__ = ["CRF2021", "CRF2022", "CRF2023", "CRF2023_AUS"]

+ 101 - 100
UNFCCC_GHG_data/UNFCCC_CRF_reader/crf_specifications/CRF2021_specification.py → src/unfccc_ghg_data/unfccc_crf_reader/crf_specifications/crf2021_specification.py

@@ -1,4 +1,4 @@
-""" CRF2021 specification.
+"""CRF2021 specification.
 Currently not all tables are included. Extend if you need all country
 Currently not all tables are included. Extend if you need all country
 specific items in categories 2, 3.H-G, 4
 specific items in categories 2, 3.H-G, 4
 
 
@@ -39,6 +39,7 @@ TODO:
 """
 """
 
 
 import numpy as np
 import numpy as np
+
 from .util import unit_info
 from .util import unit_info
 
 
 CRF2021 = {
 CRF2021 = {
@@ -117,7 +118,7 @@ CRF2021 = {
             ['1. Transport of CO2', ['1.C.1']],
             ['1. Transport of CO2', ['1.C.1']],
             ['2. Injection and storage', ['1.C.2']],
             ['2. Injection and storage', ['1.C.2']],
             ['3. Other', ['1.C.3']],
             ['3. Other', ['1.C.3']],
-            ['Memo items: (1)', ['\IGNORE']],
+            ['Memo items: (1)', ['\\IGNORE']],
             ['International bunkers', ['M.Memo.Int']],
             ['International bunkers', ['M.Memo.Int']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['Navigation', ['M.Memo.Int.Mar']],
             ['Navigation', ['M.Memo.Int.Mar']],
@@ -450,8 +451,8 @@ CRF2021 = {
             # 1.A.2.g.viii Other (please specify)
             # 1.A.2.g.viii Other (please specify)
             ['1.A.2.g.viii Other (please specify)', ['1.A.2.g.viii', 'Total'], 2],
             ['1.A.2.g.viii Other (please specify)', ['1.A.2.g.viii', 'Total'], 2],
             # DKE
             # DKE
-            ['Construction', ['\IGNORE', '\IGNORE'], 3],  # (empty)
-            ['Mining', ['\IGNORE', '\IGNORE'], 3],  # (empty)
+            ['Construction', ['\\IGNORE', '\\IGNORE'], 3],  # (empty)
+            ['Mining', ['\\IGNORE', '\\IGNORE'], 3],  # (empty)
             # DNK, DKE, USA, CZE
             # DNK, DKE, USA, CZE
             ['Other non-specified', ['1.A.2.g.viii.1', 'Total'], 3],
             ['Other non-specified', ['1.A.2.g.viii.1', 'Total'], 3],
             ['Liquid Fuels', ['1.A.2.g.viii.1', 'Liquid'], 4],
             ['Liquid Fuels', ['1.A.2.g.viii.1', 'Liquid'], 4],
@@ -501,7 +502,7 @@ CRF2021 = {
             ['Peat', ['1.A.2.g.viii.1', 'Peat'], 4],
             ['Peat', ['1.A.2.g.viii.1', 'Peat'], 4],
             ['Biomass', ['1.A.2.g.viii.1', 'Biomass'], 4],
             ['Biomass', ['1.A.2.g.viii.1', 'Biomass'], 4],
             # DKE
             # DKE
-            ['Textile', ['\IGNORE', '\IGNORE'], 3],  # (empty)
+            ['Textile', ['\\IGNORE', '\\IGNORE'], 3],  # (empty)
             # DNK, DNM, FIN, DKE
             # DNK, DNM, FIN, DKE
             ['Other manufacturing industries', ['1.A.2.g.viii.3', 'Total'], 3],
             ['Other manufacturing industries', ['1.A.2.g.viii.3', 'Total'], 3],
             ['Liquid Fuels', ['1.A.2.g.viii.3', 'Liquid'], 4],
             ['Liquid Fuels', ['1.A.2.g.viii.3', 'Liquid'], 4],
@@ -1390,10 +1391,10 @@ CRF2021 = {
             ['Biomass', ['1.A.5.b.iii', 'Biomass'], 3],
             ['Biomass', ['1.A.5.b.iii', 'Biomass'], 3],
             # ESP, FIN
             # ESP, FIN
             # Information Item
             # Information Item
-            ['Information item:(15)', ['\IGNORE', '\IGNORE'], 0],
-            ['Waste incineration with energy recovery included as:', ['\IGNORE', '\IGNORE'], 1],
-            ['Biomass(6)', ['\IGNORE', '\IGNORE'], 1],
-            ['Fossil fuels(4)', ['\IGNORE', '\IGNORE'], 1],
+            ['Information item:(15)', ['\\IGNORE', '\\IGNORE'], 0],
+            ['Waste incineration with energy recovery included as:', ['\\IGNORE', '\\IGNORE'], 1],
+            ['Biomass(6)', ['\\IGNORE', '\\IGNORE'], 1],
+            ['Fossil fuels(4)', ['\\IGNORE', '\\IGNORE'], 1],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             'EMISSIONS CH4': "CH4",
             'EMISSIONS CH4': "CH4",
@@ -1537,7 +1538,7 @@ CRF2021 = {
             ['a. Injection', ['1.C.2.a']],
             ['a. Injection', ['1.C.2.a']],
             ['b. Storage', ['1.C.2.b']],
             ['b. Storage', ['1.C.2.b']],
             ['3. Other', ['1.C.3']],
             ['3. Other', ['1.C.3']],
-            ['Information item(4, 5)', ['\IGNORE']],
+            ['Information item(4, 5)', ['\\IGNORE']],
             ['Total amount captured for storage', ['M.Info.A.TACS']],
             ['Total amount captured for storage', ['M.Info.A.TACS']],
             ['Total amount of imports for storage', ['M.Info.A.TAIS']],
             ['Total amount of imports for storage', ['M.Info.A.TAIS']],
             ['Total A', ['M.Info.A']],
             ['Total A', ['M.Info.A']],
@@ -1545,7 +1546,7 @@ CRF2021 = {
             ['Total amount of CO2 injected at storage sites', ['M.Info.B.TAI']],
             ['Total amount of CO2 injected at storage sites', ['M.Info.B.TAI']],
             ['Total leakage from transport, injection and storage', ['M.Info.B.TLTIS']],
             ['Total leakage from transport, injection and storage', ['M.Info.B.TLTIS']],
             ['Total B', ['M.Info.B']],
             ['Total B', ['M.Info.B']],
-            ['Difference (A-B)(6)', ['\IGNORE']],
+            ['Difference (A-B)(6)', ['\\IGNORE']],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             'EMISSIONS CO2(2)': 'CO2',
             'EMISSIONS CO2(2)': 'CO2',
@@ -1804,61 +1805,61 @@ CRF2021 = {
             # A. Enteric fermentation
             # A. Enteric fermentation
             ['A. Enteric fermentation', ['3.A'], 2],
             ['A. Enteric fermentation', ['3.A'], 2],
             ['1. Cattle(1)', ['3.A.1'], 3],
             ['1. Cattle(1)', ['3.A.1'], 3],
-            ['Option A:', ['\IGNORE'], 4],
+            ['Option A:', ['\\IGNORE'], 4],
             ['Dairy cattle', ['3.A.1.Aa'], 5],
             ['Dairy cattle', ['3.A.1.Aa'], 5],
             ['Non-dairy cattle', ['3.A.1.Ab'], 5],
             ['Non-dairy cattle', ['3.A.1.Ab'], 5],
-            ['Option B:', ['\IGNORE'], 4],
+            ['Option B:', ['\\IGNORE'], 4],
             ['Mature dairy cattle', ['3.A.1.Ba'], 5],
             ['Mature dairy cattle', ['3.A.1.Ba'], 5],
             ['Other mature cattle', ['3.A.1.Bb'], 5],
             ['Other mature cattle', ['3.A.1.Bb'], 5],
             ['Growing cattle', ['3.A.1.Bc'], 5],
             ['Growing cattle', ['3.A.1.Bc'], 5],
-            ['Option C (country-specific):', ['\IGNORE'], 4],
+            ['Option C (country-specific):', ['\\IGNORE'], 4],
             # all countries not specified explcitly
             # all countries not specified explcitly
-            ['\C!-AUS-MLT-LUX-POL-SVN-USA\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C!-AUS-MLT-LUX-POL-SVN-USA\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
             # Australia
             # Australia
-            ['\C-AUS\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-AUS\ Dairy Cattle', ['3.A.1.C-AUS-a'], 6],
-            ['\C-AUS\ Beef Cattle - Pasture', ['3.A.1.C-AUS-b'], 6],
-            ['\C-AUS\ Beef Cattle - Feedlot', ['3.A.1.C-AUS-c'], 6],
+            ['\\C-AUS\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-AUS\\ Dairy Cattle', ['3.A.1.C-AUS-a'], 6],
+            ['\\C-AUS\\ Beef Cattle - Pasture', ['3.A.1.C-AUS-b'], 6],
+            ['\\C-AUS\\ Beef Cattle - Feedlot', ['3.A.1.C-AUS-c'], 6],
             # malta
             # malta
-            ['\C-MLT\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-MLT\ dairy cows', ['3.A.1.C-MLT-a'], 6],
-            ['\C-MLT\ non-lactating cows', ['3.A.1.C-MLT-b'], 6],
-            ['\C-MLT\ bulls', ['3.A.1.C-MLT-c'], 6],
-            ['\C-MLT\ calves', ['3.A.1.C-MLT-d'], 6],
-            ['\C-MLT\ growing cattle 1-2 years', ['3.A.1.C-MLT-e'], 6],
+            ['\\C-MLT\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-MLT\\ dairy cows', ['3.A.1.C-MLT-a'], 6],
+            ['\\C-MLT\\ non-lactating cows', ['3.A.1.C-MLT-b'], 6],
+            ['\\C-MLT\\ bulls', ['3.A.1.C-MLT-c'], 6],
+            ['\\C-MLT\\ calves', ['3.A.1.C-MLT-d'], 6],
+            ['\\C-MLT\\ growing cattle 1-2 years', ['3.A.1.C-MLT-e'], 6],
             # Luxembourg
             # Luxembourg
-            ['\C-LUX\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-LUX\ Bulls', ['3.A.1.C-LUX-a'], 6],
-            ['\C-LUX\ Calves', ['3.A.1.C-LUX-b'], 6],
-            ['\C-LUX\ Young Cattle', ['3.A.1.C-LUX-c'], 6],
-            ['\C-LUX\ Suckler Cows', ['3.A.1.C-LUX-d'], 6],
-            ['\C-LUX\ Bulls under 2 years', ['3.A.1.C-LUX-e'], 6],
-            ['\C-LUX\ Dairy Cows', ['3.A.1.C-LUX-f'], 6],
+            ['\\C-LUX\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-LUX\\ Bulls', ['3.A.1.C-LUX-a'], 6],
+            ['\\C-LUX\\ Calves', ['3.A.1.C-LUX-b'], 6],
+            ['\\C-LUX\\ Young Cattle', ['3.A.1.C-LUX-c'], 6],
+            ['\\C-LUX\\ Suckler Cows', ['3.A.1.C-LUX-d'], 6],
+            ['\\C-LUX\\ Bulls under 2 years', ['3.A.1.C-LUX-e'], 6],
+            ['\\C-LUX\\ Dairy Cows', ['3.A.1.C-LUX-f'], 6],
             # Poland
             # Poland
-            ['\C-POL\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-POL\ Bulls (older than 2 years)', ['3.A.1.C-POL-a'], 6],
-            ['\C-POL\ Non-dairy Heifers (older than 2 years)', ['3.A.1.C-POL-b'], 6],
-            ['\C-POL\ Non-dairy Young Cattle (younger than 1 year)', ['3.A.1.C-POL-c'], 6],
-            ['\C-POL\ Dairy Cattle', ['3.A.1.C-POL-d'], 6],
-            ['\C-POL\ Non-dairy Young Cattle (1-2 years)', ['3.A.1.C-POL-e'], 6],
+            ['\\C-POL\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-POL\\ Bulls (older than 2 years)', ['3.A.1.C-POL-a'], 6],
+            ['\\C-POL\\ Non-dairy Heifers (older than 2 years)', ['3.A.1.C-POL-b'], 6],
+            ['\\C-POL\\ Non-dairy Young Cattle (younger than 1 year)', ['3.A.1.C-POL-c'], 6],
+            ['\\C-POL\\ Dairy Cattle', ['3.A.1.C-POL-d'], 6],
+            ['\\C-POL\\ Non-dairy Young Cattle (1-2 years)', ['3.A.1.C-POL-e'], 6],
             # Slovenia
             # Slovenia
-            ['\C-SVN\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-SVN\ Dairy cows', ['3.A.1.C-SVN-a'], 6],
-            ['\C-SVN\ Non-dairy cattle', ['3.A.1.C-SVN-b'], 6],
-            ['\C-SVN\ Other cows', ['3.A.1.C-SVN-c'], 6],
+            ['\\C-SVN\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-SVN\\ Dairy cows', ['3.A.1.C-SVN-a'], 6],
+            ['\\C-SVN\\ Non-dairy cattle', ['3.A.1.C-SVN-b'], 6],
+            ['\\C-SVN\\ Other cows', ['3.A.1.C-SVN-c'], 6],
             # USA
             # USA
-            ['\C-USA\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-USA\ Steer Stocker', ['3.A.1.C-USA-a'], 6],
-            ['\C-USA\ Heifer Stocker', ['3.A.1.C-USA-b'], 6],
-            ['\C-USA\ Beef Cows', ['3.A.1.C-USA-c'], 6],
-            ['\C-USA\ Dairy Replacements', ['3.A.1.C-USA-d'], 6],
-            ['\C-USA\ Beef Replacements', ['3.A.1.C-USA-e'], 6],
-            ['\C-USA\ Steer Feedlot', ['3.A.1.C-USA-f'], 6],
-            ['\C-USA\ Heifer Feedlot', ['3.A.1.C-USA-g'], 6],
-            ['\C-USA\ Bulls', ['3.A.1.C-USA-h'], 6],
-            ['\C-USA\ Dairy Cows', ['3.A.1.C-USA-i'], 6],
-            ['\C-USA\ Beef Calves', ['3.A.1.C-USA-j'], 6],
-            ['\C-USA\ Dairy Calves', ['3.A.1.C-USA-k'], 6],
+            ['\\C-USA\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-USA\\ Steer Stocker', ['3.A.1.C-USA-a'], 6],
+            ['\\C-USA\\ Heifer Stocker', ['3.A.1.C-USA-b'], 6],
+            ['\\C-USA\\ Beef Cows', ['3.A.1.C-USA-c'], 6],
+            ['\\C-USA\\ Dairy Replacements', ['3.A.1.C-USA-d'], 6],
+            ['\\C-USA\\ Beef Replacements', ['3.A.1.C-USA-e'], 6],
+            ['\\C-USA\\ Steer Feedlot', ['3.A.1.C-USA-f'], 6],
+            ['\\C-USA\\ Heifer Feedlot', ['3.A.1.C-USA-g'], 6],
+            ['\\C-USA\\ Bulls', ['3.A.1.C-USA-h'], 6],
+            ['\\C-USA\\ Dairy Cows', ['3.A.1.C-USA-i'], 6],
+            ['\\C-USA\\ Beef Calves', ['3.A.1.C-USA-j'], 6],
+            ['\\C-USA\\ Dairy Calves', ['3.A.1.C-USA-k'], 6],
             # Other livestock
             # Other livestock
             ['2. Sheep', ['3.A.2'], 3],
             ['2. Sheep', ['3.A.2'], 3],
             ['3. Swine', ['3.A.3'], 3],
             ['3. Swine', ['3.A.3'], 3],
@@ -1879,60 +1880,60 @@ CRF2021 = {
             # Manure Management
             # Manure Management
             ['B. Manure management', ['3.B'], 2],
             ['B. Manure management', ['3.B'], 2],
             ['1. Cattle(1)', ['3.B.1'], 3],
             ['1. Cattle(1)', ['3.B.1'], 3],
-            ['Option A:', ['\IGNORE'], 4],
+            ['Option A:', ['\\IGNORE'], 4],
             ['Dairy cattle', ['3.B.1.Aa'], 5],
             ['Dairy cattle', ['3.B.1.Aa'], 5],
             ['Non-dairy cattle', ['3.B.1.Ab'], 5],
             ['Non-dairy cattle', ['3.B.1.Ab'], 5],
-            ['Option B:', ['\IGNORE'], 4],
+            ['Option B:', ['\\IGNORE'], 4],
             ['Mature dairy cattle', ['3.B.1.Ba'], 5],
             ['Mature dairy cattle', ['3.B.1.Ba'], 5],
             ['Other mature cattle', ['3.B.1.Bb'], 5],
             ['Other mature cattle', ['3.B.1.Bb'], 5],
             ['Growing cattle', ['3.B.1.Bc'], 5],
             ['Growing cattle', ['3.B.1.Bc'], 5],
-            ['Option C (country-specific):', ['\IGNORE'], 4],
+            ['Option C (country-specific):', ['\\IGNORE'], 4],
             # all countries not specified explicitly
             # all countries not specified explicitly
-            ['\C!-AUS-MLT-LUX-POL-SVN-USA\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C!-AUS-MLT-LUX-POL-SVN-USA\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
             # Australia
             # Australia
-            ['\C-AUS\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-AUS\ Dairy Cattle', ['3.B.1.C-AUS-a'], 6],
-            ['\C-AUS\ Beef Cattle - Pasture', ['3.B.1.C-AUS-b'], 6],
-            ['\C-AUS\ Beef Cattle - Feedlot', ['3.B.1.C-AUS-c'], 6],
+            ['\\C-AUS\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-AUS\\ Dairy Cattle', ['3.B.1.C-AUS-a'], 6],
+            ['\\C-AUS\\ Beef Cattle - Pasture', ['3.B.1.C-AUS-b'], 6],
+            ['\\C-AUS\\ Beef Cattle - Feedlot', ['3.B.1.C-AUS-c'], 6],
             # Malta
             # Malta
-            ['\C-MLT\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-MLT\ dairy cows', ['3.B.1.C-MLT-a'], 6],
-            ['\C-MLT\ non-lactating cows', ['3.B.1.C-MLT-b'], 6],
-            ['\C-MLT\ bulls', ['3.B.1.C-MLT-c'], 6],
-            ['\C-MLT\ calves', ['3.B.1.C-MLT-d'], 6],
-            ['\C-MLT\ growing cattle 1-2 years', ['3.B.1.C-MLT-e'], 6],
+            ['\\C-MLT\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-MLT\\ dairy cows', ['3.B.1.C-MLT-a'], 6],
+            ['\\C-MLT\\ non-lactating cows', ['3.B.1.C-MLT-b'], 6],
+            ['\\C-MLT\\ bulls', ['3.B.1.C-MLT-c'], 6],
+            ['\\C-MLT\\ calves', ['3.B.1.C-MLT-d'], 6],
+            ['\\C-MLT\\ growing cattle 1-2 years', ['3.B.1.C-MLT-e'], 6],
             # Luxembourg
             # Luxembourg
-            ['\C-LUX\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-LUX\ Bulls', ['3.B.1.C-LUX-a'], 6],
-            ['\C-LUX\ Calves', ['3.B.1.C-LUX-b'], 6],
-            ['\C-LUX\ Young Cattle', ['3.B.1.C-LUX-c'], 6],
-            ['\C-LUX\ Suckler Cows', ['3.B.1.C-LUX-d'], 6],
-            ['\C-LUX\ Bulls under 2 years', ['3.B.1.C-LUX-e'], 6],
-            ['\C-LUX\ Dairy Cows', ['3.B.1.C-LUX-f'], 6],
+            ['\\C-LUX\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-LUX\\ Bulls', ['3.B.1.C-LUX-a'], 6],
+            ['\\C-LUX\\ Calves', ['3.B.1.C-LUX-b'], 6],
+            ['\\C-LUX\\ Young Cattle', ['3.B.1.C-LUX-c'], 6],
+            ['\\C-LUX\\ Suckler Cows', ['3.B.1.C-LUX-d'], 6],
+            ['\\C-LUX\\ Bulls under 2 years', ['3.B.1.C-LUX-e'], 6],
+            ['\\C-LUX\\ Dairy Cows', ['3.B.1.C-LUX-f'], 6],
             # Poland
             # Poland
-            ['\C-POL\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-POL\ Non-dairy Cattle', ['3.B.1.C-POL-a'], 6],
-            ['\C-POL\ Dairy Cattle', ['3.B.1.C-POL-b'], 6],
+            ['\\C-POL\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-POL\\ Non-dairy Cattle', ['3.B.1.C-POL-a'], 6],
+            ['\\C-POL\\ Dairy Cattle', ['3.B.1.C-POL-b'], 6],
             # Slovenia
             # Slovenia
-            ['\C-SVN\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-SVN\ Dairy cows', ['3.B.1.C-SVN-a'], 6],
-            ['\C-SVN\ Non-dairy cattle', ['3.B.1.C-SVN-b'], 6],
-            ['\C-SVN\ Other cows', ['3.B.1.C-SVN-c'], 6],
+            ['\\C-SVN\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-SVN\\ Dairy cows', ['3.B.1.C-SVN-a'], 6],
+            ['\\C-SVN\\ Non-dairy cattle', ['3.B.1.C-SVN-b'], 6],
+            ['\\C-SVN\\ Other cows', ['3.B.1.C-SVN-c'], 6],
             # USA
             # USA
-            ['\C-USA\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-USA\ Dairy Cattle', ['\IGNORE'], 6],
-            ['\C-USA\ Non-Dairy Cattle', ['\IGNORE'], 6],
-            ['\C-USA\ Steer Stocker', ['3.B.1.C-USA-a'], 6],
-            ['\C-USA\ Heifer Stocker', ['3.B.1.C-USA-b'], 6],
-            ['\C-USA\ Beef Cows', ['3.B.1.C-USA-c'], 6],
-            ['\C-USA\ Dairy Replacements', ['3.B.1.C-USA-d'], 6],
-            ['\C-USA\ Beef Replacements', ['3.B.1.C-USA-e'], 6],
-            ['\C-USA\ Steer Feedlot', ['3.B.1.C-USA-f'], 6],
-            ['\C-USA\ Heifer Feedlot', ['3.B.1.C-USA-g'], 6],
-            ['\C-USA\ Bulls', ['3.B.1.C-USA-h'], 6],
-            ['\C-USA\ Dairy Cows', ['3.B.1.C-USA-i'], 6],
-            ['\C-USA\ Beef Calves', ['3.B.1.C-USA-j'], 6],
-            ['\C-USA\ Dairy Calves', ['3.B.1.C-USA-k'], 6],
+            ['\\C-USA\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-USA\\ Dairy Cattle', ['\\IGNORE'], 6],
+            ['\\C-USA\\ Non-Dairy Cattle', ['\\IGNORE'], 6],
+            ['\\C-USA\\ Steer Stocker', ['3.B.1.C-USA-a'], 6],
+            ['\\C-USA\\ Heifer Stocker', ['3.B.1.C-USA-b'], 6],
+            ['\\C-USA\\ Beef Cows', ['3.B.1.C-USA-c'], 6],
+            ['\\C-USA\\ Dairy Replacements', ['3.B.1.C-USA-d'], 6],
+            ['\\C-USA\\ Beef Replacements', ['3.B.1.C-USA-e'], 6],
+            ['\\C-USA\\ Steer Feedlot', ['3.B.1.C-USA-f'], 6],
+            ['\\C-USA\\ Heifer Feedlot', ['3.B.1.C-USA-g'], 6],
+            ['\\C-USA\\ Bulls', ['3.B.1.C-USA-h'], 6],
+            ['\\C-USA\\ Dairy Cows', ['3.B.1.C-USA-i'], 6],
+            ['\\C-USA\\ Beef Calves', ['3.B.1.C-USA-j'], 6],
+            ['\\C-USA\\ Dairy Calves', ['3.B.1.C-USA-k'], 6],
             # other animals
             # other animals
             ['2. Sheep', ['3.B.2'], 3],
             ['2. Sheep', ['3.B.2'], 3],
             ['3. Swine', ['3.B.3'], 3],
             ['3. Swine', ['3.B.3'], 3],
@@ -2023,15 +2024,15 @@ CRF2021 = {
             ['Flood prone', ['3.C.2.a']],
             ['Flood prone', ['3.C.2.a']],
             ['Drought prone', ['3.C.2.b']],
             ['Drought prone', ['3.C.2.b']],
             ['3. Deep water', ['3.C.3']],
             ['3. Deep water', ['3.C.3']],
-            ['Water depth 50100 cm', ['3.C.3.a']],
+            ['Water depth 50-100 cm', ['3.C.3.a']],
             ['Water depth > 100 cm', ['3.C.3.b']],
             ['Water depth > 100 cm', ['3.C.3.b']],
             ['4. Other (please specify)', ['3.C.4']],
             ['4. Other (please specify)', ['3.C.4']],
             ['Non-specified', ['3.C.4.a']],  # EST
             ['Non-specified', ['3.C.4.a']],  # EST
             ['Other', ['3.C.4.a']],  # DEU
             ['Other', ['3.C.4.a']],  # DEU
             ['other', ['3.C.4.a']],  # LVA
             ['other', ['3.C.4.a']],  # LVA
             ['Other cultivation', ['3.C.4.a']],  # CZE
             ['Other cultivation', ['3.C.4.a']],  # CZE
-            ['Upland rice(4)', ['\IGNORE']],
-            ['Total(4)', ['\IGNORE']],
+            ['Upland rice(4)', ['\\IGNORE']],
+            ['Total(4)', ['\\IGNORE']],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             'EMISSIONS CH4': 'CH4',
             'EMISSIONS CH4': 'CH4',
@@ -2267,7 +2268,7 @@ CRF2021 = {
             ['Sludge spreading', ['5.E.7']],  # ESP
             ['Sludge spreading', ['5.E.7']],  # ESP
             ['Accidental combustion', ['5.E.3']],  # ESP
             ['Accidental combustion', ['5.E.3']],  # ESP
             ['Other waste', ['5.E.5']],  # CZE
             ['Other waste', ['5.E.5']],  # CZE
-            ['Memo item:(2)', ['\IGNORE']],
+            ['Memo item:(2)', ['\\IGNORE']],
             ['Long-term storage of C in waste disposal sites', ['M.Memo.LTSW']],
             ['Long-term storage of C in waste disposal sites', ['M.Memo.LTSW']],
             ['Annual change in total long-term C storage', ['M.Memo.ACLT']],
             ['Annual change in total long-term C storage', ['M.Memo.ACLT']],
             ['Annual change in total long-term C storage in HWP waste(3)', ['M.Memo.ACLTHWP']],
             ['Annual change in total long-term C storage in HWP waste(3)', ['M.Memo.ACLTHWP']],

+ 102 - 101
UNFCCC_GHG_data/UNFCCC_CRF_reader/crf_specifications/CRF2022_specification.py → src/unfccc_ghg_data/unfccc_crf_reader/crf_specifications/crf2022_specification.py

@@ -1,4 +1,4 @@
-""" CRF2022 specification.
+"""CRF2022 specification.
 Currently not all tables are included. Extend if you need all country
 Currently not all tables are included. Extend if you need all country
 specific items in categories 2, 3.H-G, 4
 specific items in categories 2, 3.H-G, 4
 
 
@@ -39,6 +39,7 @@ TODO:
 """
 """
 
 
 import numpy as np
 import numpy as np
+
 from .util import unit_info
 from .util import unit_info
 
 
 CRF2022 = {
 CRF2022 = {
@@ -117,7 +118,7 @@ CRF2022 = {
             ['1. Transport of CO2', ['1.C.1']],
             ['1. Transport of CO2', ['1.C.1']],
             ['2. Injection and storage', ['1.C.2']],
             ['2. Injection and storage', ['1.C.2']],
             ['3. Other', ['1.C.3']],
             ['3. Other', ['1.C.3']],
-            ['Memo items: (1)', ['\IGNORE']],
+            ['Memo items: (1)', ['\\IGNORE']],
             ['International bunkers', ['M.Memo.Int']],
             ['International bunkers', ['M.Memo.Int']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['Navigation', ['M.Memo.Int.Mar']],
             ['Navigation', ['M.Memo.Int.Mar']],
@@ -450,8 +451,8 @@ CRF2022 = {
             # 1.A.2.g.viii Other (please specify)
             # 1.A.2.g.viii Other (please specify)
             ['1.A.2.g.viii Other (please specify)', ['1.A.2.g.viii', 'Total'], 2],
             ['1.A.2.g.viii Other (please specify)', ['1.A.2.g.viii', 'Total'], 2],
             # DKE
             # DKE
-            ['Construction', ['\IGNORE', '\IGNORE'], 3],  # (empty)
-            ['Mining', ['\IGNORE', '\IGNORE'], 3],  # (empty)
+            ['Construction', ['\\IGNORE', '\\IGNORE'], 3],  # (empty)
+            ['Mining', ['\\IGNORE', '\\IGNORE'], 3],  # (empty)
             # DNK, DKE, USA, CZE
             # DNK, DKE, USA, CZE
             ['Other non-specified', ['1.A.2.g.viii.1', 'Total'], 3],
             ['Other non-specified', ['1.A.2.g.viii.1', 'Total'], 3],
             ['Liquid Fuels', ['1.A.2.g.viii.1', 'Liquid'], 4],
             ['Liquid Fuels', ['1.A.2.g.viii.1', 'Liquid'], 4],
@@ -501,7 +502,7 @@ CRF2022 = {
             ['Peat', ['1.A.2.g.viii.1', 'Peat'], 4],
             ['Peat', ['1.A.2.g.viii.1', 'Peat'], 4],
             ['Biomass', ['1.A.2.g.viii.1', 'Biomass'], 4],
             ['Biomass', ['1.A.2.g.viii.1', 'Biomass'], 4],
             # DKE
             # DKE
-            ['Textile', ['\IGNORE', '\IGNORE'], 3],  # (empty)
+            ['Textile', ['\\IGNORE', '\\IGNORE'], 3],  # (empty)
             # DNK, DNM, FIN, DKE
             # DNK, DNM, FIN, DKE
             ['Other manufacturing industries', ['1.A.2.g.viii.3', 'Total'], 3],
             ['Other manufacturing industries', ['1.A.2.g.viii.3', 'Total'], 3],
             ['Liquid Fuels', ['1.A.2.g.viii.3', 'Liquid'], 4],
             ['Liquid Fuels', ['1.A.2.g.viii.3', 'Liquid'], 4],
@@ -1405,10 +1406,10 @@ CRF2022 = {
             ['iii. Mobile (other)', ['1.A.5.b.iv', 'Total'], 2],
             ['iii. Mobile (other)', ['1.A.5.b.iv', 'Total'], 2],
             ['Liquid Fuels', ['1.A.5.b.iv', 'Liquid'], 3],
             ['Liquid Fuels', ['1.A.5.b.iv', 'Liquid'], 3],
             # Information Item
             # Information Item
-            ['Information item:(15)', ['\IGNORE', '\IGNORE'], 0],
-            ['Waste incineration with energy recovery included as:', ['\IGNORE', '\IGNORE'], 1],
-            ['Biomass(6)', ['\IGNORE', '\IGNORE'], 1],
-            ['Fossil fuels(4)', ['\IGNORE', '\IGNORE'], 1],
+            ['Information item:(15)', ['\\IGNORE', '\\IGNORE'], 0],
+            ['Waste incineration with energy recovery included as:', ['\\IGNORE', '\\IGNORE'], 1],
+            ['Biomass(6)', ['\\IGNORE', '\\IGNORE'], 1],
+            ['Fossil fuels(4)', ['\\IGNORE', '\\IGNORE'], 1],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             'EMISSIONS CH4': "CH4",
             'EMISSIONS CH4': "CH4",
@@ -1554,7 +1555,7 @@ CRF2022 = {
             ['a. Injection', ['1.C.2.a']],
             ['a. Injection', ['1.C.2.a']],
             ['b. Storage', ['1.C.2.b']],
             ['b. Storage', ['1.C.2.b']],
             ['3. Other', ['1.C.3']],
             ['3. Other', ['1.C.3']],
-            ['Information item(4, 5)', ['\IGNORE']],
+            ['Information item(4, 5)', ['\\IGNORE']],
             ['Total amount captured for storage', ['M.Info.A.TACS']],
             ['Total amount captured for storage', ['M.Info.A.TACS']],
             ['Total amount of imports for storage', ['M.Info.A.TAIS']],
             ['Total amount of imports for storage', ['M.Info.A.TAIS']],
             ['Total A', ['M.Info.A']],
             ['Total A', ['M.Info.A']],
@@ -1562,7 +1563,7 @@ CRF2022 = {
             ['Total amount of CO2 injected at storage sites', ['M.Info.B.TAI']],
             ['Total amount of CO2 injected at storage sites', ['M.Info.B.TAI']],
             ['Total leakage from transport, injection and storage', ['M.Info.B.TLTIS']],
             ['Total leakage from transport, injection and storage', ['M.Info.B.TLTIS']],
             ['Total B', ['M.Info.B']],
             ['Total B', ['M.Info.B']],
-            ['Difference (A-B)(6)', ['\IGNORE']],
+            ['Difference (A-B)(6)', ['\\IGNORE']],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             'EMISSIONS CO2(2)': 'CO2',
             'EMISSIONS CO2(2)': 'CO2',
@@ -1821,61 +1822,61 @@ CRF2022 = {
             # A. Enteric fermentation
             # A. Enteric fermentation
             ['A. Enteric fermentation', ['3.A'], 2],
             ['A. Enteric fermentation', ['3.A'], 2],
             ['1. Cattle(1)', ['3.A.1'], 3],
             ['1. Cattle(1)', ['3.A.1'], 3],
-            ['Option A:', ['\IGNORE'], 4],
+            ['Option A:', ['\\IGNORE'], 4],
             ['Dairy cattle', ['3.A.1.Aa'], 5],
             ['Dairy cattle', ['3.A.1.Aa'], 5],
             ['Non-dairy cattle', ['3.A.1.Ab'], 5],
             ['Non-dairy cattle', ['3.A.1.Ab'], 5],
-            ['Option B:', ['\IGNORE'], 4],
+            ['Option B:', ['\\IGNORE'], 4],
             ['Mature dairy cattle', ['3.A.1.Ba'], 5],
             ['Mature dairy cattle', ['3.A.1.Ba'], 5],
             ['Other mature cattle', ['3.A.1.Bb'], 5],
             ['Other mature cattle', ['3.A.1.Bb'], 5],
             ['Growing cattle', ['3.A.1.Bc'], 5],
             ['Growing cattle', ['3.A.1.Bc'], 5],
-            ['Option C (country-specific):', ['\IGNORE'], 4],
+            ['Option C (country-specific):', ['\\IGNORE'], 4],
             # all countries not specified explcitly
             # all countries not specified explcitly
-            ['\C!-AUS-MLT-LUX-POL-SVN-USA\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C!-AUS-MLT-LUX-POL-SVN-USA\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
             # Australia
             # Australia
-            ['\C-AUS\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-AUS\ Dairy Cattle', ['3.A.1.C-AUS-a'], 6],
-            ['\C-AUS\ Beef Cattle - Pasture', ['3.A.1.C-AUS-b'], 6],
-            ['\C-AUS\ Beef Cattle - Feedlot', ['3.A.1.C-AUS-c'], 6],
+            ['\\C-AUS\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-AUS\\ Dairy Cattle', ['3.A.1.C-AUS-a'], 6],
+            ['\\C-AUS\\ Beef Cattle - Pasture', ['3.A.1.C-AUS-b'], 6],
+            ['\\C-AUS\\ Beef Cattle - Feedlot', ['3.A.1.C-AUS-c'], 6],
             # malta
             # malta
-            ['\C-MLT\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-MLT\ dairy cows', ['3.A.1.C-MLT-a'], 6],
-            ['\C-MLT\ non-lactating cows', ['3.A.1.C-MLT-b'], 6],
-            ['\C-MLT\ bulls', ['3.A.1.C-MLT-c'], 6],
-            ['\C-MLT\ calves', ['3.A.1.C-MLT-d'], 6],
-            ['\C-MLT\ growing cattle 1-2 years', ['3.A.1.C-MLT-e'], 6],
+            ['\\C-MLT\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-MLT\\ dairy cows', ['3.A.1.C-MLT-a'], 6],
+            ['\\C-MLT\\ non-lactating cows', ['3.A.1.C-MLT-b'], 6],
+            ['\\C-MLT\\ bulls', ['3.A.1.C-MLT-c'], 6],
+            ['\\C-MLT\\ calves', ['3.A.1.C-MLT-d'], 6],
+            ['\\C-MLT\\ growing cattle 1-2 years', ['3.A.1.C-MLT-e'], 6],
             # Luxembourg
             # Luxembourg
-            ['\C-LUX\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-LUX\ Bulls', ['3.A.1.C-LUX-a'], 6],
-            ['\C-LUX\ Calves', ['3.A.1.C-LUX-b'], 6],
-            ['\C-LUX\ Young Cattle', ['3.A.1.C-LUX-c'], 6],
-            ['\C-LUX\ Suckler Cows', ['3.A.1.C-LUX-d'], 6],
-            ['\C-LUX\ Bulls under 2 years', ['3.A.1.C-LUX-e'], 6],
-            ['\C-LUX\ Dairy Cows', ['3.A.1.C-LUX-f'], 6],
+            ['\\C-LUX\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-LUX\\ Bulls', ['3.A.1.C-LUX-a'], 6],
+            ['\\C-LUX\\ Calves', ['3.A.1.C-LUX-b'], 6],
+            ['\\C-LUX\\ Young Cattle', ['3.A.1.C-LUX-c'], 6],
+            ['\\C-LUX\\ Suckler Cows', ['3.A.1.C-LUX-d'], 6],
+            ['\\C-LUX\\ Bulls under 2 years', ['3.A.1.C-LUX-e'], 6],
+            ['\\C-LUX\\ Dairy Cows', ['3.A.1.C-LUX-f'], 6],
             # Poland
             # Poland
-            ['\C-POL\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-POL\ Bulls (older than 2 years)', ['3.A.1.C-POL-a'], 6],
-            ['\C-POL\ Non-dairy Heifers (older than 2 years)', ['3.A.1.C-POL-b'], 6],
-            ['\C-POL\ Non-dairy Young Cattle (younger than 1 year)', ['3.A.1.C-POL-c'], 6],
-            ['\C-POL\ Dairy Cattle', ['3.A.1.C-POL-d'], 6],
-            ['\C-POL\ Non-dairy Young Cattle (1-2 years)', ['3.A.1.C-POL-e'], 6],
+            ['\\C-POL\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-POL\\ Bulls (older than 2 years)', ['3.A.1.C-POL-a'], 6],
+            ['\\C-POL\\ Non-dairy Heifers (older than 2 years)', ['3.A.1.C-POL-b'], 6],
+            ['\\C-POL\\ Non-dairy Young Cattle (younger than 1 year)', ['3.A.1.C-POL-c'], 6],
+            ['\\C-POL\\ Dairy Cattle', ['3.A.1.C-POL-d'], 6],
+            ['\\C-POL\\ Non-dairy Young Cattle (1-2 years)', ['3.A.1.C-POL-e'], 6],
             # Slovenia
             # Slovenia
-            ['\C-SVN\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-SVN\ Dairy cows', ['3.A.1.C-SVN-a'], 6],
-            ['\C-SVN\ Non-dairy cattle', ['3.A.1.C-SVN-b'], 6],
-            ['\C-SVN\ Other cows', ['3.A.1.C-SVN-c'], 6],
+            ['\\C-SVN\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-SVN\\ Dairy cows', ['3.A.1.C-SVN-a'], 6],
+            ['\\C-SVN\\ Non-dairy cattle', ['3.A.1.C-SVN-b'], 6],
+            ['\\C-SVN\\ Other cows', ['3.A.1.C-SVN-c'], 6],
             # USA
             # USA
-            ['\C-USA\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-USA\ Steer Stocker', ['3.A.1.C-USA-a'], 6],
-            ['\C-USA\ Heifer Stocker', ['3.A.1.C-USA-b'], 6],
-            ['\C-USA\ Beef Cows', ['3.A.1.C-USA-c'], 6],
-            ['\C-USA\ Dairy Replacements', ['3.A.1.C-USA-d'], 6],
-            ['\C-USA\ Beef Replacements', ['3.A.1.C-USA-e'], 6],
-            ['\C-USA\ Steer Feedlot', ['3.A.1.C-USA-f'], 6],
-            ['\C-USA\ Heifer Feedlot', ['3.A.1.C-USA-g'], 6],
-            ['\C-USA\ Bulls', ['3.A.1.C-USA-h'], 6],
-            ['\C-USA\ Dairy Cows', ['3.A.1.C-USA-i'], 6],
-            ['\C-USA\ Beef Calves', ['3.A.1.C-USA-j'], 6],
-            ['\C-USA\ Dairy Calves', ['3.A.1.C-USA-k'], 6],
+            ['\\C-USA\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-USA\\ Steer Stocker', ['3.A.1.C-USA-a'], 6],
+            ['\\C-USA\\ Heifer Stocker', ['3.A.1.C-USA-b'], 6],
+            ['\\C-USA\\ Beef Cows', ['3.A.1.C-USA-c'], 6],
+            ['\\C-USA\\ Dairy Replacements', ['3.A.1.C-USA-d'], 6],
+            ['\\C-USA\\ Beef Replacements', ['3.A.1.C-USA-e'], 6],
+            ['\\C-USA\\ Steer Feedlot', ['3.A.1.C-USA-f'], 6],
+            ['\\C-USA\\ Heifer Feedlot', ['3.A.1.C-USA-g'], 6],
+            ['\\C-USA\\ Bulls', ['3.A.1.C-USA-h'], 6],
+            ['\\C-USA\\ Dairy Cows', ['3.A.1.C-USA-i'], 6],
+            ['\\C-USA\\ Beef Calves', ['3.A.1.C-USA-j'], 6],
+            ['\\C-USA\\ Dairy Calves', ['3.A.1.C-USA-k'], 6],
             # Other livestock
             # Other livestock
             ['2. Sheep', ['3.A.2'], 3],
             ['2. Sheep', ['3.A.2'], 3],
             ['3. Swine', ['3.A.3'], 3],
             ['3. Swine', ['3.A.3'], 3],
@@ -1896,60 +1897,60 @@ CRF2022 = {
             # Manure Management
             # Manure Management
             ['B. Manure management', ['3.B'], 2],
             ['B. Manure management', ['3.B'], 2],
             ['1. Cattle(1)', ['3.B.1'], 3],
             ['1. Cattle(1)', ['3.B.1'], 3],
-            ['Option A:', ['\IGNORE'], 4],
+            ['Option A:', ['\\IGNORE'], 4],
             ['Dairy cattle', ['3.B.1.Aa'], 5],
             ['Dairy cattle', ['3.B.1.Aa'], 5],
             ['Non-dairy cattle', ['3.B.1.Ab'], 5],
             ['Non-dairy cattle', ['3.B.1.Ab'], 5],
-            ['Option B:', ['\IGNORE'], 4],
+            ['Option B:', ['\\IGNORE'], 4],
             ['Mature dairy cattle', ['3.B.1.Ba'], 5],
             ['Mature dairy cattle', ['3.B.1.Ba'], 5],
             ['Other mature cattle', ['3.B.1.Bb'], 5],
             ['Other mature cattle', ['3.B.1.Bb'], 5],
             ['Growing cattle', ['3.B.1.Bc'], 5],
             ['Growing cattle', ['3.B.1.Bc'], 5],
-            ['Option C (country-specific):', ['\IGNORE'], 4],
+            ['Option C (country-specific):', ['\\IGNORE'], 4],
             # all countries not specified explicitly
             # all countries not specified explicitly
-            ['\C!-AUS-MLT-LUX-POL-SVN-USA\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C!-AUS-MLT-LUX-POL-SVN-USA\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
             # Australia
             # Australia
-            ['\C-AUS\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-AUS\ Dairy Cattle', ['3.B.1.C-AUS-a'], 6],
-            ['\C-AUS\ Beef Cattle - Pasture', ['3.B.1.C-AUS-b'], 6],
-            ['\C-AUS\ Beef Cattle - Feedlot', ['3.B.1.C-AUS-c'], 6],
+            ['\\C-AUS\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-AUS\\ Dairy Cattle', ['3.B.1.C-AUS-a'], 6],
+            ['\\C-AUS\\ Beef Cattle - Pasture', ['3.B.1.C-AUS-b'], 6],
+            ['\\C-AUS\\ Beef Cattle - Feedlot', ['3.B.1.C-AUS-c'], 6],
             # Malta
             # Malta
-            ['\C-MLT\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-MLT\ dairy cows', ['3.B.1.C-MLT-a'], 6],
-            ['\C-MLT\ non-lactating cows', ['3.B.1.C-MLT-b'], 6],
-            ['\C-MLT\ bulls', ['3.B.1.C-MLT-c'], 6],
-            ['\C-MLT\ calves', ['3.B.1.C-MLT-d'], 6],
-            ['\C-MLT\ growing cattle 1-2 years', ['3.B.1.C-MLT-e'], 6],
+            ['\\C-MLT\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-MLT\\ dairy cows', ['3.B.1.C-MLT-a'], 6],
+            ['\\C-MLT\\ non-lactating cows', ['3.B.1.C-MLT-b'], 6],
+            ['\\C-MLT\\ bulls', ['3.B.1.C-MLT-c'], 6],
+            ['\\C-MLT\\ calves', ['3.B.1.C-MLT-d'], 6],
+            ['\\C-MLT\\ growing cattle 1-2 years', ['3.B.1.C-MLT-e'], 6],
             # Luxembourg
             # Luxembourg
-            ['\C-LUX\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-LUX\ Bulls', ['3.B.1.C-LUX-a'], 6],
-            ['\C-LUX\ Calves', ['3.B.1.C-LUX-b'], 6],
-            ['\C-LUX\ Young Cattle', ['3.B.1.C-LUX-c'], 6],
-            ['\C-LUX\ Suckler Cows', ['3.B.1.C-LUX-d'], 6],
-            ['\C-LUX\ Bulls under 2 years', ['3.B.1.C-LUX-e'], 6],
-            ['\C-LUX\ Dairy Cows', ['3.B.1.C-LUX-f'], 6],
+            ['\\C-LUX\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-LUX\\ Bulls', ['3.B.1.C-LUX-a'], 6],
+            ['\\C-LUX\\ Calves', ['3.B.1.C-LUX-b'], 6],
+            ['\\C-LUX\\ Young Cattle', ['3.B.1.C-LUX-c'], 6],
+            ['\\C-LUX\\ Suckler Cows', ['3.B.1.C-LUX-d'], 6],
+            ['\\C-LUX\\ Bulls under 2 years', ['3.B.1.C-LUX-e'], 6],
+            ['\\C-LUX\\ Dairy Cows', ['3.B.1.C-LUX-f'], 6],
             # Poland
             # Poland
-            ['\C-POL\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-POL\ Non-dairy Cattle', ['3.B.1.C-POL-a'], 6],
-            ['\C-POL\ Dairy Cattle', ['3.B.1.C-POL-b'], 6],
+            ['\\C-POL\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-POL\\ Non-dairy Cattle', ['3.B.1.C-POL-a'], 6],
+            ['\\C-POL\\ Dairy Cattle', ['3.B.1.C-POL-b'], 6],
             # Slovenia
             # Slovenia
-            ['\C-SVN\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-SVN\ Dairy cows', ['3.B.1.C-SVN-a'], 6],
-            ['\C-SVN\ Non-dairy cattle', ['3.B.1.C-SVN-b'], 6],
-            ['\C-SVN\ Other cows', ['3.B.1.C-SVN-c'], 6],
+            ['\\C-SVN\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-SVN\\ Dairy cows', ['3.B.1.C-SVN-a'], 6],
+            ['\\C-SVN\\ Non-dairy cattle', ['3.B.1.C-SVN-b'], 6],
+            ['\\C-SVN\\ Other cows', ['3.B.1.C-SVN-c'], 6],
             # USA
             # USA
-            ['\C-USA\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-USA\ Dairy Cattle', ['\IGNORE'], 6],
-            ['\C-USA\ Non-Dairy Cattle', ['\IGNORE'], 6],
-            ['\C-USA\ Steer Stocker', ['3.B.1.C-USA-a'], 6],
-            ['\C-USA\ Heifer Stocker', ['3.B.1.C-USA-b'], 6],
-            ['\C-USA\ Beef Cows', ['3.B.1.C-USA-c'], 6],
-            ['\C-USA\ Dairy Replacements', ['3.B.1.C-USA-d'], 6],
-            ['\C-USA\ Beef Replacements', ['3.B.1.C-USA-e'], 6],
-            ['\C-USA\ Steer Feedlot', ['3.B.1.C-USA-f'], 6],
-            ['\C-USA\ Heifer Feedlot', ['3.B.1.C-USA-g'], 6],
-            ['\C-USA\ Bulls', ['3.B.1.C-USA-h'], 6],
-            ['\C-USA\ Dairy Cows', ['3.B.1.C-USA-i'], 6],
-            ['\C-USA\ Beef Calves', ['3.B.1.C-USA-j'], 6],
-            ['\C-USA\ Dairy Calves', ['3.B.1.C-USA-k'], 6],
+            ['\\C-USA\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-USA\\ Dairy Cattle', ['\\IGNORE'], 6],
+            ['\\C-USA\\ Non-Dairy Cattle', ['\\IGNORE'], 6],
+            ['\\C-USA\\ Steer Stocker', ['3.B.1.C-USA-a'], 6],
+            ['\\C-USA\\ Heifer Stocker', ['3.B.1.C-USA-b'], 6],
+            ['\\C-USA\\ Beef Cows', ['3.B.1.C-USA-c'], 6],
+            ['\\C-USA\\ Dairy Replacements', ['3.B.1.C-USA-d'], 6],
+            ['\\C-USA\\ Beef Replacements', ['3.B.1.C-USA-e'], 6],
+            ['\\C-USA\\ Steer Feedlot', ['3.B.1.C-USA-f'], 6],
+            ['\\C-USA\\ Heifer Feedlot', ['3.B.1.C-USA-g'], 6],
+            ['\\C-USA\\ Bulls', ['3.B.1.C-USA-h'], 6],
+            ['\\C-USA\\ Dairy Cows', ['3.B.1.C-USA-i'], 6],
+            ['\\C-USA\\ Beef Calves', ['3.B.1.C-USA-j'], 6],
+            ['\\C-USA\\ Dairy Calves', ['3.B.1.C-USA-k'], 6],
             # other animals
             # other animals
             ['2. Sheep', ['3.B.2'], 3],
             ['2. Sheep', ['3.B.2'], 3],
             ['3. Swine', ['3.B.3'], 3],
             ['3. Swine', ['3.B.3'], 3],
@@ -2040,15 +2041,15 @@ CRF2022 = {
             ['Flood prone', ['3.C.2.a']],
             ['Flood prone', ['3.C.2.a']],
             ['Drought prone', ['3.C.2.b']],
             ['Drought prone', ['3.C.2.b']],
             ['3. Deep water', ['3.C.3']],
             ['3. Deep water', ['3.C.3']],
-            ['Water depth 50100 cm', ['3.C.3.a']],
+            ['Water depth 50-100 cm', ['3.C.3.a']],
             ['Water depth > 100 cm', ['3.C.3.b']],
             ['Water depth > 100 cm', ['3.C.3.b']],
             ['4. Other (please specify)', ['3.C.4']],
             ['4. Other (please specify)', ['3.C.4']],
             ['Non-specified', ['3.C.4.a']],  # EST
             ['Non-specified', ['3.C.4.a']],  # EST
             ['Other', ['3.C.4.a']],  # DEU
             ['Other', ['3.C.4.a']],  # DEU
             ['other', ['3.C.4.a']],  # LVA
             ['other', ['3.C.4.a']],  # LVA
             ['Other cultivation', ['3.C.4.a']],  # CZE
             ['Other cultivation', ['3.C.4.a']],  # CZE
-            ['Upland rice(4)', ['\IGNORE']],
-            ['Total(4)', ['\IGNORE']],
+            ['Upland rice(4)', ['\\IGNORE']],
+            ['Total(4)', ['\\IGNORE']],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             'EMISSIONS CH4': 'CH4',
             'EMISSIONS CH4': 'CH4',
@@ -2286,7 +2287,7 @@ CRF2022 = {
             ['Other waste', ['5.E.5']],  # CZE
             ['Other waste', ['5.E.5']],  # CZE
             ['5.E.1 Industrial Wastewater', ['5.E.8']],  # CAN, new in 2022
             ['5.E.1 Industrial Wastewater', ['5.E.8']],  # CAN, new in 2022
             ['Accidental Fires at SWDS', ['5.E.9']],  # AUS, new in 2022
             ['Accidental Fires at SWDS', ['5.E.9']],  # AUS, new in 2022
-            ['Memo item:(2)', ['\IGNORE']],
+            ['Memo item:(2)', ['\\IGNORE']],
             ['Long-term storage of C in waste disposal sites', ['M.Memo.LTSW']],
             ['Long-term storage of C in waste disposal sites', ['M.Memo.LTSW']],
             ['Annual change in total long-term C storage', ['M.Memo.ACLT']],
             ['Annual change in total long-term C storage', ['M.Memo.ACLT']],
             ['Annual change in total long-term C storage in HWP waste(3)', ['M.Memo.ACLTHWP']],
             ['Annual change in total long-term C storage in HWP waste(3)', ['M.Memo.ACLTHWP']],
@@ -2641,7 +2642,7 @@ CRF2022 = {
             "unit_info": unit_info["summary"],
             "unit_info": unit_info["summary"],
         },
         },
         "sector_mapping": [
         "sector_mapping": [
-            ['Memo items:(7)', ['\IGNORE']],
+            ['Memo items:(7)', ['\\IGNORE']],
             ['International bunkers', ['M.Memo.Int']],
             ['International bunkers', ['M.Memo.Int']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['Navigation', ['M.Memo.Int.Mar']],
             ['Navigation', ['M.Memo.Int.Mar']],

+ 95 - 94
UNFCCC_GHG_data/UNFCCC_CRF_reader/crf_specifications/CRF2023_AUS_specification.py → src/unfccc_ghg_data/unfccc_crf_reader/crf_specifications/crf2023_aus_specification.py

@@ -1,4 +1,4 @@
-""" CRF2023 specification for Australia.
+"""CRF2023 specification for Australia.
 Currently not all tables are included. Extend if you need all country
 Currently not all tables are included. Extend if you need all country
 specific items in categories 2, 3.H-G, 4
 specific items in categories 2, 3.H-G, 4
 
 
@@ -40,6 +40,7 @@ TODO:
 """
 """
 
 
 import numpy as np
 import numpy as np
+
 from .util import unit_info
 from .util import unit_info
 
 
 CRF2023_AUS = {
 CRF2023_AUS = {
@@ -104,7 +105,7 @@ CRF2023_AUS = {
             ["1.C.1. Transport of CO2", ["1.C.1"]],
             ["1.C.1. Transport of CO2", ["1.C.1"]],
             ["1.C.2. Injection and storage", ["1.C.2"]],
             ["1.C.2. Injection and storage", ["1.C.2"]],
             ["1.C.3. Other", ["1.C.3"]],
             ["1.C.3. Other", ["1.C.3"]],
-            ["1.D. Memo items: (3)", ["\IGNORE"]],
+            ["1.D. Memo items: (3)", ["\\IGNORE"]],
             ["1.D.1. International bunkers", ["M.Memo.Int"]],
             ["1.D.1. International bunkers", ["M.Memo.Int"]],
             ["1.D.1.a. Aviation", ["M.Memo.Int.Avi"]],
             ["1.D.1.a. Aviation", ["M.Memo.Int.Avi"]],
             ["1.D.1.b.Navigation", ["M.Memo.Int.Mar"]],
             ["1.D.1.b.Navigation", ["M.Memo.Int.Mar"]],
@@ -169,7 +170,7 @@ CRF2023_AUS = {
             ["Other fossil fuels (7)", ["1.A.1.a", "OtherFF"], 3],
             ["Other fossil fuels (7)", ["1.A.1.a", "OtherFF"], 3],
             ["Peat (8)", ["1.A.1.a", "Peat"], 3],
             ["Peat (8)", ["1.A.1.a", "Peat"], 3],
             ["Biomass (3)", ["1.A.1.a", "Biomass"], 3],
             ["Biomass (3)", ["1.A.1.a", "Biomass"], 3],
-            ["Drop-down list:", ["\IGNORE", "\IGNORE"], 3],  # (empty)
+            ["Drop-down list:", ["\\IGNORE", "\\IGNORE"], 3],  # (empty)
             # 1.A.1.a.i Electricity Generation
             # 1.A.1.a.i Electricity Generation
             ["1.A.1.a.i. Electricity generation", ["1.A.1.a.i", "Total"], 3],
             ["1.A.1.a.i. Electricity generation", ["1.A.1.a.i", "Total"], 3],
             ["Liquid fuels", ["1.A.1.a.i", "Liquid"], 4],
             ["Liquid fuels", ["1.A.1.a.i", "Liquid"], 4],
@@ -218,7 +219,7 @@ CRF2023_AUS = {
             ["Other fossil fuels (7)", ["1.A.1.c", "OtherFF"], 3],
             ["Other fossil fuels (7)", ["1.A.1.c", "OtherFF"], 3],
             ["Peat (8)", ["1.A.1.c", "Peat"], 3],
             ["Peat (8)", ["1.A.1.c", "Peat"], 3],
             ["Biomass (3)", ["1.A.1.c", "Biomass"], 3],
             ["Biomass (3)", ["1.A.1.c", "Biomass"], 3],
-            ["Drop-down list:", ["\IGNORE", "\IGNORE"], 3],  # (empty)
+            ["Drop-down list:", ["\\IGNORE", "\\IGNORE"], 3],  # (empty)
             # 1.A.1.c.i Manufacture of solid fuels
             # 1.A.1.c.i Manufacture of solid fuels
             ["1.A.1.c.i. Manufacture of solid fuels", ["1.A.1.c.i", "Total"], 3],
             ["1.A.1.c.i. Manufacture of solid fuels", ["1.A.1.c.i", "Total"], 3],
             ["Liquid fuels", ["1.A.1.c.i", "Liquid"], 4],
             ["Liquid fuels", ["1.A.1.c.i", "Liquid"], 4],
@@ -331,7 +332,7 @@ CRF2023_AUS = {
             ["Biomass (3)", ["1.A.2.f", "Biomass"], 2],
             ["Biomass (3)", ["1.A.2.f", "Biomass"], 2],
             # g. other
             # g. other
             ["1.A.2.g. Other (please specify) (11)", ["1.A.2.g", "Total"], 1],
             ["1.A.2.g. Other (please specify) (11)", ["1.A.2.g", "Total"], 1],
-            ["Dropdown list", ["\IGNORE", "\IGNORE"], 2],
+            ["Dropdown list", ["\\IGNORE", "\\IGNORE"], 2],
             # 1.A.2.g.i Manufacturing of machinery
             # 1.A.2.g.i Manufacturing of machinery
             ["1.A.2.g.i. Manufacturing of machinery", ["1.A.2.g.i", "Total"], 2],
             ["1.A.2.g.i. Manufacturing of machinery", ["1.A.2.g.i", "Total"], 2],
             ["Liquid fuels", ["1.A.2.g.i", "Liquid"], 3],
             ["Liquid fuels", ["1.A.2.g.i", "Liquid"], 3],
@@ -398,7 +399,7 @@ CRF2023_AUS = {
             ["Diesel oil", ["1.A.2.g.vii", "DieselOil"], 3],
             ["Diesel oil", ["1.A.2.g.vii", "DieselOil"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.2.g.vii", "LPG"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.2.g.vii", "LPG"], 3],
             ["Other liquid fuels (please specify)", ["1.A.2.g.vii", "OtherLiquid"], 3],
             ["Other liquid fuels (please specify)", ["1.A.2.g.vii", "OtherLiquid"], 3],
-            ["NA", ["\IGNORE", "\IGNORE"], 3],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 3],
             ["Gaseous fuels (6)", ["1.A.2.g.vii", "Gaseous"], 3],
             ["Gaseous fuels (6)", ["1.A.2.g.vii", "Gaseous"], 3],
             ["Other fossil fuels (7)", ["1.A.2.g.vii", "OtherFF"], 3],
             ["Other fossil fuels (7)", ["1.A.2.g.vii", "OtherFF"], 3],
             ["Biomass (3)", ["1.A.2.g.vii", "Biomass"], 3],
             ["Biomass (3)", ["1.A.2.g.vii", "Biomass"], 3],
@@ -454,7 +455,7 @@ CRF2023_AUS = {
             ["Diesel oil", ["1.A.3.b", "DieselOil"], 2],
             ["Diesel oil", ["1.A.3.b", "DieselOil"], 2],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b", "LPG"], 2],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b", "LPG"], 2],
             ["Other liquid fuels (please specify)", ["1.A.3.b", "OtherLiquid"], 2],
             ["Other liquid fuels (please specify)", ["1.A.3.b", "OtherLiquid"], 2],
-            ["NA", ["\IGNORE", "\IGNORE"], 3],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 3],
             ["Gaseous fuels (6)", ["1.A.3.b", "Gaseous"], 2],
             ["Gaseous fuels (6)", ["1.A.3.b", "Gaseous"], 2],
             ["Biomass (3)", ["1.A.3.b", "Biomass"], 2],
             ["Biomass (3)", ["1.A.3.b", "Biomass"], 2],
             ["Other fossil fuels (please specify) (7)", ["1.A.3.b", "OtherFF"], 2],
             ["Other fossil fuels (please specify) (7)", ["1.A.3.b", "OtherFF"], 2],
@@ -465,7 +466,7 @@ CRF2023_AUS = {
             ["Diesel oil", ["1.A.3.b.i", "DieselOil"], 3],
             ["Diesel oil", ["1.A.3.b.i", "DieselOil"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.i", "LPG"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.i", "LPG"], 3],
             ["Other liquid fuels (please specify)", ["1.A.3.b.i", "OtherLiquid"], 3],
             ["Other liquid fuels (please specify)", ["1.A.3.b.i", "OtherLiquid"], 3],
-            ["NA", ["\IGNORE", "\IGNORE"], 4],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 4],
             ["Gaseous fuels (6)", ["1.A.3.b.i", "Gaseous"], 3],
             ["Gaseous fuels (6)", ["1.A.3.b.i", "Gaseous"], 3],
             ["Biomass (3)", ["1.A.3.b.i", "Biomass"], 3],
             ["Biomass (3)", ["1.A.3.b.i", "Biomass"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.3.b.i", "OtherFF"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.3.b.i", "OtherFF"], 3],
@@ -476,7 +477,7 @@ CRF2023_AUS = {
             ["Diesel oil", ["1.A.3.b.ii", "DieselOil"], 3],
             ["Diesel oil", ["1.A.3.b.ii", "DieselOil"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.ii", "LPG"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.ii", "LPG"], 3],
             ["Other liquid fuels (please specify)", ["1.A.3.b.ii", "OtherLiquid"], 3],
             ["Other liquid fuels (please specify)", ["1.A.3.b.ii", "OtherLiquid"], 3],
-            ["NA", ["\IGNORE", "\IGNORE"], 4],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 4],
             ["Gaseous fuels (6)", ["1.A.3.b.ii", "Gaseous"], 3],
             ["Gaseous fuels (6)", ["1.A.3.b.ii", "Gaseous"], 3],
             ["Biomass (3)", ["1.A.3.b.ii", "Biomass"], 3],
             ["Biomass (3)", ["1.A.3.b.ii", "Biomass"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.3.b.ii", "OtherFF"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.3.b.ii", "OtherFF"], 3],
@@ -487,7 +488,7 @@ CRF2023_AUS = {
             ["Diesel oil", ["1.A.3.b.iii", "DieselOil"], 3],
             ["Diesel oil", ["1.A.3.b.iii", "DieselOil"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.iii", "LPG"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.iii", "LPG"], 3],
             ["Other liquid fuels (please specify)", ["1.A.3.b.iii", "OtherLiquid"], 3],
             ["Other liquid fuels (please specify)", ["1.A.3.b.iii", "OtherLiquid"], 3],
-            ["NA", ["\IGNORE", "\IGNORE"], 4],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 4],
             ["Gaseous fuels (6)", ["1.A.3.b.iii", "Gaseous"], 3],
             ["Gaseous fuels (6)", ["1.A.3.b.iii", "Gaseous"], 3],
             ["Biomass (3)", ["1.A.3.b.iii", "Biomass"], 3],
             ["Biomass (3)", ["1.A.3.b.iii", "Biomass"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.3.b.iii", "OtherFF"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.3.b.iii", "OtherFF"], 3],
@@ -498,19 +499,19 @@ CRF2023_AUS = {
             ["Diesel oil", ["1.A.3.b.iv", "DieselOil"], 3],
             ["Diesel oil", ["1.A.3.b.iv", "DieselOil"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.iv", "LPG"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.iv", "LPG"], 3],
             ["Other liquid fuels (please specify)", ["1.A.3.b.iv", "OtherLiquid"], 3],
             ["Other liquid fuels (please specify)", ["1.A.3.b.iv", "OtherLiquid"], 3],
-            ["NA", ["\IGNORE", "\IGNORE"], 4],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 4],
             ["Gaseous fuels (6)", ["1.A.3.b.iv", "Gaseous"], 3],
             ["Gaseous fuels (6)", ["1.A.3.b.iv", "Gaseous"], 3],
             ["Biomass (3)", ["1.A.3.b.iv", "Biomass"], 3],
             ["Biomass (3)", ["1.A.3.b.iv", "Biomass"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.3.b.iv", "OtherFF"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.3.b.iv", "OtherFF"], 3],
             ["Lubricants", ["1.A.3.b.iv", "OFFLubricants"], 4],
             ["Lubricants", ["1.A.3.b.iv", "OFFLubricants"], 4],
             # v. Other
             # v. Other
             ["1.A.3.b.v. Other (please specify)", ["1.A.3.b.v", "Total"], 2],
             ["1.A.3.b.v. Other (please specify)", ["1.A.3.b.v", "Total"], 2],
-            ["NA", ["\IGNORE", "\IGNORE"], 3],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 3],
             ["Gasoline", ["1.A.3.b.v", "Gasoline"], 4],
             ["Gasoline", ["1.A.3.b.v", "Gasoline"], 4],
             ["Diesel oil", ["1.A.3.b.v", "DieselOil"], 4],
             ["Diesel oil", ["1.A.3.b.v", "DieselOil"], 4],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.v", "LPG"], 4],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.v", "LPG"], 4],
             ["Other liquid fuels (please specify)", ["1.A.3.b.v", "OtherLiquid"], 4],
             ["Other liquid fuels (please specify)", ["1.A.3.b.v", "OtherLiquid"], 4],
-            ["NA", ["\IGNORE", "\IGNORE"], 5],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 5],
             ["Gaseous fuels (6)", ["1.A.3.b.v", "Gaseous"], 4],
             ["Gaseous fuels (6)", ["1.A.3.b.v", "Gaseous"], 4],
             ["Biomass (3)", ["1.A.3.b.v", "Biomass"], 4],
             ["Biomass (3)", ["1.A.3.b.v", "Biomass"], 4],
             ["Other fossil fuels (please specify)(7)", ["1.A.3.b.v", "OtherFF"], 4],
             ["Other fossil fuels (please specify)(7)", ["1.A.3.b.v", "OtherFF"], 4],
@@ -529,7 +530,7 @@ CRF2023_AUS = {
             ["Gas/diesel oil", ["1.A.3.d", "GasDieselOil"], 2],
             ["Gas/diesel oil", ["1.A.3.d", "GasDieselOil"], 2],
             ["Gasoline", ["1.A.3.d", "Gasoline"], 2],
             ["Gasoline", ["1.A.3.d", "Gasoline"], 2],
             ["Other liquid fuels (please specify)", ["1.A.3.d", "OtherLiquid"], 2],
             ["Other liquid fuels (please specify)", ["1.A.3.d", "OtherLiquid"], 2],
-            ["NA", ["\IGNORE", "\IGNORE"], 3],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 3],
             ["Gaseous fuels (6)", ["1.A.3.d", "Gaseous"], 2],
             ["Gaseous fuels (6)", ["1.A.3.d", "Gaseous"], 2],
             ["Biomass (3)", ["1.A.3.d", "Biomass"], 2],
             ["Biomass (3)", ["1.A.3.d", "Biomass"], 2],
             ["Other fossil fuels (please specify)(7)", ["1.A.3.d", "OtherFF"], 2],
             ["Other fossil fuels (please specify)(7)", ["1.A.3.d", "OtherFF"], 2],
@@ -557,7 +558,7 @@ CRF2023_AUS = {
             ["Diesel oil", ["1.A.3.e.ii.1", "DieselOil"], 4],
             ["Diesel oil", ["1.A.3.e.ii.1", "DieselOil"], 4],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.e.ii.1", "LPG"], 4],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.e.ii.1", "LPG"], 4],
             ["Other liquid fuels (please specify)", ["1.A.3.e.ii.1", "OtherLiquid"], 4],
             ["Other liquid fuels (please specify)", ["1.A.3.e.ii.1", "OtherLiquid"], 4],
-            ["NA", ["\IGNORE", "\IGNORE"], 5],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 5],
             ["Solid fuels", ["1.A.3.e.ii.1", "Solid"], 4],
             ["Solid fuels", ["1.A.3.e.ii.1", "Solid"], 4],
             ["Gaseous fuels (6)", ["1.A.3.e.ii.1", "Gaseous"], 4],
             ["Gaseous fuels (6)", ["1.A.3.e.ii.1", "Gaseous"], 4],
             ["Biomass (3)", ["1.A.3.e.ii.1", "Biomass"], 4],
             ["Biomass (3)", ["1.A.3.e.ii.1", "Biomass"], 4],
@@ -605,7 +606,7 @@ CRF2023_AUS = {
             ["Other fossil fuels (7)", ["1.A.4.a", "OtherFF"], 2],
             ["Other fossil fuels (7)", ["1.A.4.a", "OtherFF"], 2],
             ["Peat (8)", ["1.A.4.a", "Peat"], 2],
             ["Peat (8)", ["1.A.4.a", "Peat"], 2],
             ["Biomass (3)", ["1.A.4.a", "Biomass"], 2],
             ["Biomass (3)", ["1.A.4.a", "Biomass"], 2],
-            ["Drop-down list:", ["\IGNORE", "\IGNORE"], 2],  # (empty)
+            ["Drop-down list:", ["\\IGNORE", "\\IGNORE"], 2],  # (empty)
             # 1.A.4.a.i Stationary combustion
             # 1.A.4.a.i Stationary combustion
             ["1.A.4.a.i. Stationary combustion", ["1.A.4.a.i", "Total"], 2],
             ["1.A.4.a.i. Stationary combustion", ["1.A.4.a.i", "Total"], 2],
             ["Liquid fuels", ["1.A.4.a.i", "Liquid"], 3],
             ["Liquid fuels", ["1.A.4.a.i", "Liquid"], 3],
@@ -633,7 +634,7 @@ CRF2023_AUS = {
             ["Other fossil fuels (7)", ["1.A.4.b", "OtherFF"], 2],
             ["Other fossil fuels (7)", ["1.A.4.b", "OtherFF"], 2],
             ["Peat (8)", ["1.A.4.b", "Peat"], 2],
             ["Peat (8)", ["1.A.4.b", "Peat"], 2],
             ["Biomass (3)", ["1.A.4.b", "Biomass"], 2],
             ["Biomass (3)", ["1.A.4.b", "Biomass"], 2],
-            ["Drop-down list:", ["\IGNORE", "\IGNORE"], 2],  # (empty)
+            ["Drop-down list:", ["\\IGNORE", "\\IGNORE"], 2],  # (empty)
             # 1.A.4.b.i Stationary combustion
             # 1.A.4.b.i Stationary combustion
             ["1.A.4.b.i. Stationary combustion", ["1.A.4.b.i", "Total"], 2],
             ["1.A.4.b.i. Stationary combustion", ["1.A.4.b.i", "Total"], 2],
             ["Liquid fuels", ["1.A.4.b.i", "Liquid"], 3],
             ["Liquid fuels", ["1.A.4.b.i", "Liquid"], 3],
@@ -680,22 +681,22 @@ CRF2023_AUS = {
             ["Diesel oil", ["1.A.4.c.ii", "DieselOil"], 3],
             ["Diesel oil", ["1.A.4.c.ii", "DieselOil"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.4.c.ii", "LPG"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.4.c.ii", "LPG"], 3],
             ["Other liquid fuels (please specify)", ["1.A.4.c.ii", "OtherLiquid"], 3],
             ["Other liquid fuels (please specify)", ["1.A.4.c.ii", "OtherLiquid"], 3],
-            ["NA", ["\IGNORE", "\IGNORE"], 4],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 4],
             ["Gaseous fuels (6)", ["1.A.4.c.ii", "Gaseous"], 3],
             ["Gaseous fuels (6)", ["1.A.4.c.ii", "Gaseous"], 3],
             ["Biomass (3)", ["1.A.4.c.ii", "Biomass"], 3],
             ["Biomass (3)", ["1.A.4.c.ii", "Biomass"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.4.c.ii", "OtherFF"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.4.c.ii", "OtherFF"], 3],
-            ["NA", ["\IGNORE", "\IGNORE"], 4],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 4],
             # iii. Fishing
             # iii. Fishing
             ["1.A.4.c.iii. Fishing", ["1.A.4.c.iii", "Total"], 2],
             ["1.A.4.c.iii. Fishing", ["1.A.4.c.iii", "Total"], 2],
             ["Residual fuel oil", ["1.A.4.c.iii", "ResFuelOil"], 3],
             ["Residual fuel oil", ["1.A.4.c.iii", "ResFuelOil"], 3],
             ["Gas/diesel oil", ["1.A.4.c.iii", "GasDieselOil"], 3],
             ["Gas/diesel oil", ["1.A.4.c.iii", "GasDieselOil"], 3],
             ["Gasoline", ["1.A.4.c.iii", "Gasoline"], 3],
             ["Gasoline", ["1.A.4.c.iii", "Gasoline"], 3],
             ["Other liquid fuels (please specify)", ["1.A.4.c.iii", "OtherLiquid"], 3],
             ["Other liquid fuels (please specify)", ["1.A.4.c.iii", "OtherLiquid"], 3],
-            ["NA", ["\IGNORE", "\IGNORE"], 4],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 4],
             ["Gaseous fuels (6)", ["1.A.4.c.iii", "Gaseous"], 3],
             ["Gaseous fuels (6)", ["1.A.4.c.iii", "Gaseous"], 3],
             ["Biomass(3)", ["1.A.4.c.iii", "Biomass"], 3],
             ["Biomass(3)", ["1.A.4.c.iii", "Biomass"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.4.c.iii", "OtherFF"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.4.c.iii", "OtherFF"], 3],
-            ["NA", ["\IGNORE", "\IGNORE"], 4],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 4],
             # 1.A.5 Other (Not specified elsewhere)(14)
             # 1.A.5 Other (Not specified elsewhere)(14)
             ["1.A.5 Other (Not specified elsewhere)(15)", ["1.A.5", "Total"], 0],
             ["1.A.5 Other (Not specified elsewhere)(15)", ["1.A.5", "Total"], 0],
             ["Liquid fuels", ["1.A.5", "Liquid"], 1],
             ["Liquid fuels", ["1.A.5", "Liquid"], 1],
@@ -706,7 +707,7 @@ CRF2023_AUS = {
             ["Biomass (3)", ["1.A.5", "Biomass"], 1],
             ["Biomass (3)", ["1.A.5", "Biomass"], 1],
             # a. Stationary (please specify)
             # a. Stationary (please specify)
             ["1.A.5.a. Stationary (please specify)", ["1.A.5.a", "Total"], 1],
             ["1.A.5.a. Stationary (please specify)", ["1.A.5.a", "Total"], 1],
-            ["NA", ["\IGNORE", "\IGNORE"], 2],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 2],
             ["Liquid fuels", ["1.A.5.a", "Liquid"], 2],
             ["Liquid fuels", ["1.A.5.a", "Liquid"], 2],
             ["Solid fuels", ["1.A.5.a", "Solid"], 2],
             ["Solid fuels", ["1.A.5.a", "Solid"], 2],
             ["Gaseous fuels (6)", ["1.A.5.a", "Gaseous"], 2],
             ["Gaseous fuels (6)", ["1.A.5.a", "Gaseous"], 2],
@@ -722,14 +723,14 @@ CRF2023_AUS = {
             ["Other fossil fuels (7)", ["1.A.5.b.xii", "OtherFF"], 3],
             ["Other fossil fuels (7)", ["1.A.5.b.xii", "OtherFF"], 3],
             ["Biomass(3)", ["1.A.5.b.xii", "Biomass"], 3],
             ["Biomass(3)", ["1.A.5.b.xii", "Biomass"], 3],
             # Information Item
             # Information Item
-            ["Information item: (16)", ["\IGNORE", "\IGNORE"], 0],
+            ["Information item: (16)", ["\\IGNORE", "\\IGNORE"], 0],
             [
             [
                 "Waste incineration with energy recovery included as:",
                 "Waste incineration with energy recovery included as:",
-                ["\IGNORE", "\IGNORE"],
+                ["\\IGNORE", "\\IGNORE"],
                 1,
                 1,
             ],
             ],
-            ["Biomass (3)", ["\IGNORE", "\IGNORE"], 1],
-            ["Fossil fuels (7)", ["\IGNORE", "\IGNORE"], 1],
+            ["Biomass (3)", ["\\IGNORE", "\\IGNORE"], 1],
+            ["Fossil fuels (7)", ["\\IGNORE", "\\IGNORE"], 1],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             "EMISSIONS CH4": "CH4",
             "EMISSIONS CH4": "CH4",
@@ -766,22 +767,22 @@ CRF2023_AUS = {
                 2,
                 2,
             ],
             ],
             ["1.B.1.a.i.5. Other (please specify)", ["1.B.1.a.i.5"], 2],
             ["1.B.1.a.i.5. Other (please specify)", ["1.B.1.a.i.5"], 2],
-            ["NA", ["\IGNORE"], 3],
+            ["NA", ["\\IGNORE"], 3],
             ["1.B.1.a.ii. Surface mines (4)", ["1.B.1.a.ii"], 1],
             ["1.B.1.a.ii. Surface mines (4)", ["1.B.1.a.ii"], 1],
             ["1.B.1.a.ii.1. Mining activities", ["1.B.1.a.ii.1"], 2],
             ["1.B.1.a.ii.1. Mining activities", ["1.B.1.a.ii.1"], 2],
             ["1.B.1.a.ii.2. Post-mining activities", ["1.B.1.a.ii.2"], 2],
             ["1.B.1.a.ii.2. Post-mining activities", ["1.B.1.a.ii.2"], 2],
             ["1.B.1.a.ii.3. Other (please specify)", ["1.B.1.a.ii.3"], 2],
             ["1.B.1.a.ii.3. Other (please specify)", ["1.B.1.a.ii.3"], 2],
-            ["NA", ["\IGNORE"], 3],
+            ["NA", ["\\IGNORE"], 3],
             ["1. B. 1. b. Fuel transformation (6)", ["1.B.1.b"], 0],
             ["1. B. 1. b. Fuel transformation (6)", ["1.B.1.b"], 0],
-            ["Drop down list:", ["\IGNORE"], 1],
+            ["Drop down list:", ["\\IGNORE"], 1],
             ["1.B.1.b.i. Charcoal and biochar production (7)", ["1.B.1.b.i"], 1],
             ["1.B.1.b.i. Charcoal and biochar production (7)", ["1.B.1.b.i"], 1],
             ["1.B.1.b.ii. Coke production", ["1.B.1.b.ii"], 1],
             ["1.B.1.b.ii. Coke production", ["1.B.1.b.ii"], 1],
             ["1.B.1.b.iii. Coal to liquids", ["1.B.1.b.iii"], 1],
             ["1.B.1.b.iii. Coal to liquids", ["1.B.1.b.iii"], 1],
             ["1.B.1.b.iv. Gas to liquids", ["1.B.1.b.iv"], 1],
             ["1.B.1.b.iv. Gas to liquids", ["1.B.1.b.iv"], 1],
             ["1.B.1.b.v. Other (please specify)", ["1.B.1.b.v"], 1],
             ["1.B.1.b.v. Other (please specify)", ["1.B.1.b.v"], 1],
-            ["NA", ["\IGNORE"], 2],
+            ["NA", ["\\IGNORE"], 2],
             ["1. B. 1. c. Other (please specify) (8)", ["1.B.1.c"], 0],
             ["1. B. 1. c. Other (please specify) (8)", ["1.B.1.c"], 0],
-            ["NA", ["\IGNORE"], 1],
+            ["NA", ["\\IGNORE"], 1],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             "EMISSIONS (1) CH4": "CH4 emissions", # this is necessary because there
             "EMISSIONS (1) CH4": "CH4 emissions", # this is necessary because there
@@ -822,10 +823,10 @@ CRF2023_AUS = {
             ["1.B.2.a.iv. Refining/storage", ["1.B.2.a.4"], 1],
             ["1.B.2.a.iv. Refining/storage", ["1.B.2.a.4"], 1],
             ["1.B.2.a.v. Distribution of oil products", ["1.B.2.a.5"], 1],
             ["1.B.2.a.v. Distribution of oil products", ["1.B.2.a.5"], 1],
             ["1.B.2.a.vi. Other", ["1.B.2.a.6"], 1],
             ["1.B.2.a.vi. Other", ["1.B.2.a.6"], 1],
-            ["Drop down list:", ["\IGNORE"], 2],
+            ["Drop down list:", ["\\IGNORE"], 2],
             ["1.B.2.a.vi.1. Abandoned wells", ["1.B.2.a.6.1"], 2],
             ["1.B.2.a.vi.1. Abandoned wells", ["1.B.2.a.6.1"], 2],
             ["1.B.2.a.vi.2. Other (please specify)", ["1.B.1.a.6.2"], 2],
             ["1.B.2.a.vi.2. Other (please specify)", ["1.B.1.a.6.2"], 2],
-            ["NA", ["\IGNORE"], 3],
+            ["NA", ["\\IGNORE"], 3],
             ["1.B.2.b. Natural gas", ["1.B.2.b"], 0],
             ["1.B.2.b. Natural gas", ["1.B.2.b"], 0],
             ["1.B.2.b.i. Exploration", ["1.B.2.b.1"], 1],
             ["1.B.2.b.i. Exploration", ["1.B.2.b.1"], 1],
             ["1.B.2.b.ii. Production and gathering (8)", ["1.B.2.b.2"], 1],
             ["1.B.2.b.ii. Production and gathering (8)", ["1.B.2.b.2"], 1],
@@ -833,7 +834,7 @@ CRF2023_AUS = {
             ["1.B.2.b.iv. Transmission and storage", ["1.B.2.b.4"], 1],
             ["1.B.2.b.iv. Transmission and storage", ["1.B.2.b.4"], 1],
             ["1.B.2.b.v. Distribution", ["1.B.2.b.5"], 1],
             ["1.B.2.b.v. Distribution", ["1.B.2.b.5"], 1],
             ["1.B.2.b.vi. Other", ["1.B.2.b.6"], 1],
             ["1.B.2.b.vi. Other", ["1.B.2.b.6"], 1],
-            ["Drop down list:", ["\IGNORE"], 2],
+            ["Drop down list:", ["\\IGNORE"], 2],
             ["1.B.2.b.vi.1. Gas post-meter", ["1.B.2.b.6.1"], 3],
             ["1.B.2.b.vi.1. Gas post-meter", ["1.B.2.b.6.1"], 3],
             ["1.B.2.b.vi.2. Abandoned wells", ["1.B.2.b.6.2"], 3],
             ["1.B.2.b.vi.2. Abandoned wells", ["1.B.2.b.6.2"], 3],
             ["1.B.2.b.vi.3. Other (please specify)", ["1.B.2.b.6.3"], 3],
             ["1.B.2.b.vi.3. Other (please specify)", ["1.B.2.b.6.3"], 3],
@@ -850,7 +851,7 @@ CRF2023_AUS = {
             ["1.B.2.c.ii.2. Gas", ["1.B.2.c-fla.ii"], 2],
             ["1.B.2.c.ii.2. Gas", ["1.B.2.c-fla.ii"], 2],
             ["1.B.2.c.ii.3. Combined", ["1.B.2.c-fla.iii"], 2],
             ["1.B.2.c.ii.3. Combined", ["1.B.2.c-fla.iii"], 2],
             ["1.B.2.d. Other (please specify) (10)", ["1.B.2.d"], 0],
             ["1.B.2.d. Other (please specify) (10)", ["1.B.2.d"], 0],
-            ["NA", ["\IGNORE"], 1],
+            ["NA", ["\\IGNORE"], 1],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             "EMISSIONS CH4 (5)": "CH4",
             "EMISSIONS CH4 (5)": "CH4",
@@ -882,13 +883,13 @@ CRF2023_AUS = {
             ["1.C.1.a. Pipelines", ["1.C.1.a"], 1],
             ["1.C.1.a. Pipelines", ["1.C.1.a"], 1],
             ["1.C.1.b. Ships", ["1.C.1.b"], 1],
             ["1.C.1.b. Ships", ["1.C.1.b"], 1],
             ["1.C.1.c. Other (please specify)", ["1.C.1.c"], 1],
             ["1.C.1.c. Other (please specify)", ["1.C.1.c"], 1],
-            ["NA", ["\IGNORE"], 2],
+            ["NA", ["\\IGNORE"], 2],
             ["1.C.2. Injection and storage (3)", ["1.C.2"], 0],
             ["1.C.2. Injection and storage (3)", ["1.C.2"], 0],
             ["1.C.2.a. Injection", ["1.C.2.a"], 1],
             ["1.C.2.a. Injection", ["1.C.2.a"], 1],
             ["1.C.2.b. Storage", ["1.C.2.b"], 1],
             ["1.C.2.b. Storage", ["1.C.2.b"], 1],
             ["1.C.3. Other (please specify)", ["1.C.3"], 0],
             ["1.C.3. Other (please specify)", ["1.C.3"], 0],
-            ["NA", ["\IGNORE"], 1],
-            ["Information item (4, 5, 6)", ["\IGNORE"], 0],
+            ["NA", ["\\IGNORE"], 1],
+            ["Information item (4, 5, 6)", ["\\IGNORE"], 0],
             ["Total amount captured for storage (7)", ["M.Info.A.TACS"], 1],
             ["Total amount captured for storage (7)", ["M.Info.A.TACS"], 1],
             ["Total amount of imports for storage (7)", ["M.Info.A.TAIS"], 1],
             ["Total amount of imports for storage (7)", ["M.Info.A.TAIS"], 1],
             ["Total A", ["M.Info.A"], 1],
             ["Total A", ["M.Info.A"], 1],
@@ -901,7 +902,7 @@ CRF2023_AUS = {
                 1,
                 1,
             ],
             ],
             ["Total B", ["M.Info.B"], 1],
             ["Total B", ["M.Info.B"], 1],
-            ["Difference (A-B)(6)", ["\IGNORE"], 1],
+            ["Difference (A-B)(6)", ["\\IGNORE"], 1],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             "EMISSIONS CO2 (2)": "CO2",
             "EMISSIONS CO2 (2)": "CO2",
@@ -1097,10 +1098,10 @@ CRF2023_AUS = {
             ["3. Total agriculture", ["3"], 0],
             ["3. Total agriculture", ["3"], 0],
             # A. Enteric fermentation
             # A. Enteric fermentation
             ["3.A. Enteric fermentation", ["3.A"], 1],
             ["3.A. Enteric fermentation", ["3.A"], 1],
-            ["Option A:", ["\IGNORE"], 2],
+            ["Option A:", ["\\IGNORE"], 2],
             ["3.A.1.a. Dairy cattle", ["3.A.1.Aa"], 3],
             ["3.A.1.a. Dairy cattle", ["3.A.1.Aa"], 3],
             ["3.A.1.b. Non-dairy cattle", ["3.A.1.Ab"], 3],
             ["3.A.1.b. Non-dairy cattle", ["3.A.1.Ab"], 3],
-            ["Option B (country-specific):", ["\IGNORE"], 2],
+            ["Option B (country-specific):", ["\\IGNORE"], 2],
             ["3.A.1.a. Other", ["3.A.1.C"], 3],
             ["3.A.1.a. Other", ["3.A.1.C"], 3],
             # Other livestock
             # Other livestock
             ["3.A.2. Sheep", ["3.A.2"], 2],
             ["3.A.2. Sheep", ["3.A.2"], 2],
@@ -1109,10 +1110,10 @@ CRF2023_AUS = {
             # Manure Management
             # Manure Management
             ["3.B. Manure management", ["3.B"], 1],
             ["3.B. Manure management", ["3.B"], 1],
             ["3.B.1. Cattle(3)", ["3.B.1"], 2],
             ["3.B.1. Cattle(3)", ["3.B.1"], 2],
-            ["Option A:", ["\IGNORE"], 3],
+            ["Option A:", ["\\IGNORE"], 3],
             ["3.B.1.a. Dairy cattle", ["3.B.1.Aa"], 4],
             ["3.B.1.a. Dairy cattle", ["3.B.1.Aa"], 4],
             ["3.B.1.b. Non-dairy cattle", ["3.B.1.Ab"], 4],
             ["3.B.1.b. Non-dairy cattle", ["3.B.1.Ab"], 4],
-            ["Option B (country-specific):", ["\IGNORE"], 3],
+            ["Option B (country-specific):", ["\\IGNORE"], 3],
             ["3.B.1.a. Other", ["3.B.1.C"], 4],
             ["3.B.1.a. Other", ["3.B.1.C"], 4],
             ["3.B.2. Sheep", ["3.B.2"], 2],
             ["3.B.2. Sheep", ["3.B.2"], 2],
             ["3.B.3. Swine", ["3.B.3"], 2],
             ["3.B.3. Swine", ["3.B.3"], 2],
@@ -1140,7 +1141,7 @@ CRF2023_AUS = {
             ["3.H. Urea application", ["3.H"], 1],
             ["3.H. Urea application", ["3.H"], 1],
             ["3.I. Other carbon-containing fertilizers", ["3.I"], 1],
             ["3.I. Other carbon-containing fertilizers", ["3.I"], 1],
             ["3.J. Other (please specify)", ["3.J"], 1],
             ["3.J. Other (please specify)", ["3.J"], 1],
-            ["NA", ["\IGNORE"], 2],
+            ["NA", ["\\IGNORE"], 2],
         ],
         ],
         "entity_mapping": {"Total GHG emissions (1)": "KYOTOGHG (AR4GWP100)"},
         "entity_mapping": {"Total GHG emissions (1)": "KYOTOGHG (AR4GWP100)"},
         "coords_defaults": {
         "coords_defaults": {
@@ -1166,27 +1167,27 @@ CRF2023_AUS = {
         },
         },
         "sector_mapping": [
         "sector_mapping": [
             ["3.A.1. Cattle", ["3.A.1"], 0],
             ["3.A.1. Cattle", ["3.A.1"], 0],
-            ["Option A:", ["\IGNORE"], 1],
+            ["Option A:", ["\\IGNORE"], 1],
             ["3.A.1.a. Dairy cattle", ["3.A.1.Aa"], 2],
             ["3.A.1.a. Dairy cattle", ["3.A.1.Aa"], 2],
             ["3.A.1.b. Non-dairy cattle", ["3.A.1.Ab"], 2],
             ["3.A.1.b. Non-dairy cattle", ["3.A.1.Ab"], 2],
-            ["Option B (country-specific): (3)", ["\IGNORE"], 1],
-            ["3.A.1.a. Other", ["\IGNORE"], 2],
-            ["Drop-down list:", ["\IGNORE"], 3],
-            ["3.A.1.a.i. Mature dairy cattle", ["\IGNORE"], 3],
-            ["3.A.1.a.ii. Other mature cattle", ["\IGNORE"], 3],
-            ["3.A.1.a.iii. Growing cattle", ["\IGNORE"], 3],
+            ["Option B (country-specific): (3)", ["\\IGNORE"], 1],
+            ["3.A.1.a. Other", ["\\IGNORE"], 2],
+            ["Drop-down list:", ["\\IGNORE"], 3],
+            ["3.A.1.a.i. Mature dairy cattle", ["\\IGNORE"], 3],
+            ["3.A.1.a.ii. Other mature cattle", ["\\IGNORE"], 3],
+            ["3.A.1.a.iii. Growing cattle", ["\\IGNORE"], 3],
             ["3.A.1.a.iv. Other (please specify)", ["3.A.1.C"], 3],
             ["3.A.1.a.iv. Other (please specify)", ["3.A.1.C"], 3],
             ["Dairy Cattle", ["3.A.1.C-AUS-a"], 4],
             ["Dairy Cattle", ["3.A.1.C-AUS-a"], 4],
             ["Beef Cattle - Pasture", ["3.A.1.C-AUS-b"], 4],
             ["Beef Cattle - Pasture", ["3.A.1.C-AUS-b"], 4],
             ["Beef Cattle - Feedlot", ["3.A.1.C-AUS-c"], 4],
             ["Beef Cattle - Feedlot", ["3.A.1.C-AUS-c"], 4],
             ["3.A.2. Sheep", ["3.A.2"], 0],
             ["3.A.2. Sheep", ["3.A.2"], 0],
-            ["3.A.2.a. Other (please specify)", ["\IGNORE"], 1],
-            ["Sheep", ["\IGNORE"], 2],
+            ["3.A.2.a. Other (please specify)", ["\\IGNORE"], 1],
+            ["Sheep", ["\\IGNORE"], 2],
             ["3.A.3. Swine", ["3.A.3"], 0],
             ["3.A.3. Swine", ["3.A.3"], 0],
-            ["3.A.3.a. Other (please specify)", ["\IGNORE"], 1],
-            ["Swine", ["\IGNORE"], 2],
+            ["3.A.3.a. Other (please specify)", ["\\IGNORE"], 1],
+            ["Swine", ["\\IGNORE"], 2],
             ["3.A.4. Other livestock (please specify) (4)", ["3.A.4"], 0],
             ["3.A.4. Other livestock (please specify) (4)", ["3.A.4"], 0],
-            ["Drop down list:", ["\IGNORE"], 1],
+            ["Drop down list:", ["\\IGNORE"], 1],
             ["3.A.4.a. Buffalo", ["3.A.4.a"], 2],
             ["3.A.4.a. Buffalo", ["3.A.4.a"], 2],
             ["3.A.4.b. Camels", ["3.A.4.b"], 2],
             ["3.A.4.b. Camels", ["3.A.4.b"], 2],
             ["3.A.4.c. Deer", ["3.A.4.c"], 2],
             ["3.A.4.c. Deer", ["3.A.4.c"], 2],
@@ -1200,7 +1201,7 @@ CRF2023_AUS = {
             ["3.A.4.h.iii. Ostrich", ["3.A.4.h.iii"], 3],
             ["3.A.4.h.iii. Ostrich", ["3.A.4.h.iii"], 3],
             ["3.A.4.h.iv. Fur-bearing animals (5)", ["3.A.4.h.iv"], 3],
             ["3.A.4.h.iv. Fur-bearing animals (5)", ["3.A.4.h.iv"], 3],
             ["3.A.4.h.v. Other (please specity)", ["3.A.4.h.v"], 3],
             ["3.A.4.h.v. Other (please specity)", ["3.A.4.h.v"], 3],
-            ["Alpacas", ["\IGNORE"], 4],
+            ["Alpacas", ["\\IGNORE"], 4],
         ],
         ],
         "entity_mapping": {"EMISSIONS CH4": "CH4"},
         "entity_mapping": {"EMISSIONS CH4": "CH4"},
         "coords_defaults": {
         "coords_defaults": {
@@ -1230,27 +1231,27 @@ CRF2023_AUS = {
         },
         },
         "sector_mapping": [
         "sector_mapping": [
             ["3.B.1. Cattle", ["3.B.1"], 0],
             ["3.B.1. Cattle", ["3.B.1"], 0],
-            ["Option A:", ["\IGNORE"], 1],
+            ["Option A:", ["\\IGNORE"], 1],
             ["3.B.1.a. Dairy cattle", ["3.B.1.Aa"], 2],
             ["3.B.1.a. Dairy cattle", ["3.B.1.Aa"], 2],
             ["3.B.1.b. Non-dairy cattle", ["3.B.1.Ab"], 2],
             ["3.B.1.b. Non-dairy cattle", ["3.B.1.Ab"], 2],
-            ["Option B (country-specific): (3)", ["\IGNORE"], 1],
-            ["3.B.1.a. Other", ["\IGNORE"], 2],
-            ["Drop down list:", ["\IGNORE"], 3],
-            ["3.B.1.a.i. Mature dairy cattle", ["\IGNORE"], 3],
-            ["3.B.1.a.ii. Other mature cattle", ["\IGNORE"], 3],
-            ["3.B.1.a.iii. Growing cattle", ["\IGNORE"], 3],
+            ["Option B (country-specific): (3)", ["\\IGNORE"], 1],
+            ["3.B.1.a. Other", ["\\IGNORE"], 2],
+            ["Drop down list:", ["\\IGNORE"], 3],
+            ["3.B.1.a.i. Mature dairy cattle", ["\\IGNORE"], 3],
+            ["3.B.1.a.ii. Other mature cattle", ["\\IGNORE"], 3],
+            ["3.B.1.a.iii. Growing cattle", ["\\IGNORE"], 3],
             ["3.B.1.a.iv. Other (please specify)", ["3.B.1.C"], 3],
             ["3.B.1.a.iv. Other (please specify)", ["3.B.1.C"], 3],
             ["Dairy Cattle", ["3.B.1.C-AUS-a"], 4],
             ["Dairy Cattle", ["3.B.1.C-AUS-a"], 4],
             ["Beef Cattle - Pasture", ["3.B.1.C-AUS-b"], 4],
             ["Beef Cattle - Pasture", ["3.B.1.C-AUS-b"], 4],
             ["Beef Cattle - Feedlot", ["3.B.1.C-AUS-c"], 4],
             ["Beef Cattle - Feedlot", ["3.B.1.C-AUS-c"], 4],
             ["3.B.2. Sheep", ["3.B.2"], 0],
             ["3.B.2. Sheep", ["3.B.2"], 0],
-            ["3.B.2.a. Other (please specify)", ["\IGNORE"], 1],
-            ["Sheep", ["\IGNORE"], 2],
+            ["3.B.2.a. Other (please specify)", ["\\IGNORE"], 1],
+            ["Sheep", ["\\IGNORE"], 2],
             ["3.B.3. Swine", ["3.B.3"], 0],
             ["3.B.3. Swine", ["3.B.3"], 0],
-            ["3.B.3.a. Other (please specify)", ["\IGNORE"], 1],
-            ["Swine", ["\IGNORE"], 2],
+            ["3.B.3.a. Other (please specify)", ["\\IGNORE"], 1],
+            ["Swine", ["\\IGNORE"], 2],
             ["3.B.4. Other livestock (4)", ["3.B.4"], 0],
             ["3.B.4. Other livestock (4)", ["3.B.4"], 0],
-            ["Drop-down list:", ["\IGNORE"], 1],
+            ["Drop-down list:", ["\\IGNORE"], 1],
             ["3.B.4.a. Buffalo", ["3.B.4.a"], 2],
             ["3.B.4.a. Buffalo", ["3.B.4.a"], 2],
             ["3.B.4.b. Camels", ["3.B.4.b"], 2],
             ["3.B.4.b. Camels", ["3.B.4.b"], 2],
             ["3.B.4.c. Deer", ["3.B.4.c"], 2],
             ["3.B.4.c. Deer", ["3.B.4.c"], 2],
@@ -1264,7 +1265,7 @@ CRF2023_AUS = {
             ["3.B.4.h.iii. Ostrich", ["3.B.4.h.iii"], 3],
             ["3.B.4.h.iii. Ostrich", ["3.B.4.h.iii"], 3],
             ["3.B.4.h.iv. Fur-bearing animals (5)", ["3.B.4.h.iv"], 3],
             ["3.B.4.h.iv. Fur-bearing animals (5)", ["3.B.4.h.iv"], 3],
             ["3.B.4.h.v. Other (please specity)", ["3.B.4.h.v"], 3],
             ["3.B.4.h.v. Other (please specity)", ["3.B.4.h.v"], 3],
-            ["Alpacas", ["\IGNORE"], 4],
+            ["Alpacas", ["\\IGNORE"], 4],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             "EMISSIONS CH4 producing potential (Bo) (2) (average) CH4": "CH4"
             "EMISSIONS CH4 producing potential (Bo) (2) (average) CH4": "CH4"
@@ -1330,27 +1331,27 @@ CRF2023_AUS = {
         },
         },
         "sector_mapping": [
         "sector_mapping": [
             ["3.B.1. Cattle", ["3.B.1"], 0],
             ["3.B.1. Cattle", ["3.B.1"], 0],
-            ["Option A:", ["\IGNORE"], 1],
+            ["Option A:", ["\\IGNORE"], 1],
             ["3.B.1.a. Dairy cattle", ["3.B.1.Aa"], 2],
             ["3.B.1.a. Dairy cattle", ["3.B.1.Aa"], 2],
             ["3.B.1.b. Non-dairy cattle", ["3.B.1.Ab"], 2],
             ["3.B.1.b. Non-dairy cattle", ["3.B.1.Ab"], 2],
-            ["Option B (country-specific): (5)", ["\IGNORE"], 1],
-            ["3.B.1.a. Other", ["\IGNORE"], 2],
-            ["Drop-down list", ["\IGNORE"], 3],
-            ["3.B.1.a.i. Mature dairy cattle", ["\IGNORE"], 3],
-            ["3.B.1.a.ii. Other mature cattle", ["\IGNORE"], 3],
-            ["3.B.1.a.iii. Growing cattle", ["\IGNORE"], 3],
+            ["Option B (country-specific): (5)", ["\\IGNORE"], 1],
+            ["3.B.1.a. Other", ["\\IGNORE"], 2],
+            ["Drop-down list", ["\\IGNORE"], 3],
+            ["3.B.1.a.i. Mature dairy cattle", ["\\IGNORE"], 3],
+            ["3.B.1.a.ii. Other mature cattle", ["\\IGNORE"], 3],
+            ["3.B.1.a.iii. Growing cattle", ["\\IGNORE"], 3],
             ["3.B.1.a.iv. Other (please specify)", ["3.B.1.C"], 3],
             ["3.B.1.a.iv. Other (please specify)", ["3.B.1.C"], 3],
             ["Dairy Cattle", ["3.B.1.C-AUS-a"], 4],
             ["Dairy Cattle", ["3.B.1.C-AUS-a"], 4],
             ["Beef Cattle - Pasture", ["3.B.1.C-AUS-b"], 4],
             ["Beef Cattle - Pasture", ["3.B.1.C-AUS-b"], 4],
             ["Beef Cattle - Feedlot", ["3.B.1.C-AUS-c"], 4],
             ["Beef Cattle - Feedlot", ["3.B.1.C-AUS-c"], 4],
             ["3.B.2. Sheep", ["3.B.2"], 0],
             ["3.B.2. Sheep", ["3.B.2"], 0],
-            ["3.B.2.a. Other (please specify)", ["\IGNORE"], 1],
-            ["Sheep", ["\IGNORE"], 2],
+            ["3.B.2.a. Other (please specify)", ["\\IGNORE"], 1],
+            ["Sheep", ["\\IGNORE"], 2],
             ["3.B.3. Swine", ["3.B.3"], 0],
             ["3.B.3. Swine", ["3.B.3"], 0],
-            ["3.B.3.a. Other (please specify)", ["\IGNORE"], 1],
-            ["Swine", ["\IGNORE"], 2],
+            ["3.B.3.a. Other (please specify)", ["\\IGNORE"], 1],
+            ["Swine", ["\\IGNORE"], 2],
             ["3.B.4. Other livestock (6)", ["3.B.4"], 0],
             ["3.B.4. Other livestock (6)", ["3.B.4"], 0],
-            ["Drop-down list", ["\IGNORE"], 1],
+            ["Drop-down list", ["\\IGNORE"], 1],
             ["3.B.4.a. Buffalo", ["3.B.4.a"], 2],
             ["3.B.4.a. Buffalo", ["3.B.4.a"], 2],
             ["3.B.4.b. Camels", ["3.B.4.b"], 2],
             ["3.B.4.b. Camels", ["3.B.4.b"], 2],
             ["3.B.4.c. Deer", ["3.B.4.c"], 2],
             ["3.B.4.c. Deer", ["3.B.4.c"], 2],
@@ -1364,7 +1365,7 @@ CRF2023_AUS = {
             ["3.B.4.h.iii. Ostrich", ["3.B.4.h.iii"], 3],
             ["3.B.4.h.iii. Ostrich", ["3.B.4.h.iii"], 3],
             ["3.B.4.h.iv Fur-bearing animals (7)", ["3.B.4.h.iv"], 3],
             ["3.B.4.h.iv Fur-bearing animals (7)", ["3.B.4.h.iv"], 3],
             ["3.B.4.h.v. Other (please specity)", ["3.B.4.h.v"], 3],
             ["3.B.4.h.v. Other (please specity)", ["3.B.4.h.v"], 3],
-            ["Alpacas", ["\IGNORE"], 4],
+            ["Alpacas", ["\\IGNORE"], 4],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             "EMISSIONS N2O Direct Nitrogen leaching and run-off": "N2O",
             "EMISSIONS N2O Direct Nitrogen leaching and run-off": "N2O",
@@ -1400,12 +1401,12 @@ CRF2023_AUS = {
             ["3.C.2.a. Flood-prone", ["3.C.2.a"]],
             ["3.C.2.a. Flood-prone", ["3.C.2.a"]],
             ["3.C.2.b. Drought-prone", ["3.C.2.b"]],
             ["3.C.2.b. Drought-prone", ["3.C.2.b"]],
             ["3.C.3. Deep water", ["3.C.3"]],
             ["3.C.3. Deep water", ["3.C.3"]],
-            ["3.C.3.a. Water depth 50100 cm", ["3.C.3.a"]],
+            ["3.C.3.a. Water depth 50-100 cm", ["3.C.3.a"]],
             ["3.C.3.b. Water depth > 100 cm", ["3.C.3.b"]],
             ["3.C.3.b. Water depth > 100 cm", ["3.C.3.b"]],
             ["3.C.4. Other (please specify)", ["3.C.4"]],
             ["3.C.4. Other (please specify)", ["3.C.4"]],
-            ["NA", ["\IGNORE"]],
-            ["Upland rice(4)", ["\IGNORE"]],
-            ["Total(4)", ["\IGNORE"]],
+            ["NA", ["\\IGNORE"]],
+            ["Upland rice(4)", ["\\IGNORE"]],
+            ["Total(4)", ["\\IGNORE"]],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             "EMISSIONS CH4": "CH4",
             "EMISSIONS CH4": "CH4",
@@ -1484,9 +1485,9 @@ CRF2023_AUS = {
         },
         },
         "sector_mapping": [
         "sector_mapping": [
             ["3.E.1. Forest land (specify ecological zone) (2)", ["3.E.1"], 0],
             ["3.E.1. Forest land (specify ecological zone) (2)", ["3.E.1"], 0],
-            ["NA", ["\IGNORE"], 1],
+            ["NA", ["\\IGNORE"], 1],
             ["3.E.2. Grassland (specify ecological zone) (2)", ["3.E.2"], 0],
             ["3.E.2. Grassland (specify ecological zone) (2)", ["3.E.2"], 0],
-            ["NA", ["\IGNORE"], 1],
+            ["NA", ["\\IGNORE"], 1],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             "EMISSIONS (2) CH4": "CH4",
             "EMISSIONS (2) CH4": "CH4",
@@ -1612,7 +1613,7 @@ CRF2023_AUS = {
             ["5.D.3. Other", ["5.D.3"]],
             ["5.D.3. Other", ["5.D.3"]],
             ["5.E. Other (please specify)", ["5.E"]],
             ["5.E. Other (please specify)", ["5.E"]],
             ["Accidential fires at Solid Waste Disposal Sites", ["5.E.9"]],
             ["Accidential fires at Solid Waste Disposal Sites", ["5.E.9"]],
-            ["Memo item: (3)", ["\IGNORE"]],
+            ["Memo item: (3)", ["\\IGNORE"]],
             ["5.F.1. Long-term storage of C in waste disposal sites", ["M.Memo.LTSW"]],
             ["5.F.1. Long-term storage of C in waste disposal sites", ["M.Memo.LTSW"]],
             ["5.F.1.a. Annual change in total long-term C storage", ["M.Memo.ACLT"]],
             ["5.F.1.a. Annual change in total long-term C storage", ["M.Memo.ACLT"]],
             [
             [
@@ -1693,10 +1694,10 @@ CRF2023_AUS = {
             ["5.D. Wastewater treatment and discharge", ["5.D"]],
             ["5.D. Wastewater treatment and discharge", ["5.D"]],
             ["5.E. Other (6)", ["5.E"]],
             ["5.E. Other (6)", ["5.E"]],
             ["6. Other (please specify) (7)", ["6"]],
             ["6. Other (please specify) (7)", ["6"]],
-            ["NA", ["\IGNORE"]],
-            ["", ["\IGNORE"]],
-            [np.nan, ["\IGNORE"]],
-            ["Memo items: (8)", ["\IGNORE"]],
+            ["NA", ["\\IGNORE"]],
+            ["", ["\\IGNORE"]],
+            [np.nan, ["\\IGNORE"]],
+            ["Memo items: (8)", ["\\IGNORE"]],
             ["1.D.1. International bunkers", ["M.Memo.Int"]],
             ["1.D.1. International bunkers", ["M.Memo.Int"]],
             ["1.D.1.a. Aviation", ["M.Memo.Int.Avi"]],
             ["1.D.1.a. Aviation", ["M.Memo.Int.Avi"]],
             ["1.D.1.b. Navigation", ["M.Memo.Int.Mar"]],
             ["1.D.1.b. Navigation", ["M.Memo.Int.Mar"]],

+ 102 - 101
UNFCCC_GHG_data/UNFCCC_CRF_reader/crf_specifications/CRF2023_specification.py → src/unfccc_ghg_data/unfccc_crf_reader/crf_specifications/crf2023_specification.py

@@ -1,4 +1,4 @@
-""" CRF2022 specification.
+"""CRF2022 specification.
 Currently not all tables are included. Extend if you need all country
 Currently not all tables are included. Extend if you need all country
 specific items in categories 2, 3.H-G, 4
 specific items in categories 2, 3.H-G, 4
 
 
@@ -40,6 +40,7 @@ TODO:
 """
 """
 
 
 import numpy as np
 import numpy as np
+
 from .util import unit_info
 from .util import unit_info
 
 
 # TODO: GWPs now differ by country. This has to be implemented (maybe giving
 # TODO: GWPs now differ by country. This has to be implemented (maybe giving
@@ -122,7 +123,7 @@ CRF2023 = {
             ['1. Transport of CO2', ['1.C.1']],
             ['1. Transport of CO2', ['1.C.1']],
             ['2. Injection and storage', ['1.C.2']],
             ['2. Injection and storage', ['1.C.2']],
             ['3. Other', ['1.C.3']],
             ['3. Other', ['1.C.3']],
-            ['Memo items: (1)', ['\IGNORE']],
+            ['Memo items: (1)', ['\\IGNORE']],
             ['International bunkers', ['M.Memo.Int']],
             ['International bunkers', ['M.Memo.Int']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['Navigation', ['M.Memo.Int.Mar']],
             ['Navigation', ['M.Memo.Int.Mar']],
@@ -455,8 +456,8 @@ CRF2023 = {
             # 1.A.2.g.viii Other (please specify)
             # 1.A.2.g.viii Other (please specify)
             ['1.A.2.g.viii Other (please specify)', ['1.A.2.g.viii', 'Total'], 2],
             ['1.A.2.g.viii Other (please specify)', ['1.A.2.g.viii', 'Total'], 2],
             # DKE
             # DKE
-            ['Construction', ['\IGNORE', '\IGNORE'], 3],  # (empty)
-            ['Mining', ['\IGNORE', '\IGNORE'], 3],  # (empty)
+            ['Construction', ['\\IGNORE', '\\IGNORE'], 3],  # (empty)
+            ['Mining', ['\\IGNORE', '\\IGNORE'], 3],  # (empty)
             # DNK, DKE, USA, CZE
             # DNK, DKE, USA, CZE
             ['Other non-specified', ['1.A.2.g.viii.1', 'Total'], 3],
             ['Other non-specified', ['1.A.2.g.viii.1', 'Total'], 3],
             ['Liquid Fuels', ['1.A.2.g.viii.1', 'Liquid'], 4],
             ['Liquid Fuels', ['1.A.2.g.viii.1', 'Liquid'], 4],
@@ -506,7 +507,7 @@ CRF2023 = {
             ['Peat', ['1.A.2.g.viii.1', 'Peat'], 4],
             ['Peat', ['1.A.2.g.viii.1', 'Peat'], 4],
             ['Biomass', ['1.A.2.g.viii.1', 'Biomass'], 4],
             ['Biomass', ['1.A.2.g.viii.1', 'Biomass'], 4],
             # DKE
             # DKE
-            ['Textile', ['\IGNORE', '\IGNORE'], 3],  # (empty)
+            ['Textile', ['\\IGNORE', '\\IGNORE'], 3],  # (empty)
             # DNK, DNM, FIN, DKE
             # DNK, DNM, FIN, DKE
             ['Other manufacturing industries', ['1.A.2.g.viii.3', 'Total'], 3],
             ['Other manufacturing industries', ['1.A.2.g.viii.3', 'Total'], 3],
             ['Liquid Fuels', ['1.A.2.g.viii.3', 'Liquid'], 4],
             ['Liquid Fuels', ['1.A.2.g.viii.3', 'Liquid'], 4],
@@ -1419,10 +1420,10 @@ CRF2023 = {
             ['iii. Mobile (other)', ['1.A.5.b.iv', 'Total'], 2],
             ['iii. Mobile (other)', ['1.A.5.b.iv', 'Total'], 2],
             ['Liquid Fuels', ['1.A.5.b.iv', 'Liquid'], 3],
             ['Liquid Fuels', ['1.A.5.b.iv', 'Liquid'], 3],
             # Information Item
             # Information Item
-            ['Information item:(15)', ['\IGNORE', '\IGNORE'], 0],
-            ['Waste incineration with energy recovery included as:', ['\IGNORE', '\IGNORE'], 1],
-            ['Biomass(6)', ['\IGNORE', '\IGNORE'], 1],
-            ['Fossil fuels(4)', ['\IGNORE', '\IGNORE'], 1],
+            ['Information item:(15)', ['\\IGNORE', '\\IGNORE'], 0],
+            ['Waste incineration with energy recovery included as:', ['\\IGNORE', '\\IGNORE'], 1],
+            ['Biomass(6)', ['\\IGNORE', '\\IGNORE'], 1],
+            ['Fossil fuels(4)', ['\\IGNORE', '\\IGNORE'], 1],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             'EMISSIONS CH4': "CH4",
             'EMISSIONS CH4': "CH4",
@@ -1570,7 +1571,7 @@ CRF2023 = {
             ['a. Injection', ['1.C.2.a']],
             ['a. Injection', ['1.C.2.a']],
             ['b. Storage', ['1.C.2.b']],
             ['b. Storage', ['1.C.2.b']],
             ['3. Other', ['1.C.3']],
             ['3. Other', ['1.C.3']],
-            ['Information item(4, 5)', ['\IGNORE']],
+            ['Information item(4, 5)', ['\\IGNORE']],
             ['Total amount captured for storage', ['M.Info.A.TACS']],
             ['Total amount captured for storage', ['M.Info.A.TACS']],
             ['Total amount of imports for storage', ['M.Info.A.TAIS']],
             ['Total amount of imports for storage', ['M.Info.A.TAIS']],
             ['Total A', ['M.Info.A']],
             ['Total A', ['M.Info.A']],
@@ -1578,7 +1579,7 @@ CRF2023 = {
             ['Total amount of CO2 injected at storage sites', ['M.Info.B.TAI']],
             ['Total amount of CO2 injected at storage sites', ['M.Info.B.TAI']],
             ['Total leakage from transport, injection and storage', ['M.Info.B.TLTIS']],
             ['Total leakage from transport, injection and storage', ['M.Info.B.TLTIS']],
             ['Total B', ['M.Info.B']],
             ['Total B', ['M.Info.B']],
-            ['Difference (A-B)(6)', ['\IGNORE']],
+            ['Difference (A-B)(6)', ['\\IGNORE']],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             'EMISSIONS CO2(2)': 'CO2',
             'EMISSIONS CO2(2)': 'CO2',
@@ -1837,61 +1838,61 @@ CRF2023 = {
             # A. Enteric fermentation
             # A. Enteric fermentation
             ['A. Enteric fermentation', ['3.A'], 2],
             ['A. Enteric fermentation', ['3.A'], 2],
             ['1. Cattle(1)', ['3.A.1'], 3],
             ['1. Cattle(1)', ['3.A.1'], 3],
-            ['Option A:', ['\IGNORE'], 4],
+            ['Option A:', ['\\IGNORE'], 4],
             ['Dairy cattle', ['3.A.1.Aa'], 5],
             ['Dairy cattle', ['3.A.1.Aa'], 5],
             ['Non-dairy cattle', ['3.A.1.Ab'], 5],
             ['Non-dairy cattle', ['3.A.1.Ab'], 5],
-            ['Option B:', ['\IGNORE'], 4],
+            ['Option B:', ['\\IGNORE'], 4],
             ['Mature dairy cattle', ['3.A.1.Ba'], 5],
             ['Mature dairy cattle', ['3.A.1.Ba'], 5],
             ['Other mature cattle', ['3.A.1.Bb'], 5],
             ['Other mature cattle', ['3.A.1.Bb'], 5],
             ['Growing cattle', ['3.A.1.Bc'], 5],
             ['Growing cattle', ['3.A.1.Bc'], 5],
-            ['Option C (country-specific):', ['\IGNORE'], 4],
+            ['Option C (country-specific):', ['\\IGNORE'], 4],
             # all countries not specified explcitly
             # all countries not specified explcitly
-            ['\C!-AUS-MLT-LUX-POL-SVN-USA\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C!-AUS-MLT-LUX-POL-SVN-USA\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
             # Australia
             # Australia
-            ['\C-AUS\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-AUS\ Dairy Cattle', ['3.A.1.C-AUS-a'], 6],
-            ['\C-AUS\ Beef Cattle - Pasture', ['3.A.1.C-AUS-b'], 6],
-            ['\C-AUS\ Beef Cattle - Feedlot', ['3.A.1.C-AUS-c'], 6],
+            ['\\C-AUS\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-AUS\\ Dairy Cattle', ['3.A.1.C-AUS-a'], 6],
+            ['\\C-AUS\\ Beef Cattle - Pasture', ['3.A.1.C-AUS-b'], 6],
+            ['\\C-AUS\\ Beef Cattle - Feedlot', ['3.A.1.C-AUS-c'], 6],
             # malta
             # malta
-            ['\C-MLT\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-MLT\ dairy cows', ['3.A.1.C-MLT-a'], 6],
-            ['\C-MLT\ non-lactating cows', ['3.A.1.C-MLT-b'], 6],
-            ['\C-MLT\ bulls', ['3.A.1.C-MLT-c'], 6],
-            ['\C-MLT\ calves', ['3.A.1.C-MLT-d'], 6],
-            ['\C-MLT\ growing cattle 1-2 years', ['3.A.1.C-MLT-e'], 6],
+            ['\\C-MLT\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-MLT\\ dairy cows', ['3.A.1.C-MLT-a'], 6],
+            ['\\C-MLT\\ non-lactating cows', ['3.A.1.C-MLT-b'], 6],
+            ['\\C-MLT\\ bulls', ['3.A.1.C-MLT-c'], 6],
+            ['\\C-MLT\\ calves', ['3.A.1.C-MLT-d'], 6],
+            ['\\C-MLT\\ growing cattle 1-2 years', ['3.A.1.C-MLT-e'], 6],
             # Luxembourg
             # Luxembourg
-            ['\C-LUX\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-LUX\ Bulls', ['3.A.1.C-LUX-a'], 6],
-            ['\C-LUX\ Calves', ['3.A.1.C-LUX-b'], 6],
-            ['\C-LUX\ Young Cattle', ['3.A.1.C-LUX-c'], 6],
-            ['\C-LUX\ Suckler Cows', ['3.A.1.C-LUX-d'], 6],
-            ['\C-LUX\ Bulls under 2 years', ['3.A.1.C-LUX-e'], 6],
-            ['\C-LUX\ Dairy Cows', ['3.A.1.C-LUX-f'], 6],
+            ['\\C-LUX\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-LUX\\ Bulls', ['3.A.1.C-LUX-a'], 6],
+            ['\\C-LUX\\ Calves', ['3.A.1.C-LUX-b'], 6],
+            ['\\C-LUX\\ Young Cattle', ['3.A.1.C-LUX-c'], 6],
+            ['\\C-LUX\\ Suckler Cows', ['3.A.1.C-LUX-d'], 6],
+            ['\\C-LUX\\ Bulls under 2 years', ['3.A.1.C-LUX-e'], 6],
+            ['\\C-LUX\\ Dairy Cows', ['3.A.1.C-LUX-f'], 6],
             # Poland
             # Poland
-            ['\C-POL\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-POL\ Bulls (older than 2 years)', ['3.A.1.C-POL-a'], 6],
-            ['\C-POL\ Non-dairy Heifers (older than 2 years)', ['3.A.1.C-POL-b'], 6],
-            ['\C-POL\ Non-dairy Young Cattle (younger than 1 year)', ['3.A.1.C-POL-c'], 6],
-            ['\C-POL\ Dairy Cattle', ['3.A.1.C-POL-d'], 6],
-            ['\C-POL\ Non-dairy Young Cattle (1-2 years)', ['3.A.1.C-POL-e'], 6],
+            ['\\C-POL\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-POL\\ Bulls (older than 2 years)', ['3.A.1.C-POL-a'], 6],
+            ['\\C-POL\\ Non-dairy Heifers (older than 2 years)', ['3.A.1.C-POL-b'], 6],
+            ['\\C-POL\\ Non-dairy Young Cattle (younger than 1 year)', ['3.A.1.C-POL-c'], 6],
+            ['\\C-POL\\ Dairy Cattle', ['3.A.1.C-POL-d'], 6],
+            ['\\C-POL\\ Non-dairy Young Cattle (1-2 years)', ['3.A.1.C-POL-e'], 6],
             # Slovenia
             # Slovenia
-            ['\C-SVN\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-SVN\ Dairy cows', ['3.A.1.C-SVN-a'], 6],
-            ['\C-SVN\ Non-dairy cattle', ['3.A.1.C-SVN-b'], 6],
-            ['\C-SVN\ Other cows', ['3.A.1.C-SVN-c'], 6],
+            ['\\C-SVN\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-SVN\\ Dairy cows', ['3.A.1.C-SVN-a'], 6],
+            ['\\C-SVN\\ Non-dairy cattle', ['3.A.1.C-SVN-b'], 6],
+            ['\\C-SVN\\ Other cows', ['3.A.1.C-SVN-c'], 6],
             # USA
             # USA
-            ['\C-USA\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
-            ['\C-USA\ Steer Stocker', ['3.A.1.C-USA-a'], 6],
-            ['\C-USA\ Heifer Stocker', ['3.A.1.C-USA-b'], 6],
-            ['\C-USA\ Beef Cows', ['3.A.1.C-USA-c'], 6],
-            ['\C-USA\ Dairy Replacements', ['3.A.1.C-USA-d'], 6],
-            ['\C-USA\ Beef Replacements', ['3.A.1.C-USA-e'], 6],
-            ['\C-USA\ Steer Feedlot', ['3.A.1.C-USA-f'], 6],
-            ['\C-USA\ Heifer Feedlot', ['3.A.1.C-USA-g'], 6],
-            ['\C-USA\ Bulls', ['3.A.1.C-USA-h'], 6],
-            ['\C-USA\ Dairy Cows', ['3.A.1.C-USA-i'], 6],
-            ['\C-USA\ Beef Calves', ['3.A.1.C-USA-j'], 6],
-            ['\C-USA\ Dairy Calves', ['3.A.1.C-USA-k'], 6],
+            ['\\C-USA\\ Other (as specified in table 3(I).A)', ['3.A.1.C'], 5],
+            ['\\C-USA\\ Steer Stocker', ['3.A.1.C-USA-a'], 6],
+            ['\\C-USA\\ Heifer Stocker', ['3.A.1.C-USA-b'], 6],
+            ['\\C-USA\\ Beef Cows', ['3.A.1.C-USA-c'], 6],
+            ['\\C-USA\\ Dairy Replacements', ['3.A.1.C-USA-d'], 6],
+            ['\\C-USA\\ Beef Replacements', ['3.A.1.C-USA-e'], 6],
+            ['\\C-USA\\ Steer Feedlot', ['3.A.1.C-USA-f'], 6],
+            ['\\C-USA\\ Heifer Feedlot', ['3.A.1.C-USA-g'], 6],
+            ['\\C-USA\\ Bulls', ['3.A.1.C-USA-h'], 6],
+            ['\\C-USA\\ Dairy Cows', ['3.A.1.C-USA-i'], 6],
+            ['\\C-USA\\ Beef Calves', ['3.A.1.C-USA-j'], 6],
+            ['\\C-USA\\ Dairy Calves', ['3.A.1.C-USA-k'], 6],
             # Other livestock
             # Other livestock
             ['2. Sheep', ['3.A.2'], 3],
             ['2. Sheep', ['3.A.2'], 3],
             ['3. Swine', ['3.A.3'], 3],
             ['3. Swine', ['3.A.3'], 3],
@@ -1912,60 +1913,60 @@ CRF2023 = {
             # Manure Management
             # Manure Management
             ['B. Manure management', ['3.B'], 2],
             ['B. Manure management', ['3.B'], 2],
             ['1. Cattle(1)', ['3.B.1'], 3],
             ['1. Cattle(1)', ['3.B.1'], 3],
-            ['Option A:', ['\IGNORE'], 4],
+            ['Option A:', ['\\IGNORE'], 4],
             ['Dairy cattle', ['3.B.1.Aa'], 5],
             ['Dairy cattle', ['3.B.1.Aa'], 5],
             ['Non-dairy cattle', ['3.B.1.Ab'], 5],
             ['Non-dairy cattle', ['3.B.1.Ab'], 5],
-            ['Option B:', ['\IGNORE'], 4],
+            ['Option B:', ['\\IGNORE'], 4],
             ['Mature dairy cattle', ['3.B.1.Ba'], 5],
             ['Mature dairy cattle', ['3.B.1.Ba'], 5],
             ['Other mature cattle', ['3.B.1.Bb'], 5],
             ['Other mature cattle', ['3.B.1.Bb'], 5],
             ['Growing cattle', ['3.B.1.Bc'], 5],
             ['Growing cattle', ['3.B.1.Bc'], 5],
-            ['Option C (country-specific):', ['\IGNORE'], 4],
+            ['Option C (country-specific):', ['\\IGNORE'], 4],
             # all countries not specified explicitly
             # all countries not specified explicitly
-            ['\C!-AUS-MLT-LUX-POL-SVN-USA\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C!-AUS-MLT-LUX-POL-SVN-USA\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
             # Australia
             # Australia
-            ['\C-AUS\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-AUS\ Dairy Cattle', ['3.B.1.C-AUS-a'], 6],
-            ['\C-AUS\ Beef Cattle - Pasture', ['3.B.1.C-AUS-b'], 6],
-            ['\C-AUS\ Beef Cattle - Feedlot', ['3.B.1.C-AUS-c'], 6],
+            ['\\C-AUS\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-AUS\\ Dairy Cattle', ['3.B.1.C-AUS-a'], 6],
+            ['\\C-AUS\\ Beef Cattle - Pasture', ['3.B.1.C-AUS-b'], 6],
+            ['\\C-AUS\\ Beef Cattle - Feedlot', ['3.B.1.C-AUS-c'], 6],
             # Malta
             # Malta
-            ['\C-MLT\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-MLT\ dairy cows', ['3.B.1.C-MLT-a'], 6],
-            ['\C-MLT\ non-lactating cows', ['3.B.1.C-MLT-b'], 6],
-            ['\C-MLT\ bulls', ['3.B.1.C-MLT-c'], 6],
-            ['\C-MLT\ calves', ['3.B.1.C-MLT-d'], 6],
-            ['\C-MLT\ growing cattle 1-2 years', ['3.B.1.C-MLT-e'], 6],
+            ['\\C-MLT\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-MLT\\ dairy cows', ['3.B.1.C-MLT-a'], 6],
+            ['\\C-MLT\\ non-lactating cows', ['3.B.1.C-MLT-b'], 6],
+            ['\\C-MLT\\ bulls', ['3.B.1.C-MLT-c'], 6],
+            ['\\C-MLT\\ calves', ['3.B.1.C-MLT-d'], 6],
+            ['\\C-MLT\\ growing cattle 1-2 years', ['3.B.1.C-MLT-e'], 6],
             # Luxembourg
             # Luxembourg
-            ['\C-LUX\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-LUX\ Bulls', ['3.B.1.C-LUX-a'], 6],
-            ['\C-LUX\ Calves', ['3.B.1.C-LUX-b'], 6],
-            ['\C-LUX\ Young Cattle', ['3.B.1.C-LUX-c'], 6],
-            ['\C-LUX\ Suckler Cows', ['3.B.1.C-LUX-d'], 6],
-            ['\C-LUX\ Bulls under 2 years', ['3.B.1.C-LUX-e'], 6],
-            ['\C-LUX\ Dairy Cows', ['3.B.1.C-LUX-f'], 6],
+            ['\\C-LUX\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-LUX\\ Bulls', ['3.B.1.C-LUX-a'], 6],
+            ['\\C-LUX\\ Calves', ['3.B.1.C-LUX-b'], 6],
+            ['\\C-LUX\\ Young Cattle', ['3.B.1.C-LUX-c'], 6],
+            ['\\C-LUX\\ Suckler Cows', ['3.B.1.C-LUX-d'], 6],
+            ['\\C-LUX\\ Bulls under 2 years', ['3.B.1.C-LUX-e'], 6],
+            ['\\C-LUX\\ Dairy Cows', ['3.B.1.C-LUX-f'], 6],
             # Poland
             # Poland
-            ['\C-POL\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-POL\ Non-dairy Cattle', ['3.B.1.C-POL-a'], 6],
-            ['\C-POL\ Dairy Cattle', ['3.B.1.C-POL-b'], 6],
+            ['\\C-POL\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-POL\\ Non-dairy Cattle', ['3.B.1.C-POL-a'], 6],
+            ['\\C-POL\\ Dairy Cattle', ['3.B.1.C-POL-b'], 6],
             # Slovenia
             # Slovenia
-            ['\C-SVN\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-SVN\ Dairy cows', ['3.B.1.C-SVN-a'], 6],
-            ['\C-SVN\ Non-dairy cattle', ['3.B.1.C-SVN-b'], 6],
-            ['\C-SVN\ Other cows', ['3.B.1.C-SVN-c'], 6],
+            ['\\C-SVN\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-SVN\\ Dairy cows', ['3.B.1.C-SVN-a'], 6],
+            ['\\C-SVN\\ Non-dairy cattle', ['3.B.1.C-SVN-b'], 6],
+            ['\\C-SVN\\ Other cows', ['3.B.1.C-SVN-c'], 6],
             # USA
             # USA
-            ['\C-USA\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
-            ['\C-USA\ Dairy Cattle', ['\IGNORE'], 6],
-            ['\C-USA\ Non-Dairy Cattle', ['\IGNORE'], 6],
-            ['\C-USA\ Steer Stocker', ['3.B.1.C-USA-a'], 6],
-            ['\C-USA\ Heifer Stocker', ['3.B.1.C-USA-b'], 6],
-            ['\C-USA\ Beef Cows', ['3.B.1.C-USA-c'], 6],
-            ['\C-USA\ Dairy Replacements', ['3.B.1.C-USA-d'], 6],
-            ['\C-USA\ Beef Replacements', ['3.B.1.C-USA-e'], 6],
-            ['\C-USA\ Steer Feedlot', ['3.B.1.C-USA-f'], 6],
-            ['\C-USA\ Heifer Feedlot', ['3.B.1.C-USA-g'], 6],
-            ['\C-USA\ Bulls', ['3.B.1.C-USA-h'], 6],
-            ['\C-USA\ Dairy Cows', ['3.B.1.C-USA-i'], 6],
-            ['\C-USA\ Beef Calves', ['3.B.1.C-USA-j'], 6],
-            ['\C-USA\ Dairy Calves', ['3.B.1.C-USA-k'], 6],
+            ['\\C-USA\\ Other (as specified in table 3(I).B)', ['3.B.1.C'], 5],
+            ['\\C-USA\\ Dairy Cattle', ['\\IGNORE'], 6],
+            ['\\C-USA\\ Non-Dairy Cattle', ['\\IGNORE'], 6],
+            ['\\C-USA\\ Steer Stocker', ['3.B.1.C-USA-a'], 6],
+            ['\\C-USA\\ Heifer Stocker', ['3.B.1.C-USA-b'], 6],
+            ['\\C-USA\\ Beef Cows', ['3.B.1.C-USA-c'], 6],
+            ['\\C-USA\\ Dairy Replacements', ['3.B.1.C-USA-d'], 6],
+            ['\\C-USA\\ Beef Replacements', ['3.B.1.C-USA-e'], 6],
+            ['\\C-USA\\ Steer Feedlot', ['3.B.1.C-USA-f'], 6],
+            ['\\C-USA\\ Heifer Feedlot', ['3.B.1.C-USA-g'], 6],
+            ['\\C-USA\\ Bulls', ['3.B.1.C-USA-h'], 6],
+            ['\\C-USA\\ Dairy Cows', ['3.B.1.C-USA-i'], 6],
+            ['\\C-USA\\ Beef Calves', ['3.B.1.C-USA-j'], 6],
+            ['\\C-USA\\ Dairy Calves', ['3.B.1.C-USA-k'], 6],
             # other animals
             # other animals
             ['2. Sheep', ['3.B.2'], 3],
             ['2. Sheep', ['3.B.2'], 3],
             ['3. Swine', ['3.B.3'], 3],
             ['3. Swine', ['3.B.3'], 3],
@@ -2056,15 +2057,15 @@ CRF2023 = {
             ['Flood prone', ['3.C.2.a']],
             ['Flood prone', ['3.C.2.a']],
             ['Drought prone', ['3.C.2.b']],
             ['Drought prone', ['3.C.2.b']],
             ['3. Deep water', ['3.C.3']],
             ['3. Deep water', ['3.C.3']],
-            ['Water depth 50100 cm', ['3.C.3.a']],
+            ['Water depth 50-100 cm', ['3.C.3.a']],
             ['Water depth > 100 cm', ['3.C.3.b']],
             ['Water depth > 100 cm', ['3.C.3.b']],
             ['4. Other (please specify)', ['3.C.4']],
             ['4. Other (please specify)', ['3.C.4']],
             ['Non-specified', ['3.C.4.a']],  # EST
             ['Non-specified', ['3.C.4.a']],  # EST
             ['Other', ['3.C.4.a']],  # DEU
             ['Other', ['3.C.4.a']],  # DEU
             ['other', ['3.C.4.a']],  # LVA
             ['other', ['3.C.4.a']],  # LVA
             ['Other cultivation', ['3.C.4.a']],  # CZE
             ['Other cultivation', ['3.C.4.a']],  # CZE
-            ['Upland rice(4)', ['\IGNORE']],
-            ['Total(4)', ['\IGNORE']],
+            ['Upland rice(4)', ['\\IGNORE']],
+            ['Total(4)', ['\\IGNORE']],
         ],
         ],
         "entity_mapping": {
         "entity_mapping": {
             'EMISSIONS CH4': 'CH4',
             'EMISSIONS CH4': 'CH4',
@@ -2304,7 +2305,7 @@ CRF2023 = {
             ['Other waste', ['5.E.5']],  # CZE
             ['Other waste', ['5.E.5']],  # CZE
             ['5.E.1 Industrial Wastewater', ['5.E.8']],  # CAN, new in 2022
             ['5.E.1 Industrial Wastewater', ['5.E.8']],  # CAN, new in 2022
             ['Accidental Fires at SWDS', ['5.E.9']],  # AUS, new in 2022
             ['Accidental Fires at SWDS', ['5.E.9']],  # AUS, new in 2022
-            ['Memo item:(2)', ['\IGNORE']],
+            ['Memo item:(2)', ['\\IGNORE']],
             ['Long-term storage of C in waste disposal sites', ['M.Memo.LTSW']],
             ['Long-term storage of C in waste disposal sites', ['M.Memo.LTSW']],
             ['Annual change in total long-term C storage', ['M.Memo.ACLT']],
             ['Annual change in total long-term C storage', ['M.Memo.ACLT']],
             ['Annual change in total long-term C storage in HWP waste(3)', ['M.Memo.ACLTHWP']],
             ['Annual change in total long-term C storage in HWP waste(3)', ['M.Memo.ACLTHWP']],
@@ -2663,7 +2664,7 @@ CRF2023 = {
             "unit_info": unit_info["summary"],
             "unit_info": unit_info["summary"],
         },
         },
         "sector_mapping": [
         "sector_mapping": [
-            ['Memo items:(7)', ['\IGNORE']],
+            ['Memo items:(7)', ['\\IGNORE']],
             ['International bunkers', ['M.Memo.Int']],
             ['International bunkers', ['M.Memo.Int']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['Navigation', ['M.Memo.Int.Mar']],
             ['Navigation', ['M.Memo.Int.Mar']],

+ 2 - 2
UNFCCC_GHG_data/UNFCCC_CRF_reader/crf_specifications/util.py → src/unfccc_ghg_data/unfccc_crf_reader/crf_specifications/util.py

@@ -1,4 +1,4 @@
-""" Some definitions used for several CRF specifications"""
+"""Some definitions used for several CRF specifications"""
 
 
 unit_info = {
 unit_info = {
     "default": {
     "default": {
@@ -46,4 +46,4 @@ unit_info = {
         },
         },
         "default_unit": "kt",
         "default_unit": "kt",
     },
     },
-}
+}

+ 2 - 2
UNFCCC_GHG_data/UNFCCC_CRF_reader/read_new_UNFCCC_CRF_for_year.py → src/unfccc_ghg_data/unfccc_crf_reader/read_new_unfccc_crf_for_year.py

@@ -3,10 +3,10 @@ This script is a wrapper around the read_crf_for_country
 function such that it can be called from datalad
 function such that it can be called from datalad
 """
 """
 
 
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.UNFCCC_CRF_reader_prod import \
-    read_new_crf_for_year
 import argparse
 import argparse
 
 
+from unfccc_ghg_data.unfccc_crf_reader.unfccc_crf_reader_prod import read_new_crf_for_year
+
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 #parser.add_argument('--countries', help='List of country codes', default=None)
 #parser.add_argument('--countries', help='List of country codes', default=None)
 parser.add_argument('--submission_year', help='Submission round to read', type=int)
 parser.add_argument('--submission_year', help='Submission round to read', type=int)

+ 4 - 3
UNFCCC_GHG_data/UNFCCC_CRF_reader/read_new_UNFCCC_CRF_for_year_datalad.py → src/unfccc_ghg_data/unfccc_crf_reader/read_new_unfccc_crf_for_year_datalad.py

@@ -4,10 +4,11 @@ from doit in the current setup where doit runs on system python and
 not in the venv.
 not in the venv.
 """
 """
 
 
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.UNFCCC_CRF_reader_prod import read_new_crf_for_year_datalad
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.util import NoCRFFilesError
 import argparse
 import argparse
 
 
+from unfccc_ghg_data.unfccc_crf_reader.unfccc_crf_reader_prod import read_new_crf_for_year_datalad
+from unfccc_ghg_data.unfccc_crf_reader.util import NoCRFFilesError
+
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 #parser.add_argument('--countries', help='List of country codes', default=None)
 #parser.add_argument('--countries', help='List of country codes', default=None)
 parser.add_argument('--submission_year', help='Submission round to read')
 parser.add_argument('--submission_year', help='Submission round to read')
@@ -29,4 +30,4 @@ try:
         re_read=re_read
         re_read=re_read
     )
     )
 except NoCRFFilesError as err:
 except NoCRFFilesError as err:
-    print(f"NoCRFFilesError: {err}")
+    print(f"NoCRFFilesError: {err}")

+ 2 - 1
UNFCCC_GHG_data/UNFCCC_CRF_reader/read_UNFCCC_CRF_submission.py → src/unfccc_ghg_data/unfccc_crf_reader/read_unfccc_crf_submission.py

@@ -3,9 +3,10 @@ This script is a wrapper around the read_crf_for_country
 function such that it can be called from datalad
 function such that it can be called from datalad
 """
 """
 
 
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.UNFCCC_CRF_reader_prod import read_crf_for_country
 import argparse
 import argparse
 
 
+from unfccc_ghg_data.unfccc_crf_reader.unfccc_crf_reader_prod import read_crf_for_country
+
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 parser.add_argument('--country', help='Country name or code')
 parser.add_argument('--country', help='Country name or code')
 parser.add_argument('--submission_year', help='Submission round to read', type=int)
 parser.add_argument('--submission_year', help='Submission round to read', type=int)

+ 3 - 2
UNFCCC_GHG_data/UNFCCC_CRF_reader/read_UNFCCC_CRF_submission_datalad.py → src/unfccc_ghg_data/unfccc_crf_reader/read_unfccc_crf_submission_datalad.py

@@ -4,9 +4,10 @@ from doit in the current setup where doit runs on system python and
 not in the venv.
 not in the venv.
 """
 """
 
 
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.UNFCCC_CRF_reader_prod import read_crf_for_country_datalad
 import argparse
 import argparse
 
 
+from unfccc_ghg_data.unfccc_crf_reader.unfccc_crf_reader_prod import read_crf_for_country_datalad
+
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 parser.add_argument('--country', help='Country name or code')
 parser.add_argument('--country', help='Country name or code')
 parser.add_argument('--submission_year', help='Submission round to read')
 parser.add_argument('--submission_year', help='Submission round to read')
@@ -30,4 +31,4 @@ read_crf_for_country_datalad(
     submission_year=int(submission_year),
     submission_year=int(submission_year),
     submission_date=submission_date,
     submission_date=submission_date,
     re_read=re_read
     re_read=re_read
-)
+)

+ 2 - 1
UNFCCC_GHG_data/UNFCCC_CRF_reader/test_read_UNFCCC_CRF_for_year.py → src/unfccc_ghg_data/unfccc_crf_reader/test_read_unfccc_crf_for_year.py

@@ -3,9 +3,10 @@ This script is a wrapper around the read_year_to_test_specs
 function such that it can be called from datalad
 function such that it can be called from datalad
 """
 """
 
 
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.UNFCCC_CRF_reader_devel import read_year_to_test_specs
 import argparse
 import argparse
 
 
+from unfccc_ghg_data.unfccc_crf_reader.unfccc_crf_reader_devel import read_year_to_test_specs
+
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 parser.add_argument('--submission_year', help='Submission round to read', type=int)
 parser.add_argument('--submission_year', help='Submission round to read', type=int)
 parser.add_argument('--data_year', help='Data year to read', type=int, default=2010)
 parser.add_argument('--data_year', help='Data year to read', type=int, default=2010)

+ 100 - 71
UNFCCC_GHG_data/UNFCCC_CRF_reader/UNFCCC_CRF_reader_core.py → src/unfccc_ghg_data/unfccc_crf_reader/unfccc_crf_reader_core.py

@@ -4,36 +4,42 @@ Core function are used both for reading for final datasets as
 well as for test-reading to check for new categories etc.
 well as for test-reading to check for new categories etc.
 """
 """
 
 
-import re
-import os
 import json
 import json
+import os
+import re
+from collections import Counter
+from datetime import datetime, timedelta
+from operator import itemgetter
+from pathlib import Path
+from typing import Optional, Union
+
+import datalad as dl
 import numpy as np
 import numpy as np
 import pandas as pd
 import pandas as pd
 import primap2 as pm2
 import primap2 as pm2
-from pathlib import Path
 from treelib import Tree
 from treelib import Tree
-from operator import itemgetter
-from collections import Counter
-from typing import Dict, List, Optional, Tuple, Union
-from datetime import datetime, timedelta
+
+from unfccc_ghg_data.helper import downloaded_data_path_UNFCCC, root_path
+
 from . import crf_specifications as crf
 from . import crf_specifications as crf
 from .util import NoCRFFilesError
 from .util import NoCRFFilesError
-from UNFCCC_GHG_data.helper import downloaded_data_path_UNFCCC
+
 
 
 ### reading functions
 ### reading functions
 def convert_crf_table_to_pm2if(
 def convert_crf_table_to_pm2if(
         df_table: pd.DataFrame,
         df_table: pd.DataFrame,
         submission_year: int,
         submission_year: int,
-        entity_mapping: Optional[Dict[str,str]]=None,
-        coords_defaults_input: Optional[Dict[str,str]]=None,
-        filter_remove_input: Optional[Dict[str,Dict[str,Union[str,List]]]]=None,
-        filter_keep_input: Optional[Dict[str,Dict[str,Union[str,List]]]]=None,
-        meta_data_input: Optional[Dict[str,str]]=None,
+        entity_mapping: Optional[dict[str,str]]=None,
+        coords_defaults_input: Optional[dict[str,str]]=None,
+        filter_remove_input: Optional[dict[str,dict[str,Union[str,list]]]]=None,
+        filter_keep_input: Optional[dict[str,dict[str,Union[str,list]]]]=None,
+        meta_data_input: Optional[dict[str,str]]=None,
 ) -> pd.DataFrame:
 ) -> pd.DataFrame:
     """
     """
     Converts a given pandas long format crf table to PRIMAP2 interchange format
     Converts a given pandas long format crf table to PRIMAP2 interchange format
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
         df_table: pd.DataFrame
         df_table: pd.DataFrame
             Data to convert
             Data to convert
@@ -60,12 +66,12 @@ def convert_crf_table_to_pm2if(
             are given as input the automatic values are overwritten.
             are given as input the automatic values are overwritten.
 
 
     Returns
     Returns
+    -------
     _______
     _______
         pd.DataFrame:
         pd.DataFrame:
             Pandas DataFrame containing the data in PRIMAP2 interchange format
             Pandas DataFrame containing the data in PRIMAP2 interchange format
             Metadata is stored as attrs in the DataFrame
             Metadata is stored as attrs in the DataFrame
     """
     """
-
     coords_cols = {
     coords_cols = {
         "category": "category",
         "category": "category",
         "entity": "entity",
         "entity": "entity",
@@ -107,7 +113,7 @@ def convert_crf_table_to_pm2if(
 
 
     filter_remove = {
     filter_remove = {
         "f1": {
         "f1": {
-            "category": ["\IGNORE"],
+            "category": ["\\IGNORE"],
         }
         }
     }
     }
     if filter_remove_input is not None:
     if filter_remove_input is not None:
@@ -150,14 +156,14 @@ def convert_crf_table_to_pm2if(
 
 
 
 
 def read_crf_table(
 def read_crf_table(
-        country_codes: Union[str, List[str]],
+        country_codes: Union[str, list[str]],
         table: str,
         table: str,
         submission_year: int,
         submission_year: int,
-        data_year: Optional[Union[int, List[int]]]=None,
+        data_year: Optional[Union[int, list[int]]]=None,
         date: Optional[str]=None,
         date: Optional[str]=None,
         folder: Optional[str]=None,
         folder: Optional[str]=None,
         debug: Optional[bool]=False,
         debug: Optional[bool]=False,
-) -> Tuple[pd.DataFrame, List[List], List[List]]:
+) -> tuple[pd.DataFrame, list[list], list[list]]:
     """
     """
     Read CRF table for given submission year and country / or countries
     Read CRF table for given submission year and country / or countries
     This function can read for multiple years and countries but only a single
     This function can read for multiple years and countries but only a single
@@ -168,10 +174,11 @@ def read_crf_table(
     from the submission_year and country_code variables
     from the submission_year and country_code variables
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     country_codes: str or list[str]
     country_codes: str or list[str]
-        ISO 3-letter country UNFCCC_GHG_data or list of country codes
+        ISO 3-letter country code or list of country codes
 
 
     table: str
     table: str
         name of the table sheet in the CRF xlsx file
         name of the table sheet in the CRF xlsx file
@@ -194,6 +201,7 @@ def read_crf_table(
         if true print some debug information like column headers
         if true print some debug information like column headers
 
 
     Returns
     Returns
+    -------
     _______
     _______
         Tuple[pd.DataFrame, List[List], List[List]]:
         Tuple[pd.DataFrame, List[List], List[List]]:
         * First return parameter is the data as a pandas DataFrame in long format
         * First return parameter is the data as a pandas DataFrame in long format
@@ -223,7 +231,7 @@ def read_crf_table(
         if len(input_files) < expected_files:
         if len(input_files) < expected_files:
             print(f"Found only {len(input_files)} input files for {country_codes}. "
             print(f"Found only {len(input_files)} input files for {country_codes}. "
                   f"Expected {expected_files}.")
                   f"Expected {expected_files}.")
-            print(f"Possibly exporting run overnight and some files have the previous day as date.")
+            print("Possibly exporting run overnight and some files have the previous day as date.")
             date_datetime = datetime.strptime(date, "%d%m%Y")
             date_datetime = datetime.strptime(date, "%d%m%Y")
             date_datetime = date_datetime - timedelta(days=1)
             date_datetime = date_datetime - timedelta(days=1)
             prv_date = date_datetime.strftime("%d%m%Y")
             prv_date = date_datetime.strftime("%d%m%Y")
@@ -236,7 +244,7 @@ def read_crf_table(
                 print(f"Found {len(more_input_files)} additional input files.")
                 print(f"Found {len(more_input_files)} additional input files.")
                 input_files = input_files + more_input_files
                 input_files = input_files + more_input_files
             else:
             else:
-                print(f"Found no additional input files")
+                print("Found no additional input files")
 
 
     if input_files == []:
     if input_files == []:
         raise NoCRFFilesError(f"No files found for {country_codes}, "
         raise NoCRFFilesError(f"No files found for {country_codes}, "
@@ -251,7 +259,7 @@ def read_crf_table(
     if len(country_codes) == 1:
     if len(country_codes) == 1:
         try:
         try:
             crf_spec = getattr(crf, f"CRF{submission_year}_{country_codes[0]}")
             crf_spec = getattr(crf, f"CRF{submission_year}_{country_codes[0]}")
-            print(f"Using country specific specification: " 
+            print(f"Using country specific specification: "
                   f"CRF{submission_year}_{country_codes[0]}")
                   f"CRF{submission_year}_{country_codes[0]}")
         except:
         except:
             # no country specific specification, check for general specification
             # no country specific specification, check for general specification
@@ -294,14 +302,15 @@ def read_crf_table(
 def read_crf_table_from_file(
 def read_crf_table_from_file(
         file: Path,
         file: Path,
         table: str,
         table: str,
-        table_spec: Dict[str, Dict],
+        table_spec: dict[str, dict],
         debug: Optional[bool]=False,
         debug: Optional[bool]=False,
-) -> Tuple[pd.DataFrame, List[List], List[List]]:
+) -> tuple[pd.DataFrame, list[list], list[list]]:
     """
     """
     Read a single CRF table from a given file. This is the core function of the CRF
     Read a single CRF table from a given file. This is the core function of the CRF
     reading process as it reads the data from xls and performs the category mapping.
     reading process as it reads the data from xls and performs the category mapping.
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
     file: Path
     file: Path
         file to read from
         file to read from
@@ -316,6 +325,7 @@ def read_crf_table_from_file(
         if true print some debug information like column headers
         if true print some debug information like column headers
 
 
     Returns
     Returns
+    -------
     _______
     _______
         Tuple[pd.DataFrame, List[List], List[List]]:
         Tuple[pd.DataFrame, List[List], List[List]]:
         * First return parameter is the data as a pandas DataFrame in long format
         * First return parameter is the data as a pandas DataFrame in long format
@@ -326,6 +336,12 @@ def read_crf_table_from_file(
 
 
     TODO: add verbosity option for debugging?
     TODO: add verbosity option for debugging?
     """
     """
+    # check if file exists and if not download
+    if file.is_symlink():
+        if not file.exists():
+            dlds = dl.api.Dataset(root_path)
+            dlds.get(file.relative_to(root_path))
+
 
 
     table_properties = table_spec["table"]
     table_properties = table_spec["table"]
     file_info = get_info_from_crf_filename(file.name)
     file_info = get_info_from_crf_filename(file.name)
@@ -366,7 +382,7 @@ def read_crf_table_from_file(
         last_row_nan = True
         last_row_nan = True
     else:
     else:
         last_row_nan = False
         last_row_nan = False
-    
+
 
 
     cols_to_drop = []
     cols_to_drop = []
     # remove empty first column (for Australia tables start with an empty column)
     # remove empty first column (for Australia tables start with an empty column)
@@ -433,7 +449,7 @@ def read_crf_table_from_file(
 
 
     # remove double spaces
     # remove double spaces
     entities = [entity.strip() for entity in entities]
     entities = [entity.strip() for entity in entities]
-    entities = [re.sub('\s+', ' ', entity) for entity in entities]
+    entities = [re.sub('\\s+', ' ', entity) for entity in entities]
 
 
     # replace the old header
     # replace the old header
     if len(header) > 2:
     if len(header) > 2:
@@ -451,7 +467,7 @@ def read_crf_table_from_file(
     # remove double spaces
     # remove double spaces
     for col in cols_for_space_stripping:
     for col in cols_for_space_stripping:
         df_current[col] = df_current[col].str.strip()
         df_current[col] = df_current[col].str.strip()
-        df_current[col] = df_current[col].replace('\s+', ' ', regex=True)
+        df_current[col] = df_current[col].replace('\\s+', ' ', regex=True)
 
 
     # prepare for sector mapping by initializing result lists and
     # prepare for sector mapping by initializing result lists and
     # variables
     # variables
@@ -571,20 +587,21 @@ def read_crf_table_from_file(
 
 
 
 
 def get_crf_files(
 def get_crf_files(
-        country_codes: Union[str, List[str]],
+        country_codes: Union[str, list[str]],
         submission_year: int,
         submission_year: int,
-        data_year: Optional[Union[int, List[int]]] = None,
+        data_year: Optional[Union[int, list[int]]] = None,
         date: Optional[str] = None,
         date: Optional[str] = None,
         folder: Optional[str] = None,
         folder: Optional[str] = None,
-) -> List[Path]:
+) -> list[Path]:
     """
     """
     Finds all files according to given parameters
     Finds all files according to given parameters
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     country_codes: str or list[str]
     country_codes: str or list[str]
-        ISO 3-letter country UNFCCC_GHG_data or list of country codes
+        ISO 3-letter country code or list of country codes
 
 
     submission_year: int
     submission_year: int
         Year of the submission of the data
         Year of the submission of the data
@@ -601,6 +618,7 @@ def get_crf_files(
         submissions_year and country_code variables
         submissions_year and country_code variables
 
 
     Returns
     Returns
+    -------
     _______
     _______
         List[Path]: list of Path objects for the files
         List[Path]: list of Path objects for the files
     """
     """
@@ -615,7 +633,7 @@ def get_crf_files(
         data_folder = downloaded_data_path_UNFCCC
         data_folder = downloaded_data_path_UNFCCC
         submission_folder = f"CRF{submission_year}"
         submission_folder = f"CRF{submission_year}"
 
 
-        with open(data_folder / "folder_mapping.json", "r") as mapping_file:
+        with open(data_folder / "folder_mapping.json") as mapping_file:
             folder_mapping = json.load(mapping_file)
             folder_mapping = json.load(mapping_file)
 
 
         # use country default folders
         # use country default folders
@@ -625,8 +643,7 @@ def get_crf_files(
                 new_country_folders = folder_mapping[country_code]
                 new_country_folders = folder_mapping[country_code]
                 if isinstance(new_country_folders, str):
                 if isinstance(new_country_folders, str):
                     # only one folder
                     # only one folder
-                    country_folders = country_folders + \
-                                      [data_folder / new_country_folders / submission_folder]
+                    country_folders = [*country_folders, data_folder / new_country_folders / submission_folder]
                 else:
                 else:
                     country_folders = country_folders + \
                     country_folders = country_folders + \
                                       [data_folder / folder / submission_folder
                                       [data_folder / folder / submission_folder
@@ -683,21 +700,23 @@ def get_crf_files(
 
 
 def get_info_from_crf_filename(
 def get_info_from_crf_filename(
         filename: str,
         filename: str,
-) -> Dict[str, Union[int, str]]:
+) -> dict[str, Union[int, str]]:
     """
     """
     Parse given file name and return a dict with information
     Parse given file name and return a dict with information
     on the contained data.
     on the contained data.
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     filename: str
     filename: str
         The file to analyze (without path)
         The file to analyze (without path)
 
 
     Returns
     Returns
+    -------
     _______
     _______
     dict with fields:
     dict with fields:
-        party: the party that submitted the data (3 letter UNFCCC_GHG_data)
+        party: the party that submitted the data (3 letter code)
         submission_year: year of submission
         submission_year: year of submission
         data_year: year in which the emissions took place
         data_year: year in which the emissions took place
         date: date of the submission
         date: date of the submission
@@ -724,22 +743,23 @@ def get_info_from_crf_filename(
 
 
 
 
 def filter_filenames(
 def filter_filenames(
-        files_to_filter: List[Path],
-        party: Optional[Union[str, List[str]]] = None,
-        data_year: Optional[Union[int, List[int]]] = None,
+        files_to_filter: list[Path],
+        party: Optional[Union[str, list[str]]] = None,
+        data_year: Optional[Union[int, list[int]]] = None,
         submission_year: Optional[str] = None,
         submission_year: Optional[str] = None,
         date: Optional[str] = None,
         date: Optional[str] = None,
-) -> List[Path]:
-    """ Filter a list of filenames of CRF files
+) -> list[Path]:
+    """Filter a list of filenames of CRF files
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
     files_to_filter: List[Path]
     files_to_filter: List[Path]
         List with pathlib.Path objects for the filenames to filter
         List with pathlib.Path objects for the filenames to filter
 
 
     party: Optional[Union[str, List[str]]] (default: None)
     party: Optional[Union[str, List[str]]] (default: None)
-        List of country codes or single country UNFCCC_GHG_data. If given only files
-        for this(these) country-UNFCCC_GHG_data(s) will be returned.
+        List of country codes or single country code. If given only files
+        for this(these) country-code(s) will be returned.
 
 
     data_year: Optional[Union[int, List[int]]] (default: None)
     data_year: Optional[Union[int, List[int]]] (default: None)
         List of data years or single year. If given only files for this
         List of data years or single year. If given only files for this
@@ -774,13 +794,14 @@ def filter_filenames(
 
 
 
 
 def check_crf_file_info(
 def check_crf_file_info(
-        file_info: Dict,
-        file_filter: Dict,
+        file_info: dict,
+        file_filter: dict,
 ) -> bool:
 ) -> bool:
     """
     """
     Check if a CRF file has given properties
     Check if a CRF file has given properties
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
     file_info: Dict
     file_info: Dict
         the file info dict of a CRF xlsx file as returned by
         the file info dict of a CRF xlsx file as returned by
@@ -791,6 +812,7 @@ def check_crf_file_info(
         with functionality as in `filter_filenames`
         with functionality as in `filter_filenames`
 
 
     Returns
     Returns
+    -------
     _______
     _______
         bool: `True` if the file info matches the filter and `False` if not
         bool: `True` if the file info matches the filter and `False` if not
 
 
@@ -819,7 +841,7 @@ def check_crf_file_info(
 
 
 
 
 def create_category_tree(
 def create_category_tree(
-        specification: List[List],
+        specification: list[list],
         table: str,
         table: str,
         country: Optional[str] = None,
         country: Optional[str] = None,
 ) -> Tree:
 ) -> Tree:
@@ -831,6 +853,7 @@ def create_category_tree(
     correct categories to non-unique row headers.
     correct categories to non-unique row headers.
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     specification: List[List]
     specification: List[List]
@@ -874,7 +897,7 @@ def create_category_tree(
                          for mapping in specification]
                          for mapping in specification]
         # remove the categories for other countries
         # remove the categories for other countries
         specification = [mapping for mapping in specification
         specification = [mapping for mapping in specification
-                         if mapping[0] != "\REMOVE"]
+                         if mapping[0] != "\\REMOVE"]
 
 
     # build a tree from specification
     # build a tree from specification
     # when looping over the categories present in the table
     # when looping over the categories present in the table
@@ -922,31 +945,33 @@ def create_category_tree(
 
 
 
 
 def filter_category(
 def filter_category(
-        mapping: List,
+        mapping: list,
         country: str,
         country: str,
-) -> List[str]:
+) -> list[str]:
     """
     """
     This function checks if a category mapping is suitable for the given country.
     This function checks if a category mapping is suitable for the given country.
     If it is the country information will be removed and the new mapping returned.
     If it is the country information will be removed and the new mapping returned.
-    If it is not suitable it will be returned with category name "\REMOVE" such that
+    If it is not suitable it will be returned with category name "\\REMOVE" such that
     it can be removed from the mapping by the calling function.
     it can be removed from the mapping by the calling function.
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
         mapping: List
         mapping: List
             mapping for a single category
             mapping for a single category
         country: str
         country: str
-            iso 3-letter UNFCCC_GHG_data of the country
+            iso 3-letter code of the country
 
 
     Returns
     Returns
+    -------
     _______
     _______
         List: updated mapping
         List: updated mapping
 
 
     """
     """
-    string_exclude = f"\C!-"
+    string_exclude = "\\C!-"
     regex_exclude = r"\\C!-([A-Z\-]+)\\"
     regex_exclude = r"\\C!-([A-Z\-]+)\\"
     regex_exclude_full = r"(\\C!-[A-Z\-]+\\)"
     regex_exclude_full = r"(\\C!-[A-Z\-]+\\)"
-    string_country = f"\C-{country}\\"
+    string_country = f"\\C-{country}\\"
     regex_countries = r"^\\C-[A-Z]{3}\\"
     regex_countries = r"^\\C-[A-Z]{3}\\"
     new_mapping = mapping.copy()
     new_mapping = mapping.copy()
     if mapping[0].startswith(string_exclude):
     if mapping[0].startswith(string_exclude):
@@ -954,14 +979,14 @@ def filter_category(
         countries_ex = re_result.group(1)
         countries_ex = re_result.group(1)
         countries_ex = countries_ex.split("-")
         countries_ex = countries_ex.split("-")
         if country in countries_ex:
         if country in countries_ex:
-            new_mapping[0] = "\REMOVE"
+            new_mapping[0] = "\\REMOVE"
         else:
         else:
             re_result = re.search(regex_exclude_full, mapping[0])
             re_result = re.search(regex_exclude_full, mapping[0])
             new_mapping[0] = mapping[0][len(re_result.group(1)) + 1:]
             new_mapping[0] = mapping[0][len(re_result.group(1)) + 1:]
     elif mapping[0].startswith(string_country):
     elif mapping[0].startswith(string_country):
         new_mapping[0] = mapping[0][len(string_country) + 1:]
         new_mapping[0] = mapping[0][len(string_country) + 1:]
     elif re.match(regex_countries, mapping[0]):
     elif re.match(regex_countries, mapping[0]):
-        new_mapping[0] = "\REMOVE"
+        new_mapping[0] = "\\REMOVE"
 
 
     return new_mapping
     return new_mapping
 
 
@@ -974,19 +999,20 @@ def get_latest_date_for_country(
     Find the latest submission date for a country
     Find the latest submission date for a country
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
     country: str
     country: str
-        3-letter country UNFCCC_GHG_data
+        3-letter country code
 
 
     submission_year: int
     submission_year: int
         Year of the submission to find the l;atest date for
         Year of the submission to find the l;atest date for
 
 
     Returns
     Returns
+    -------
     _______
     _______
         str: string with date
         str: string with date
     """
     """
-
-    with open(downloaded_data_path_UNFCCC / "folder_mapping.json", "r") as mapping_file:
+    with open(downloaded_data_path_UNFCCC / "folder_mapping.json") as mapping_file:
         folder_mapping = json.load(mapping_file)
         folder_mapping = json.load(mapping_file)
 
 
     if country_code in folder_mapping:
     if country_code in folder_mapping:
@@ -1014,12 +1040,13 @@ def get_latest_date_for_country(
 
 
 def get_submission_dates(
 def get_submission_dates(
         folder: Path,
         folder: Path,
-        file_filter: Dict[str, Union[str, int, List]],
-)->List[str]:
+        file_filter: dict[str, Union[str, int, list]],
+)->list[str]:
     """
     """
     Returns all submission dates available in a folder
     Returns all submission dates available in a folder
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
     folder: Path
     folder: Path
         Folder to analyze
         Folder to analyze
@@ -1028,14 +1055,14 @@ def get_submission_dates(
         Dict with possible fields "party", "submission_year", "data_year"
         Dict with possible fields "party", "submission_year", "data_year"
 
 
     Returns
     Returns
+    -------
     _______
     _______
         List[str]:
         List[str]:
             List of dates as str
             List of dates as str
     """
     """
-
     if "date" in file_filter:
     if "date" in file_filter:
-        raise ValueError(f"'date' present in 'file_filter'. This makes no sense as "
-                         f"the function's purpose is to return available dates.")
+        raise ValueError("'date' present in 'file_filter'. This makes no sense as "
+                         "the function's purpose is to return available dates.")
 
 
     if folder.exists():
     if folder.exists():
         files = filter_filenames(folder.glob("*.xlsx"), **file_filter)
         files = filter_filenames(folder.glob("*.xlsx"), **file_filter)
@@ -1050,12 +1077,13 @@ def get_submission_dates(
 
 
 def get_submission_parties(
 def get_submission_parties(
         folder: Path,
         folder: Path,
-        file_filter: Dict[str, Union[str, int, List]],
-)->List[str]:
+        file_filter: dict[str, Union[str, int, list]],
+)->list[str]:
     """
     """
     Returns all submission dates available in a folder
     Returns all submission dates available in a folder
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
     folder: Path
     folder: Path
         Folder to analyze
         Folder to analyze
@@ -1064,14 +1092,14 @@ def get_submission_parties(
         Dict with possible fields "submission_year", "data_year", "date"
         Dict with possible fields "submission_year", "data_year", "date"
 
 
     Returns
     Returns
+    -------
     _______
     _______
         List[str]:
         List[str]:
             List of parties as str
             List of parties as str
     """
     """
-
     if "party" in file_filter:
     if "party" in file_filter:
-        raise ValueError(f"'party' present in 'file_filter'. This makes no sense as "
-                         f"the function's purpose is to return available parties.")
+        raise ValueError("'party' present in 'file_filter'. This makes no sense as "
+                         "the function's purpose is to return available parties.")
 
 
     if folder.exists():
     if folder.exists():
         files = filter_filenames(list(folder.glob("*.xlsx")), **file_filter)
         files = filter_filenames(list(folder.glob("*.xlsx")), **file_filter)
@@ -1085,7 +1113,7 @@ def get_submission_parties(
 
 
 
 
 def find_latest_date(
 def find_latest_date(
-        dates: List[str],
+        dates: list[str],
         date_format: str='%d%m%Y',
         date_format: str='%d%m%Y',
 )-> str:
 )-> str:
     """
     """
@@ -1093,21 +1121,22 @@ def find_latest_date(
     ddmmyyyy
     ddmmyyyy
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
     dates: List[str]
     dates: List[str]
         List of dates
         List of dates
 
 
     Returns
     Returns
+    -------
     _______
     _______
         str: latest date
         str: latest date
     """
     """
-
     if len(dates) > 0:
     if len(dates) > 0:
         dates_datetime = [[date, datetime.strptime(date, date_format)] for date in
         dates_datetime = [[date, datetime.strptime(date, date_format)] for date in
                           dates]
                           dates]
         dates_datetime = sorted(dates_datetime, key=itemgetter(1))
         dates_datetime = sorted(dates_datetime, key=itemgetter(1))
     else:
     else:
-        raise ValueError(f"Passed list of dates is empty")
+        raise ValueError("Passed list of dates is empty")
 
 
     return dates_datetime[-1][0]
     return dates_datetime[-1][0]
 
 

+ 56 - 54
UNFCCC_GHG_data/UNFCCC_CRF_reader/UNFCCC_CRF_reader_devel.py → src/unfccc_ghg_data/unfccc_crf_reader/unfccc_crf_reader_devel.py

@@ -6,18 +6,20 @@ of single years in contrast to the production functions which are tailored
 towards the creation of full datasets including storage in the
 towards the creation of full datasets including storage in the
 """
 """
 
 
+from datetime import date
+from pathlib import Path
+from typing import Optional
+
 import pandas as pd
 import pandas as pd
-import xarray as xr
 import primap2 as pm2
 import primap2 as pm2
-from typing import List, Optional
-from pathlib import Path
-from datetime import date
+import xarray as xr
+
+from unfccc_ghg_data.helper import get_country_name, log_path
 
 
-from .util import all_crf_countries
-from UNFCCC_GHG_data.helper import log_path, get_country_name
 from . import crf_specifications as crf
 from . import crf_specifications as crf
-from .UNFCCC_CRF_reader_core import get_latest_date_for_country, read_crf_table
-from .UNFCCC_CRF_reader_core import convert_crf_table_to_pm2if
+from .unfccc_crf_reader_core import convert_crf_table_to_pm2if, get_latest_date_for_country, read_crf_table
+from .util import all_crf_countries
+
 
 
 def read_year_to_test_specs(
 def read_year_to_test_specs(
         submission_year: int,
         submission_year: int,
@@ -35,6 +37,9 @@ def read_year_to_test_specs(
     if data_year is None:
     if data_year is None:
         data_year=2000
         data_year=2000
 
 
+    if country_code=="None":
+        country_code=None
+
     unknown_categories = []
     unknown_categories = []
     last_row_info = []
     last_row_info = []
     ds_all = None
     ds_all = None
@@ -43,43 +48,6 @@ def read_year_to_test_specs(
         print("Reading only tables to test.")
         print("Reading only tables to test.")
     print("#"*80)
     print("#"*80)
 
 
-
-    # get specification
-    # if we only have a single country check if we might have a country specific
-    # specification (currently only Australia, 2023)
-    if country_code is not None:
-        try:
-            crf_spec = getattr(crf, f"CRF{submission_year}_{country_code}")
-            print(
-                f"Using country specific specification: "
-                f"CRF{submission_year}_{country_code}"
-            )
-        except:
-            # no country specific specification, check for general specification
-            try:
-                crf_spec = getattr(crf, f"CRF{submission_year}")
-            except:
-                raise ValueError(
-                    f"No terminology exists for submission year " f"{submission_year}"
-                )
-    else:
-        try:
-            crf_spec = getattr(crf, f"CRF{submission_year}")
-        except:
-            raise ValueError(
-                f"No terminology exists for submission year " f"{submission_year}"
-            )
-
-    if totest:
-        tables = [table for table in crf_spec.keys()
-                  if crf_spec[table]["status"] == "totest"]
-    else:
-        tables = [table for table in crf_spec.keys()
-                  if crf_spec[table]["status"] == "tested"]
-    print(f"The following tables are available in the " \
-          f"CRF{submission_year} specification: {tables}")
-    print("#" * 80)
-
     if country_code is not None:
     if country_code is not None:
         countries_to_read = [country_code]
         countries_to_read = [country_code]
     else:
     else:
@@ -87,8 +55,42 @@ def read_year_to_test_specs(
     for country_code in countries_to_read:
     for country_code in countries_to_read:
         # get country name
         # get country name
         country_name = get_country_name(country_code)
         country_name = get_country_name(country_code)
-        print(f"Reading for {country_name}")
+        print(f"reading for country: {country_code}")
         # get specification and available tables
         # get specification and available tables
+           # if we only have a single country check if we might have a country specific
+        # specification (currently only Australia, 2023)
+        if country_code is not None:
+            try:
+                crf_spec = getattr(crf, f"CRF{submission_year}_{country_code}")
+                print(
+                    f"Using country specific specification: "
+                    f"CRF{submission_year}_{country_code}"
+                )
+            except:
+                # no country specific specification, check for general specification
+                try:
+                    crf_spec = getattr(crf, f"CRF{submission_year}")
+                except:
+                    raise ValueError(
+                        f"No terminology exists for submission year " f"{submission_year}"
+                    )
+        else:
+            try:
+                crf_spec = getattr(crf, f"CRF{submission_year}")
+            except:
+                raise ValueError(
+                    f"No terminology exists for submission year " f"{submission_year}"
+                )
+
+        if totest:
+            tables = [table for table in crf_spec.keys()
+                      if crf_spec[table]["status"] == "totest"]
+        else:
+            tables = [table for table in crf_spec.keys()
+                      if crf_spec[table]["status"] == "tested"]
+        print(f"The following tables are available in the " \
+              f"CRF{submission_year} specification: {tables}")
+        print("#" * 80)
 
 
         try:
         try:
             submission_date = get_latest_date_for_country(country_code, submission_year)
             submission_date = get_latest_date_for_country(country_code, submission_year)
@@ -98,7 +100,7 @@ def read_year_to_test_specs(
 
 
         if submission_date is not None:
         if submission_date is not None:
             for table in tables:
             for table in tables:
-                # read table for all years
+                # read table for given years
                 ds_table, new_unknown_categories, new_last_row_info = read_crf_table(
                 ds_table, new_unknown_categories, new_last_row_info = read_crf_table(
                     country_code, table, submission_year, date=submission_date,
                     country_code, table, submission_year, date=submission_date,
                     data_year=[data_year], debug=True)
                     data_year=[data_year], debug=True)
@@ -134,8 +136,7 @@ def read_year_to_test_specs(
                     # if individual data for emissions and removals / recovery exist combine
                     # if individual data for emissions and removals / recovery exist combine
                     # them
                     # them
                     if (('CO2 removals' in ds_table_pm2.data_vars) and
                     if (('CO2 removals' in ds_table_pm2.data_vars) and
-                            ('CO2 emissions' in ds_table_pm2.data_vars) and not
-                            ('CO2' in ds_table_pm2.data_vars)):
+                            ('CO2 emissions' in ds_table_pm2.data_vars) and "CO2" not in ds_table_pm2.data_vars):
                         # we can just sum to CO2 as we made sure that it doesn't exist.
                         # we can just sum to CO2 as we made sure that it doesn't exist.
                         # If we have CO2 and removals but not emissions, CO2 already has
                         # If we have CO2 and removals but not emissions, CO2 already has
                         # removals subtracted and we do nothing here
                         # removals subtracted and we do nothing here
@@ -146,8 +147,7 @@ def read_year_to_test_specs(
                         ds_table_pm2["CO2"].attrs["entity"] = "CO2"
                         ds_table_pm2["CO2"].attrs["entity"] = "CO2"
 
 
                     if (('CH4 removals' in ds_table_pm2.data_vars) and
                     if (('CH4 removals' in ds_table_pm2.data_vars) and
-                            ('CH4 emissions' in ds_table_pm2.data_vars) and not
-                            ('CH4' in ds_table_pm2.data_vars)):
+                            ('CH4 emissions' in ds_table_pm2.data_vars) and "CH4" not in ds_table_pm2.data_vars):
                         # we can just sum to CH4 as we made sure that it doesn't exist.
                         # we can just sum to CH4 as we made sure that it doesn't exist.
                         # If we have CH4 and removals but not emissions, CH4 already has
                         # If we have CH4 and removals but not emissions, CH4 already has
                         # removals subtracted and we do nothing here
                         # removals subtracted and we do nothing here
@@ -227,13 +227,14 @@ def read_year_to_test_specs(
 
 
 
 
 def save_unknown_categories_info(
 def save_unknown_categories_info(
-        unknown_categories: List[List],
+        unknown_categories: list[list],
         file: Path,
         file: Path,
 ) -> None:
 ) -> None:
     """
     """
     Save information on unknown categories to a csv file.
     Save information on unknown categories to a csv file.
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     unknown_categories: List[List]
     unknown_categories: List[List]
@@ -277,7 +278,7 @@ def save_unknown_categories_info(
 
 
 
 
 def save_last_row_info(
 def save_last_row_info(
-        last_row_info: List[List],
+        last_row_info: list[list],
         file: Path,
         file: Path,
     ) -> None:
     ) -> None:
     """
     """
@@ -287,6 +288,7 @@ def save_last_row_info(
     given in the specification and thus we might not read the full table.
     given in the specification and thus we might not read the full table.
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     last_row_info: List[List]
     last_row_info: List[List]
@@ -325,4 +327,4 @@ def save_last_row_info(
     if not file.parents[0].exists():
     if not file.parents[0].exists():
         file.parents[0].mkdir()
         file.parents[0].mkdir()
     df_processed_lost_row_info = pd.DataFrame(processed_last_row_info, columns=["Table", "Country", "Categories"])
     df_processed_lost_row_info = pd.DataFrame(processed_last_row_info, columns=["Table", "Country", "Categories"])
-    df_processed_lost_row_info.to_csv("test_last_row_info.csv", index=False)
+    df_processed_lost_row_info.to_csv("test_last_row_info.csv", index=False)

+ 50 - 43
UNFCCC_GHG_data/UNFCCC_CRF_reader/UNFCCC_CRF_reader_prod.py → src/unfccc_ghg_data/unfccc_crf_reader/unfccc_crf_reader_prod.py

@@ -1,22 +1,30 @@
-import xarray as xr
-import primap2 as pm2
-import datalad.api
+
 from datetime import date
 from datetime import date
-from typing import Optional, List, Dict, Union
+from typing import Optional, Union
 
 
-from . import crf_specifications as crf
+import datalad.api
+import primap2 as pm2
+import xarray as xr
 
 
-from .UNFCCC_CRF_reader_core import read_crf_table
-from .UNFCCC_CRF_reader_core import convert_crf_table_to_pm2if
-from .UNFCCC_CRF_reader_core import get_latest_date_for_country
-from .UNFCCC_CRF_reader_core import get_crf_files
-from .UNFCCC_CRF_reader_devel import save_unknown_categories_info
-from .UNFCCC_CRF_reader_devel import save_last_row_info
+from unfccc_ghg_data.helper import (
+    code_path,
+    custom_country_mapping,
+    extracted_data_path_UNFCCC,
+    get_country_code,
+    get_country_name,
+    log_path,
+    root_path,
+)
 
 
-from UNFCCC_GHG_data.helper import code_path, log_path, root_path
-from UNFCCC_GHG_data.helper import custom_country_mapping, extracted_data_path_UNFCCC
-from UNFCCC_GHG_data.helper import get_country_code, get_country_name
-from .util import all_crf_countries, NoCRFFilesError
+from . import crf_specifications as crf
+from .unfccc_crf_reader_core import (
+    convert_crf_table_to_pm2if,
+    get_crf_files,
+    get_latest_date_for_country,
+    read_crf_table,
+)
+from .unfccc_crf_reader_devel import save_last_row_info, save_unknown_categories_info
+from .util import NoCRFFilesError, all_crf_countries
 
 
 #import sys
 #import sys
 #sys.path.append(code_path.name)
 #sys.path.append(code_path.name)
@@ -31,7 +39,7 @@ from .util import all_crf_countries, NoCRFFilesError
 # TODO: add function to read several / all countries
 # TODO: add function to read several / all countries
 
 
 # general approach:
 # general approach:
-# main UNFCCC_GHG_data in a function that reads on table from one file.
+# main code in a function that reads on table from one file.
 # return raw pandas DF for use in different functions
 # return raw pandas DF for use in different functions
 # wrappers around this function to read for a whole country or for test reading where we also
 # wrappers around this function to read for a whole country or for test reading where we also
 # write files with missing sectors etc.
 # write files with missing sectors etc.
@@ -67,10 +75,11 @@ def read_crf_for_country(
 
 
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     country_codes: str
     country_codes: str
-        ISO 3-letter country UNFCCC_GHG_data
+        ISO 3-letter country code
 
 
     submission_year: int
     submission_year: int
         Year of the submission of the data
         Year of the submission of the data
@@ -83,10 +92,10 @@ def read_crf_for_country(
         Read the data also if it's already present
         Read the data also if it's already present
 
 
     Returns
     Returns
+    -------
     _______
     _______
         return value is a Pandas DataFrame with the read data in PRIMAP2 format
         return value is a Pandas DataFrame with the read data in PRIMAP2 format
     """
     """
-
     # get country name
     # get country name
     country_name = get_country_name(country_code)
     country_name = get_country_name(country_code)
 
 
@@ -160,8 +169,7 @@ def read_crf_for_country(
             # if individual data for emissions and removals / recovery exist combine
             # if individual data for emissions and removals / recovery exist combine
             # them
             # them
             if (('CO2 removals' in ds_table_pm2.data_vars) and
             if (('CO2 removals' in ds_table_pm2.data_vars) and
-                    ('CO2 emissions' in ds_table_pm2.data_vars) and not
-                    ('CO2' in ds_table_pm2.data_vars)):
+                    ('CO2 emissions' in ds_table_pm2.data_vars) and "CO2" not in ds_table_pm2.data_vars):
                 # we can just sum to CO2 as we made sure that it doesn't exist.
                 # we can just sum to CO2 as we made sure that it doesn't exist.
                 # If we have CO2 and removals but not emissions, CO2 already has
                 # If we have CO2 and removals but not emissions, CO2 already has
                 # removals subtracted and we do nothing here
                 # removals subtracted and we do nothing here
@@ -172,11 +180,10 @@ def read_crf_for_country(
                 ds_table_pm2["CO2"].attrs["entity"] = "CO2"
                 ds_table_pm2["CO2"].attrs["entity"] = "CO2"
 
 
             if (('CH4 removals' in ds_table_pm2.data_vars) and
             if (('CH4 removals' in ds_table_pm2.data_vars) and
-                    ('CH4 emissions' in ds_table_pm2.data_vars) and not
-                    ('CH4' in ds_table_pm2.data_vars)):
+                    ('CH4 emissions' in ds_table_pm2.data_vars) and "CH4" not in ds_table_pm2.data_vars):
                 # we can just sum to CH4 as we made sure that it doesn't exist.
                 # we can just sum to CH4 as we made sure that it doesn't exist.
                 # If we have CH4 and removals but not emissions, CH4 already has
                 # If we have CH4 and removals but not emissions, CH4 already has
-                # removals subtracted and we do nothing here 
+                # removals subtracted and we do nothing here
                 ds_table_pm2["CH4"] = ds_table_pm2[["CH4 emissions",
                 ds_table_pm2["CH4"] = ds_table_pm2[["CH4 emissions",
                                                 "CH4 removals"]].pr.sum(
                                                 "CH4 removals"]].pr.sum(
                     dim="entity", skipna=True, min_count=1
                     dim="entity", skipna=True, min_count=1
@@ -240,10 +247,11 @@ def read_crf_for_country_datalad(
     and output files and using datalad run to trigger the data reading
     and output files and using datalad run to trigger the data reading
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     country_codes: str
     country_codes: str
-        ISO 3-letter country UNFCCC_GHG_data
+        ISO 3-letter country code
 
 
     submission_year: int
     submission_year: int
         Year of the submission of the data
         Year of the submission of the data
@@ -253,7 +261,6 @@ def read_crf_for_country_datalad(
         If not specified latest data will be read
         If not specified latest data will be read
 
 
     """
     """
-
     # get all the info for the country
     # get all the info for the country
     country_info = get_input_and_output_files_for_country(
     country_info = get_input_and_output_files_for_country(
         country, submission_year=submission_year, verbose=True)
         country, submission_year=submission_year, verbose=True)
@@ -261,15 +268,15 @@ def read_crf_for_country_datalad(
     print(f"Attempting to read data for CRF{submission_year} from {country}.")
     print(f"Attempting to read data for CRF{submission_year} from {country}.")
     print("#"*80)
     print("#"*80)
     print("")
     print("")
-    print(f"Using the UNFCCC_CRF_reader")
+    print("Using the unfccc_crf_reader")
     print("")
     print("")
-    print(f"Run the script using datalad run via the python api")
-    script = code_path / "UNFCCC_CRF_reader" / "read_UNFCCC_CRF_submission.py"
+    print("Run the script using datalad run via the python api")
+    script = code_path / "unfccc_crf_reader" / "read_unfccc_crf_submission.py"
 
 
     cmd = f"./venv/bin/python3 {script.as_posix()} --country={country} "\
     cmd = f"./venv/bin/python3 {script.as_posix()} --country={country} "\
           f"--submission_year={submission_year} --submission_date={submission_date}"
           f"--submission_year={submission_year} --submission_date={submission_date}"
     if re_read:
     if re_read:
-        cmd = cmd + f" --re_read"
+        cmd = cmd + " --re_read"
     datalad.api.run(
     datalad.api.run(
         cmd=cmd,
         cmd=cmd,
         dataset=root_path,
         dataset=root_path,
@@ -283,7 +290,7 @@ def read_crf_for_country_datalad(
 
 
 def read_new_crf_for_year(
 def read_new_crf_for_year(
         submission_year: int,
         submission_year: int,
-        countries: Optional[List[str]]=None,
+        countries: Optional[list[str]]=None,
         re_read: Optional[bool]=False,
         re_read: Optional[bool]=False,
 ) -> dict:
 ) -> dict:
     """
     """
@@ -302,6 +309,7 @@ def read_new_crf_for_year(
     read from different tables
     read from different tables
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     submission_year: int
     submission_year: int
@@ -317,11 +325,11 @@ def read_new_crf_for_year(
     TODO: write log with failed countries and what has been read
     TODO: write log with failed countries and what has been read
 
 
     Returns
     Returns
+    -------
     _______
     _______
         list[str]: list with country codes for which the data has been read
         list[str]: list with country codes for which the data has been read
 
 
     """
     """
-
     if countries is None:
     if countries is None:
         countries = all_crf_countries
         countries = all_crf_countries
 
 
@@ -356,7 +364,7 @@ def read_new_crf_for_year(
 
 
 def read_new_crf_for_year_datalad(
 def read_new_crf_for_year_datalad(
         submission_year: int,
         submission_year: int,
-        countries: Optional[List[str]] = None,
+        countries: Optional[list[str]] = None,
         re_read: Optional[bool] = False,
         re_read: Optional[bool] = False,
 ) -> None:
 ) -> None:
     """
     """
@@ -364,6 +372,7 @@ def read_new_crf_for_year_datalad(
     and output files and using datalad run to trigger the data reading
     and output files and using datalad run to trigger the data reading
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     submission_year: int
     submission_year: int
@@ -377,11 +386,10 @@ def read_new_crf_for_year_datalad(
         If true data will be read even if already read before.
         If true data will be read even if already read before.
 
 
     """
     """
-
     if countries is not None:
     if countries is not None:
-        print(f"Reading CRF{submission_year} for countries {countries} using UNFCCC_CRF_reader.")
+        print(f"Reading CRF{submission_year} for countries {countries} using unfccc_crf_reader.")
     else:
     else:
-        print(f"Reading CRF{submission_year} for all countries using UNFCCC_CRF_reader.")
+        print(f"Reading CRF{submission_year} for all countries using unfccc_crf_reader.")
         countries = all_crf_countries
         countries = all_crf_countries
     print("#" * 80)
     print("#" * 80)
     print("")
     print("")
@@ -417,8 +425,8 @@ def read_new_crf_for_year_datalad(
             # no error handling here as that is done in the function that does the actual reading
             # no error handling here as that is done in the function that does the actual reading
             pass
             pass
 
 
-    print(f"Run the script using datalad run via the python api")
-    script = code_path / "UNFCCC_CRF_reader" / "read_new_UNFCCC_CRF_for_year.py"
+    print("Run the script using datalad run via the python api")
+    script = code_path / "unfccc_crf_reader" / "read_new_unfccc_crf_for_year.py"
 
 
     #cmd = f"./venv/bin/python3 {script.as_posix()} --countries={countries} "\
     #cmd = f"./venv/bin/python3 {script.as_posix()} --countries={countries} "\
     #      f"--submission_year={submission_year}"
     #      f"--submission_year={submission_year}"
@@ -443,11 +451,10 @@ def get_input_and_output_files_for_country(
         submission_year: int,
         submission_year: int,
         submission_date: Optional[str]=None,
         submission_date: Optional[str]=None,
         verbose: Optional[bool]=True,
         verbose: Optional[bool]=True,
-) -> Dict[str, Union[List, str]]:
+) -> dict[str, Union[list, str]]:
     """
     """
     Get input and output files for a given country
     Get input and output files for a given country
     """
     """
-
     country_info = {}
     country_info = {}
 
 
     if country in custom_country_mapping:
     if country in custom_country_mapping:
@@ -463,7 +470,7 @@ def get_input_and_output_files_for_country(
     print(f"Determining input and output files for {country}")
     print(f"Determining input and output files for {country}")
     if submission_date is None:
     if submission_date is None:
         if verbose:
         if verbose:
-            print(f"No submission date given, find latest date.")
+            print("No submission date given, find latest date.")
         submission_date = get_latest_date_for_country(country_code, submission_year)
         submission_date = get_latest_date_for_country(country_code, submission_year)
     else:
     else:
         if verbose:
         if verbose:
@@ -488,7 +495,7 @@ def get_input_and_output_files_for_country(
                               f"v{submission_date}. Are they already submitted and included in the "
                               f"v{submission_date}. Are they already submitted and included in the "
                               f"repository?")
                               f"repository?")
     elif verbose:
     elif verbose:
-        print(f"Found the following input_files:")
+        print("Found the following input_files:")
         for file in input_files:
         for file in input_files:
             print(file.name)
             print(file.name)
         print("")
         print("")
@@ -504,7 +511,7 @@ def get_input_and_output_files_for_country(
                                     f"_{submission_date}.{suffix}" for suffix
                                     f"_{submission_date}.{suffix}" for suffix
                     in ['yaml', 'csv', 'nc']]
                     in ['yaml', 'csv', 'nc']]
     if verbose:
     if verbose:
-        print(f"The following files are considered as output_files:")
+        print("The following files are considered as output_files:")
         for file in output_files:
         for file in output_files:
             print(file)
             print(file)
         print("")
         print("")
@@ -551,4 +558,4 @@ def submission_has_been_read(
             print(f"No read data available for {country_code}, "
             print(f"No read data available for {country_code}, "
                   f"CRF{submission_year}, version {submission_date}. ")
                   f"CRF{submission_year}, version {submission_date}. ")
 
 
-    return has_been_read
+    return has_been_read

+ 1 - 1
UNFCCC_GHG_data/UNFCCC_CRF_reader/util.py → src/unfccc_ghg_data/unfccc_crf_reader/util.py

@@ -13,4 +13,4 @@ all_crf_countries = [
 ]
 ]
 
 
 class NoCRFFilesError(Exception):
 class NoCRFFilesError(Exception):
-    pass
+    pass

+ 0 - 0
UNFCCC_GHG_data/UNFCCC_DI_reader/DI_AI_parties.conf → src/unfccc_ghg_data/unfccc_di_reader/DI_AI_parties.conf


+ 0 - 0
UNFCCC_GHG_data/UNFCCC_DI_reader/DI_NAI_parties.conf → src/unfccc_ghg_data/unfccc_di_reader/DI_NAI_parties.conf


+ 36 - 0
src/unfccc_ghg_data/unfccc_di_reader/__init__.py

@@ -0,0 +1,36 @@
+# submodule to read data from UNFCCC DI API using the unfccc_di_api package
+
+#import unfccc_di_api
+from .unfccc_di_reader_core import (
+    convert_DI_data_to_pm2_if,
+    convert_DI_IF_data_to_pm2,
+    read_UNFCCC_DI_for_country,
+    read_UNFCCC_DI_for_country_group,
+)
+from .unfccc_di_reader_datalad import (
+    process_DI_for_country_datalad,
+    process_DI_for_country_group_datalad,
+    read_DI_for_country_datalad,
+    read_DI_for_country_group_datalad,
+)
+from .unfccc_di_reader_helper import determine_filename
+from .unfccc_di_reader_proc import (
+    process_and_save_UNFCCC_DI_for_country,
+    process_UNFCCC_DI_for_country,
+    process_UNFCCC_DI_for_country_group,
+)
+
+__all__ = [
+    "read_UNFCCC_DI_for_country",
+    "convert_DI_data_to_pm2_if",
+    "convert_DI_IF_data_to_pm2",
+    "read_UNFCCC_DI_for_country_group",
+    "process_UNFCCC_DI_for_country",
+    "process_and_save_UNFCCC_DI_for_country",
+    "process_UNFCCC_DI_for_country_group",
+    "process_DI_for_country_group_datalad",
+    "read_DI_for_country_datalad",
+    "process_DI_for_country_datalad",
+    "read_DI_for_country_group_datalad",
+    "determine_filename",
+]

+ 1 - 2
UNFCCC_GHG_data/UNFCCC_DI_reader/process_UNFCCC_DI_for_country.py → src/unfccc_ghg_data/unfccc_di_reader/process_unfccc_di_for_country.py

@@ -4,9 +4,8 @@ function such that it can be called from datalad
 """
 """
 
 
 import argparse
 import argparse
-from UNFCCC_GHG_data.UNFCCC_DI_reader import \
-    process_and_save_UNFCCC_DI_for_country
 
 
+from unfccc_ghg_data.UNFCCC_DI_reader import process_and_save_UNFCCC_DI_for_country
 
 
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 parser.add_argument('--country', help='Country code')
 parser.add_argument('--country', help='Country code')

+ 3 - 3
UNFCCC_GHG_data/UNFCCC_DI_reader/process_UNFCCC_DI_for_country_datalad.py → src/unfccc_ghg_data/unfccc_di_reader/process_unfccc_di_for_country_datalad.py

@@ -4,10 +4,10 @@ from doit in the current setup where doit runs on system python and
 not in the venv.
 not in the venv.
 """
 """
 
 
-from UNFCCC_GHG_data.UNFCCC_DI_reader import \
-    process_DI_for_country_datalad
 import argparse
 import argparse
 
 
+from unfccc_ghg_data.UNFCCC_DI_reader import process_DI_for_country_datalad
+
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 parser.add_argument('--country', help='Country name or code')
 parser.add_argument('--country', help='Country name or code')
 parser.add_argument('--date', help='String with date to read and process. If not '
 parser.add_argument('--date', help='String with date to read and process. If not '
@@ -19,4 +19,4 @@ date_str = args.date
 if date_str == "None":
 if date_str == "None":
     date_str = None
     date_str = None
 
 
-process_DI_for_country_datalad(country, date_str=date_str)
+process_DI_for_country_datalad(country, date_str=date_str)

+ 1 - 2
UNFCCC_GHG_data/UNFCCC_DI_reader/process_UNFCCC_DI_for_country_group.py → src/unfccc_ghg_data/unfccc_di_reader/process_unfccc_di_for_country_group.py

@@ -4,9 +4,8 @@ function such that it can be called from datalad
 """
 """
 
 
 import argparse
 import argparse
-from UNFCCC_GHG_data.UNFCCC_DI_reader import \
-    process_UNFCCC_DI_for_country_group
 
 
+from unfccc_ghg_data.UNFCCC_DI_reader import process_UNFCCC_DI_for_country_group
 
 
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 parser.add_argument('--annexI', help='read for AnnexI countries (default is for '
 parser.add_argument('--annexI', help='read for AnnexI countries (default is for '

+ 2 - 2
UNFCCC_GHG_data/UNFCCC_DI_reader/process_UNFCCC_DI_for_country_group_datalad.py → src/unfccc_ghg_data/unfccc_di_reader/process_unfccc_di_for_country_group_datalad.py

@@ -4,10 +4,10 @@ from doit in the current setup where doit runs on system python and
 not in the venv.
 not in the venv.
 """
 """
 
 
-from UNFCCC_GHG_data.UNFCCC_DI_reader import \
-    process_DI_for_country_group_datalad
 import argparse
 import argparse
 
 
+from unfccc_ghg_data.UNFCCC_DI_reader import process_DI_for_country_group_datalad
+
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 parser.add_argument('--annexI', help='read for AnnexI countries (default is for '
 parser.add_argument('--annexI', help='read for AnnexI countries (default is for '
                                      'non-AnnexI)', action='store_true')
                                      'non-AnnexI)', action='store_true')

+ 1 - 2
UNFCCC_GHG_data/UNFCCC_DI_reader/read_UNFCCC_DI_for_country.py → src/unfccc_ghg_data/unfccc_di_reader/read_unfccc_di_for_country.py

@@ -4,9 +4,8 @@ function such that it can be called from datalad
 """
 """
 
 
 import argparse
 import argparse
-from UNFCCC_GHG_data.UNFCCC_DI_reader.UNFCCC_DI_reader_core import \
-    read_UNFCCC_DI_for_country
 
 
+from unfccc_ghg_data.UNFCCC_DI_reader.UNFCCC_DI_reader_core import read_UNFCCC_DI_for_country
 
 
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 parser.add_argument('--country', help='Country code')
 parser.add_argument('--country', help='Country code')

+ 3 - 3
UNFCCC_GHG_data/UNFCCC_DI_reader/read_UNFCCC_DI_for_country_datalad.py → src/unfccc_ghg_data/unfccc_di_reader/read_unfccc_di_for_country_datalad.py

@@ -4,14 +4,14 @@ from doit in the current setup where doit runs on system python and
 not in the venv.
 not in the venv.
 """
 """
 
 
-from UNFCCC_GHG_data.UNFCCC_DI_reader import \
-    read_DI_for_country_datalad
 import argparse
 import argparse
 
 
+from unfccc_ghg_data.UNFCCC_DI_reader import read_DI_for_country_datalad
+
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 parser.add_argument('--country', help='Country name or code')
 parser.add_argument('--country', help='Country name or code')
 
 
 args = parser.parse_args()
 args = parser.parse_args()
 country = args.country
 country = args.country
 
 
-read_DI_for_country_datalad(country)
+read_DI_for_country_datalad(country)

+ 1 - 2
UNFCCC_GHG_data/UNFCCC_DI_reader/read_UNFCCC_DI_for_country_group.py → src/unfccc_ghg_data/unfccc_di_reader/read_unfccc_di_for_country_group.py

@@ -4,9 +4,8 @@ function such that it can be called from datalad
 """
 """
 
 
 import argparse
 import argparse
-from UNFCCC_GHG_data.UNFCCC_DI_reader import \
-    read_UNFCCC_DI_for_country_group
 
 
+from unfccc_ghg_data.UNFCCC_DI_reader import read_UNFCCC_DI_for_country_group
 
 
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 parser.add_argument('--annexI', help='read for AnnexI countries (default is for '
 parser.add_argument('--annexI', help='read for AnnexI countries (default is for '

+ 2 - 2
UNFCCC_GHG_data/UNFCCC_DI_reader/read_UNFCCC_DI_for_country_group_datalad.py → src/unfccc_ghg_data/unfccc_di_reader/read_unfccc_di_for_country_group_datalad.py

@@ -4,10 +4,10 @@ from doit in the current setup where doit runs on system python and
 not in the venv.
 not in the venv.
 """
 """
 
 
-from UNFCCC_GHG_data.UNFCCC_DI_reader import \
-    read_DI_for_country_group_datalad
 import argparse
 import argparse
 
 
+from unfccc_ghg_data.UNFCCC_DI_reader import read_DI_for_country_group_datalad
+
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
 parser.add_argument('--annexI', help='read for AnnexI countries (default is for '
 parser.add_argument('--annexI', help='read for AnnexI countries (default is for '
                                      'non-AnnexI)', action='store_true')
                                      'non-AnnexI)', action='store_true')

+ 0 - 0
UNFCCC_GHG_data/UNFCCC_DI_reader/UNFCCC_DI_reader_config.py → src/unfccc_ghg_data/unfccc_di_reader/unfccc_di_reader_config.py


+ 23 - 26
UNFCCC_GHG_data/UNFCCC_DI_reader/UNFCCC_DI_reader_core.py → src/unfccc_ghg_data/unfccc_di_reader/unfccc_di_reader_core.py

@@ -1,29 +1,28 @@
-import primap2 as pm2
-import unfccc_di_api
-import pandas as pd
-import pycountry
-import itertools
 import copy
 import copy
-import xarray as xr
-
-from datetime import date
-from typing import Optional, Dict
+import itertools
 from copy import deepcopy
 from copy import deepcopy
+from datetime import date
+from typing import Optional
 
 
-from .UNFCCC_DI_reader_config import di_to_pm2if_template_nai
-from .UNFCCC_DI_reader_config import di_to_pm2if_template_ai
-from .UNFCCC_DI_reader_config import di_query_filters
-
-from .UNFCCC_DI_reader_config import cat_code_regexp
-from .util import NoDIDataError, nAI_countries, AI_countries
-from .util import DI_date_format
+import pandas as pd
+import primap2 as pm2
+import pycountry
+import unfccc_di_api
+import xarray as xr
 
 
-from .UNFCCC_DI_reader_io import save_DI_dataset, save_DI_country_data
+from .unfccc_di_reader_config import (
+    cat_code_regexp,
+    di_query_filters,
+    di_to_pm2if_template_ai,
+    di_to_pm2if_template_nai,
+)
+from .unfccc_di_reader_io import save_DI_country_data, save_DI_dataset
+from .util import AI_countries, DI_date_format, nAI_countries
 
 
 
 
 def read_UNFCCC_DI_for_country(
 def read_UNFCCC_DI_for_country(
         country_code: str,
         country_code: str,
-        category_groups: Optional[Dict]=None,
+        category_groups: Optional[dict]=None,
         read_subsectors: bool=False,
         read_subsectors: bool=False,
         save_data: Optional[bool]=True,
         save_data: Optional[bool]=True,
         date_str: Optional[str]=None,
         date_str: Optional[str]=None,
@@ -36,7 +35,6 @@ def read_UNFCCC_DI_for_country(
     reads data for a country from the UNFCCC DI interface and saves to native and
     reads data for a country from the UNFCCC DI interface and saves to native and
     interchange format
     interchange format
     """
     """
-
     # read the data
     # read the data
     if use_zenodo:
     if use_zenodo:
         data_df = read_UNFCCC_DI_for_country_df_zenodo(
         data_df = read_UNFCCC_DI_for_country_df_zenodo(
@@ -81,7 +79,7 @@ def read_UNFCCC_DI_for_country(
 
 
 def read_UNFCCC_DI_for_country_df(
 def read_UNFCCC_DI_for_country_df(
         country_code: str,
         country_code: str,
-        category_groups: Optional[Dict]=None,
+        category_groups: Optional[dict]=None,
         read_subsectors: bool=False,
         read_subsectors: bool=False,
         debug: Optional[bool]=False,
         debug: Optional[bool]=False,
 )->pd.DataFrame:
 )->pd.DataFrame:
@@ -193,7 +191,7 @@ def read_UNFCCC_DI_for_country_df(
                     node_codes = node_codes + (
                     node_codes = node_codes + (
                         [sub_node.identifier for sub_node in sub_nodes])
                         [sub_node.identifier for sub_node in sub_nodes])
                 else:
                 else:
-                    node_codes = node_codes + [node.identifier]
+                    node_codes = [*node_codes, node.identifier]
             if debug:
             if debug:
                 print(f"Found node_codes: {node_codes}")
                 print(f"Found node_codes: {node_codes}")
             # add category node_codes to query
             # add category node_codes to query
@@ -254,7 +252,7 @@ def read_UNFCCC_DI_for_country_df(
 
 
 def read_UNFCCC_DI_for_country_df_zenodo(
 def read_UNFCCC_DI_for_country_df_zenodo(
         country_code: str,
         country_code: str,
-        category_groups: Optional[Dict]=None,
+        category_groups: Optional[dict]=None,
         read_subsectors: bool=False,
         read_subsectors: bool=False,
         debug: Optional[bool]=False,
         debug: Optional[bool]=False,
 )->pd.DataFrame:
 )->pd.DataFrame:
@@ -338,7 +336,6 @@ def convert_DI_data_to_pm2_if(
     TODO: consider moving the specification template into this function and just use the config parameter
     TODO: consider moving the specification template into this function and just use the config parameter
     to overwrite certain parameters (makes sense if function is used in a broader context
     to overwrite certain parameters (makes sense if function is used in a broader context
     """
     """
-
     print("Convert data to PRIMAP2 interchange format")
     print("Convert data to PRIMAP2 interchange format")
 
 
     # create a copy of the data to avoid data altering the original data
     # create a copy of the data to avoid data altering the original data
@@ -373,7 +370,7 @@ def convert_DI_data_to_pm2_if(
 
 
     # set the scenario to today's date if not given explicitly
     # set the scenario to today's date if not given explicitly
     if date_str == "country":
     if date_str == "country":
-        pm2if_specifications["coords_defaults"]["scenario"] = f"DIrolling"
+        pm2if_specifications["coords_defaults"]["scenario"] = "DIrolling"
     elif date_str is None:
     elif date_str is None:
         today = date.today()
         today = date.today()
         date_str = today.strftime(DI_date_format)
         date_str = today.strftime(DI_date_format)
@@ -434,7 +431,8 @@ def convert_DI_data_to_pm2_if(
         data_temp["category_copy"] = data_temp["category"]
         data_temp["category_copy"] = data_temp["category"]
 
 
     # replace category name and code by just the code
     # replace category name and code by just the code
-    repl = lambda m: m.group('code')
+    def repl(m):
+        return m.group("code")
     data_temp["category"] = data_temp["category"].str.replace(cat_code_regexp, repl,
     data_temp["category"] = data_temp["category"].str.replace(cat_code_regexp, repl,
                                                               regex=True)
                                                               regex=True)
 
 
@@ -473,7 +471,6 @@ def read_UNFCCC_DI_for_country_group(
     The function reads all data in one go using datalad run. as the output data file
     The function reads all data in one go using datalad run. as the output data file
     names are unknown beforehand datalad run uses explicit=false
     names are unknown beforehand datalad run uses explicit=false
     '''
     '''
-
     today = date.today()
     today = date.today()
     date_str = today.strftime(DI_date_format)
     date_str = today.strftime(DI_date_format)
 
 

+ 25 - 22
UNFCCC_GHG_data/UNFCCC_DI_reader/UNFCCC_DI_reader_datalad.py → src/unfccc_ghg_data/unfccc_di_reader/unfccc_di_reader_datalad.py

@@ -1,12 +1,15 @@
 from datetime import date
 from datetime import date
-from typing import Union, Optional
+from typing import Optional, Union
+
 import datalad.api
 import datalad.api
 from datalad.support.exceptions import IncompleteResultsError
 from datalad.support.exceptions import IncompleteResultsError
-from UNFCCC_GHG_data.helper import root_path, code_path
 
 
-from .UNFCCC_DI_reader_helper import get_input_and_output_files_for_country_DI
+from unfccc_ghg_data.helper import code_path, root_path
+
+from .unfccc_di_reader_helper import get_input_and_output_files_for_country_DI
 from .util import DI_date_format
 from .util import DI_date_format
 
 
+
 ## datalad and pydoit interface functions
 ## datalad and pydoit interface functions
 def read_DI_for_country_datalad(
 def read_DI_for_country_datalad(
         country: str,
         country: str,
@@ -16,13 +19,13 @@ def read_DI_for_country_datalad(
     and output files and using datalad run to trigger the data reading
     and output files and using datalad run to trigger the data reading
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     country: str
     country: str
         country name or ISO 3-letter country code
         country name or ISO 3-letter country code
 
 
     """
     """
-
     # get date to determine output filename
     # get date to determine output filename
     today = date.today()
     today = date.today()
     date_str = today.strftime(DI_date_format)
     date_str = today.strftime(DI_date_format)
@@ -34,10 +37,10 @@ def read_DI_for_country_datalad(
     print(f"Attempting to read DI data for {country_info['name']}.")
     print(f"Attempting to read DI data for {country_info['name']}.")
     print("#"*80)
     print("#"*80)
     print("")
     print("")
-    print(f"Using the UNFCCC_DI_reader")
+    print("Using the unfccc_di_reader")
     print("")
     print("")
-    print(f"Run the script using datalad run via the python api")
-    script = code_path / "UNFCCC_DI_reader" / "read_UNFCCC_DI_for_country.py"
+    print("Run the script using datalad run via the python api")
+    script = code_path / "unfccc_di_reader" / "read_unfccc_di_for_country.py"
     script = script.relative_to(root_path)
     script = script.relative_to(root_path)
 
 
     cmd = f"./venv/bin/python3 {script.as_posix()} --country={country_info['code']} " \
     cmd = f"./venv/bin/python3 {script.as_posix()} --country={country_info['code']} " \
@@ -68,6 +71,7 @@ def process_DI_for_country_datalad(
     and output files and using datalad run to trigger the data processing
     and output files and using datalad run to trigger the data processing
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     country: str
     country: str
@@ -76,7 +80,6 @@ def process_DI_for_country_datalad(
         Date of the data to be processed in the format %Y-%m-%d (e.g. 2023-01-30). If
         Date of the data to be processed in the format %Y-%m-%d (e.g. 2023-01-30). If
         no date is given the last data read will be processed.
         no date is given the last data read will be processed.
     """
     """
-
     # get all the info for the country
     # get all the info for the country
     country_info = get_input_and_output_files_for_country_DI(country, date_str,
     country_info = get_input_and_output_files_for_country_DI(country, date_str,
                                                              raw=True, verbose=True)
                                                              raw=True, verbose=True)
@@ -84,10 +87,10 @@ def process_DI_for_country_datalad(
     print(f"Attempting to process DI data for {country_info['name']}.")
     print(f"Attempting to process DI data for {country_info['name']}.")
     print("#"*80)
     print("#"*80)
     print("")
     print("")
-    print(f"Using the UNFCCC_DI_reader")
+    print("Using the unfccc_di_reader")
     print("")
     print("")
-    print(f"Run the script using datalad run via the python api")
-    script = code_path / "UNFCCC_DI_reader" / "process_UNFCCC_DI_for_country.py"
+    print("Run the script using datalad run via the python api")
+    script = code_path / "unfccc_di_reader" / "process_unfccc_di_for_country.py"
     script = script.relative_to(root_path)
     script = script.relative_to(root_path)
 
 
     cmd = f"./venv/bin/python3 {script.as_posix()} --country={country_info['code']} " \
     cmd = f"./venv/bin/python3 {script.as_posix()} --country={country_info['code']} " \
@@ -117,6 +120,7 @@ def read_DI_for_country_group_datalad(
     and output files and using datalad run to trigger the data processing
     and output files and using datalad run to trigger the data processing
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     country: str
     country: str
@@ -125,7 +129,6 @@ def read_DI_for_country_group_datalad(
         Date of the data to be processed in the format %Y-%m-%d (e.g. 2023-01-30). If
         Date of the data to be processed in the format %Y-%m-%d (e.g. 2023-01-30). If
         no date is given the last data read will be processed.
         no date is given the last data read will be processed.
     """
     """
-
     if annexI:
     if annexI:
         country_group = "AnnexI"
         country_group = "AnnexI"
     else:
     else:
@@ -134,15 +137,15 @@ def read_DI_for_country_group_datalad(
     print(f"Attempting to read DI data for {country_group}.")
     print(f"Attempting to read DI data for {country_group}.")
     print("#"*80)
     print("#"*80)
     print("")
     print("")
-    print(f"Using the UNFCCC_DI_reader")
+    print("Using the unfccc_di_reader")
     print("")
     print("")
-    print(f"Run the script using datalad run via the python api")
-    script = code_path / "UNFCCC_DI_reader" / "read_UNFCCC_DI_for_country_group.py"
+    print("Run the script using datalad run via the python api")
+    script = code_path / "unfccc_di_reader" / "read_unfccc_di_for_country_group.py"
     script = script.relative_to(root_path)
     script = script.relative_to(root_path)
 
 
     cmd = f"./venv/bin/python3 {script.as_posix()} "
     cmd = f"./venv/bin/python3 {script.as_posix()} "
     if annexI:
     if annexI:
-        cmd = cmd + f" --annexI"
+        cmd = cmd + " --annexI"
 
 
     try:
     try:
         datalad.api.run(
         datalad.api.run(
@@ -170,6 +173,7 @@ def process_DI_for_country_group_datalad(
     and output files and using datalad run to trigger the data processing
     and output files and using datalad run to trigger the data processing
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     annexI: bool (default False)
     annexI: bool (default False)
@@ -179,7 +183,6 @@ def process_DI_for_country_group_datalad(
         Date of the data to be processed in the format %Y-%m-%d (e.g. 2023-01-30). If
         Date of the data to be processed in the format %Y-%m-%d (e.g. 2023-01-30). If
         no date is given the last data read will be processed.
         no date is given the last data read will be processed.
     """
     """
-
     if annexI:
     if annexI:
         country_group = "AnnexI"
         country_group = "AnnexI"
     else:
     else:
@@ -188,15 +191,15 @@ def process_DI_for_country_group_datalad(
     print(f"Attempting to process DI data for {country_group}.")
     print(f"Attempting to process DI data for {country_group}.")
     print("#"*80)
     print("#"*80)
     print("")
     print("")
-    print(f"Using the UNFCCC_DI_reader")
+    print("Using the unfccc_di_reader")
     print("")
     print("")
-    print(f"Run the script using datalad run via the python api")
-    script = code_path / "UNFCCC_DI_reader" / "process_UNFCCC_DI_for_country_group.py"
+    print("Run the script using datalad run via the python api")
+    script = code_path / "unfccc_di_reader" / "process_unfccc_di_for_country_group.py"
     script = script.relative_to(root_path)
     script = script.relative_to(root_path)
 
 
     cmd = f"./venv/bin/python3 {script.as_posix()} "
     cmd = f"./venv/bin/python3 {script.as_posix()} "
     if annexI:
     if annexI:
-        cmd = cmd + f" --annexI"
+        cmd = cmd + " --annexI"
     if date_str is not None:
     if date_str is not None:
         cmd = cmd + f" --date_str={date_str}"
         cmd = cmd + f" --date_str={date_str}"
     else:
     else:
@@ -216,4 +219,4 @@ def process_DI_for_country_group_datalad(
         print(f"IncompleteResultsError occurred when running {cmd}: {IRE}")
         print(f"IncompleteResultsError occurred when running {cmd}: {IRE}")
     except Exception as ex:
     except Exception as ex:
         print(f"Exception occurred when running {cmd}")
         print(f"Exception occurred when running {cmd}")
-        print(ex.message)
+        print(ex.message)

+ 25 - 23
UNFCCC_GHG_data/UNFCCC_DI_reader/UNFCCC_DI_reader_helper.py → src/unfccc_ghg_data/unfccc_di_reader/unfccc_di_reader_helper.py

@@ -1,14 +1,20 @@
 import json
 import json
 import re
 import re
-from typing import Optional, Dict, List, Union
-from pathlib import Path
 from datetime import date
 from datetime import date
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.UNFCCC_CRF_reader_core import find_latest_date
-from .util import regex_date, DI_date_format
-from UNFCCC_GHG_data.helper import custom_country_mapping
-from UNFCCC_GHG_data.helper import get_country_code, get_country_name
-from UNFCCC_GHG_data.helper import extracted_data_path_UNFCCC, root_path, code_path
-from UNFCCC_GHG_data.helper import dataset_path_UNFCCC
+from pathlib import Path
+from typing import Optional, Union
+
+from unfccc_ghg_data.helper import (
+    custom_country_mapping,
+    dataset_path_UNFCCC,
+    extracted_data_path_UNFCCC,
+    get_country_code,
+    get_country_name,
+    root_path,
+)
+from unfccc_ghg_data.UNFCCC_CRF_reader.UNFCCC_CRF_reader_core import find_latest_date
+
+from .util import DI_date_format, regex_date
 
 
 
 
 ## helper functions
 ## helper functions
@@ -21,7 +27,6 @@ def determine_filename(
     """
     """
     Determine the filename for a dataset from given country code and date string.
     Determine the filename for a dataset from given country code and date string.
 
 
-
     Parameters
     Parameters
     ----------
     ----------
     country_code: str
     country_code: str
@@ -33,13 +38,13 @@ def determine_filename(
     hash: str
     hash: str
 
 
     Returns
     Returns
+    -------
     _______
     _______
         pathlib Path object for the file name (without suffix)
         pathlib Path object for the file name (without suffix)
 
 
     """
     """
-
     # get the country folder
     # get the country folder
-    with open(extracted_data_path_UNFCCC / "folder_mapping.json", "r") as mapping_file:
+    with open(extracted_data_path_UNFCCC / "folder_mapping.json") as mapping_file:
         folder_mapping = json.load(mapping_file)
         folder_mapping = json.load(mapping_file)
 
 
     if country_code in folder_mapping:
     if country_code in folder_mapping:
@@ -98,10 +103,10 @@ def determine_dataset_filename(
     hash: str
     hash: str
 
 
     Returns
     Returns
+    -------
     _______
     _______
         pathlib Path object for the file name (without suffix)
         pathlib Path object for the file name (without suffix)
     """
     """
-
     # get the country folder
     # get the country folder
     if annexI:
     if annexI:
         current_dataset_path = dataset_path_UNFCCC / "DI_AnnexI"
         current_dataset_path = dataset_path_UNFCCC / "DI_AnnexI"
@@ -127,11 +132,10 @@ def get_input_and_output_files_for_country_DI(
         date_str: str,
         date_str: str,
         raw: bool,
         raw: bool,
         verbose: Optional[bool]=True,
         verbose: Optional[bool]=True,
-) -> Dict[str, Union[List, str]]:
+) -> dict[str, Union[list, str]]:
     """
     """
     Get input and output files for a given country
     Get input and output files for a given country
     """
     """
-
     country_info = {}
     country_info = {}
 
 
     if country in custom_country_mapping:
     if country in custom_country_mapping:
@@ -175,7 +179,7 @@ def get_input_and_output_files_for_country_DI(
                         suffix in ['yaml', 'csv', 'nc']]
                         suffix in ['yaml', 'csv', 'nc']]
 
 
         if verbose:
         if verbose:
-            print(f"The following files are considered as input_files:")
+            print("The following files are considered as input_files:")
             for file in input_files:
             for file in input_files:
                 print(file)
                 print(file)
             print("")
             print("")
@@ -186,7 +190,7 @@ def get_input_and_output_files_for_country_DI(
                     suffix in ['yaml', 'csv', 'nc']]
                     suffix in ['yaml', 'csv', 'nc']]
 
 
     if verbose:
     if verbose:
-        print(f"The following files are considered as output_files:")
+        print("The following files are considered as output_files:")
         for file in output_files:
         for file in output_files:
             print(file)
             print(file)
         print("")
         print("")
@@ -202,19 +206,18 @@ def get_input_and_output_files_for_country_DI(
 def get_present_hashes_for_country_DI(
 def get_present_hashes_for_country_DI(
         country_code: str,
         country_code: str,
         raw: bool,
         raw: bool,
-) -> List:
+) -> list:
     '''
     '''
     Get the hashes of outputs
     Get the hashes of outputs
     '''
     '''
-
     regex_hash = r"_([a-f0-9]*)_"
     regex_hash = r"_([a-f0-9]*)_"
     if raw:
     if raw:
-        regex_hash = regex_hash + "raw_hash\.nc"
+        regex_hash = regex_hash + "raw_hash\\.nc"
     else:
     else:
-        regex_hash = regex_hash + "hash\.nc"
+        regex_hash = regex_hash + "hash\\.nc"
 
 
     # get the country folder
     # get the country folder
-    with open(extracted_data_path_UNFCCC / "folder_mapping.json", "r") as mapping_file:
+    with open(extracted_data_path_UNFCCC / "folder_mapping.json") as mapping_file:
         folder_mapping = json.load(mapping_file)
         folder_mapping = json.load(mapping_file)
 
 
     if country_code in folder_mapping:
     if country_code in folder_mapping:
@@ -252,7 +255,6 @@ def find_latest_DI_data(
     '''
     '''
     Find the path to the nc file with the latest DI data for a given country
     Find the path to the nc file with the latest DI data for a given country
     '''
     '''
-
     if raw:
     if raw:
         regex = f"{country_code}_DI_{regex_date}" + r"_raw\.nc"
         regex = f"{country_code}_DI_{regex_date}" + r"_raw\.nc"
     else:
     else:
@@ -260,7 +262,7 @@ def find_latest_DI_data(
         #regex = f"{country_code}_DI_{regex_date}" + r"\.nc"
         #regex = f"{country_code}_DI_{regex_date}" + r"\.nc"
 
 
     # get the country folder
     # get the country folder
-    with open(extracted_data_path_UNFCCC / "folder_mapping.json", "r") as mapping_file:
+    with open(extracted_data_path_UNFCCC / "folder_mapping.json") as mapping_file:
         folder_mapping = json.load(mapping_file)
         folder_mapping = json.load(mapping_file)
 
 
     if country_code in folder_mapping:
     if country_code in folder_mapping:

+ 4 - 5
UNFCCC_GHG_data/UNFCCC_DI_reader/UNFCCC_DI_reader_io.py → src/unfccc_ghg_data/unfccc_di_reader/unfccc_di_reader_io.py

@@ -2,9 +2,10 @@ import primap2 as pm2
 import xarray as xr
 import xarray as xr
 from dask.base import tokenize
 from dask.base import tokenize
 
 
-from UNFCCC_GHG_data.helper import root_path
+from unfccc_ghg_data.helper import root_path
+
+from .unfccc_di_reader_helper import determine_dataset_filename, determine_filename
 
 
-from .UNFCCC_DI_reader_helper import determine_filename, determine_dataset_filename
 
 
 def save_DI_country_data(
 def save_DI_country_data(
         data_pm2: xr.Dataset,
         data_pm2: xr.Dataset,
@@ -14,7 +15,6 @@ def save_DI_country_data(
     save primap2 and IF data to country folder
     save primap2 and IF data to country folder
     can be used for raw and processed data but for a single country only
     can be used for raw and processed data but for a single country only
     '''
     '''
-
     # preparations
     # preparations
     data_if = data_pm2.pr.to_interchange_format()
     data_if = data_pm2.pr.to_interchange_format()
 
 
@@ -88,7 +88,6 @@ def save_DI_dataset(
     save primap2 and IF data to dataset folder
     save primap2 and IF data to dataset folder
     can be used for raw and processed data but not to save to country folders
     can be used for raw and processed data but not to save to country folders
     '''
     '''
-
     # preparations
     # preparations
     data_if = data_pm2.pr.to_interchange_format()
     data_if = data_pm2.pr.to_interchange_format()
     if annexI:
     if annexI:
@@ -149,4 +148,4 @@ def save_DI_dataset(
         file_hash = filename_hash.name + suffix
         file_hash = filename_hash.name + suffix
         if file_date.exists():
         if file_date.exists():
             file_date.unlink()
             file_date.unlink()
-        file_date.symlink_to(file_hash)
+        file_date.symlink_to(file_hash)

+ 21 - 26
UNFCCC_GHG_data/UNFCCC_DI_reader/UNFCCC_DI_reader_proc.py → src/unfccc_ghg_data/unfccc_di_reader/unfccc_di_reader_proc.py

@@ -1,21 +1,16 @@
-import primap2 as pm2
-import unfccc_di_api
-import numpy as np
-import xarray as xr
 import re
 import re
 from datetime import date
 from datetime import date
-from typing import Optional, Dict, List, Union
+from typing import Optional, Union
 
 
-from .UNFCCC_DI_reader_config import di_processing_info
-from .UNFCCC_DI_reader_config import cat_conversion
-from .util import NoDIDataError, nAI_countries
-from .util import DI_date_format
+import primap2 as pm2
+import xarray as xr
 
 
-from UNFCCC_GHG_data.helper import process_data_for_country, gas_baskets
-from .UNFCCC_DI_reader_helper import find_latest_DI_data
-from .UNFCCC_DI_reader_helper import determine_filename
+from unfccc_ghg_data.helper import gas_baskets, process_data_for_country
 
 
-from .UNFCCC_DI_reader_io import save_DI_dataset, save_DI_country_data
+from .unfccc_di_reader_config import cat_conversion, di_processing_info
+from .unfccc_di_reader_helper import determine_filename, find_latest_DI_data
+from .unfccc_di_reader_io import save_DI_country_data, save_DI_dataset
+from .util import DI_date_format, nAI_countries
 
 
 
 
 def process_and_save_UNFCCC_DI_for_country(
 def process_and_save_UNFCCC_DI_for_country(
@@ -25,7 +20,6 @@ def process_and_save_UNFCCC_DI_for_country(
     """
     """
     process data and save them to disk using default parameters
     process data and save them to disk using default parameters
     """
     """
-
     # get latest dataset if no date given
     # get latest dataset if no date given
     if date_str is None:
     if date_str is None:
         # get the latest date
         # get the latest date
@@ -82,19 +76,19 @@ def process_and_save_UNFCCC_DI_for_country(
 
 
 def process_UNFCCC_DI_for_country(
 def process_UNFCCC_DI_for_country(
         data_country: xr.Dataset,
         data_country: xr.Dataset,
-        entities_to_ignore: List[str],
-        gas_baskets: Dict[str, List[str]],
-        filter_dims: Optional[Dict[str, List[str]]] = None,
-        category_conversion: Dict[str, Dict] = None,
-        sectors_out: List[str] = None,
-        processing_info_country: Dict = None,
+        entities_to_ignore: list[str],
+        gas_baskets: dict[str, list[str]],
+        filter_dims: Optional[dict[str, list[str]]] = None,
+        category_conversion: dict[str, dict] = None,
+        sectors_out: list[str] = None,
+        processing_info_country: dict = None,
 ) -> xr.Dataset:
 ) -> xr.Dataset:
     """
     """
-        Process data from DI interface (where necessary).
-        * Downscaling including subtraction of time series
-        * country specific sector aggregation
-        * Conversion to IPCC2006 categories
-        * general sector and gas basket aggregation (in new categories)
+    Process data from DI interface (where necessary).
+    * Downscaling including subtraction of time series
+    * country specific sector aggregation
+    * Conversion to IPCC2006 categories
+    * general sector and gas basket aggregation (in new categories)
     """
     """
     # get country
     # get country
     countries = list(data_country.coords[data_country.attrs['area']].values)
     countries = list(data_country.coords[data_country.attrs['area']].values)
@@ -167,6 +161,7 @@ def process_UNFCCC_DI_for_country_group(
     This function processes DI data for all countries in a group (annexI or non-AnnexI)
     This function processes DI data for all countries in a group (annexI or non-AnnexI)
 
 
     Parameters
     Parameters
+    ----------
     __________
     __________
 
 
     annexI: bool (default False)
     annexI: bool (default False)
@@ -205,7 +200,7 @@ def process_UNFCCC_DI_for_country_group(
             data_country = data_country.assign_coords({"scenario (Access_Date)": [
             data_country = data_country.assign_coords({"scenario (Access_Date)": [
                 f"DI{date_str_today}"]})
                 f"DI{date_str_today}"]})
             scen_dim = data_country.attrs["scen"]
             scen_dim = data_country.attrs["scen"]
-            data_country.attrs["scen"] = f"scenario (Process_Date)"
+            data_country.attrs["scen"] = "scenario (Process_Date)"
             data_country = data_country.rename({scen_dim: data_country.attrs["scen"]})
             data_country = data_country.rename({scen_dim: data_country.attrs["scen"]})
 
 
             if data_all is None:
             if data_all is None:

+ 4 - 4
UNFCCC_GHG_data/UNFCCC_DI_reader/util.py → src/unfccc_ghg_data/unfccc_di_reader/util.py

@@ -1,13 +1,13 @@
-import unfccc_di_api
 import pandas as pd
 import pandas as pd
-from UNFCCC_GHG_data.helper import code_path
+
+from unfccc_ghg_data.helper import code_path
 
 
 #reader = unfccc_di_api.UNFCCCApiReader()
 #reader = unfccc_di_api.UNFCCCApiReader()
 #nAI_countries = list(reader.non_annex_one_reader.parties["code"])
 #nAI_countries = list(reader.non_annex_one_reader.parties["code"])
-nAI_countries = list(pd.read_csv(code_path / 'UNFCCC_DI_reader' /
+nAI_countries = list(pd.read_csv(code_path / 'unfccc_di_reader' /
                                  'DI_NAI_parties.conf')["code"])
                                  'DI_NAI_parties.conf')["code"])
 #AI_countries = list(reader.annex_one_reader.parties["code"])
 #AI_countries = list(reader.annex_one_reader.parties["code"])
-AI_countries = list(pd.read_csv(code_path / 'UNFCCC_DI_reader' /
+AI_countries = list(pd.read_csv(code_path / 'unfccc_di_reader' /
                                 'DI_AI_parties.conf')["code"])
                                 'DI_AI_parties.conf')["code"])
 
 
 DI_date_format = '%Y-%m-%d'
 DI_date_format = '%Y-%m-%d'

+ 1 - 1
UNFCCC_GHG_data/UNFCCC_downloader/__init__.py → src/unfccc_ghg_data/unfccc_downloader/__init__.py

@@ -2,4 +2,4 @@ from .unfccc_submission_info import get_unfccc_submission_info
 
 
 __all__ = [
 __all__ = [
     "get_unfccc_submission_info",
     "get_unfccc_submission_info",
-]
+]

+ 13 - 12
UNFCCC_GHG_data/UNFCCC_downloader/download_annexI.py → src/unfccc_ghg_data/unfccc_downloader/download_annexI.py

@@ -1,17 +1,18 @@
 import argparse
 import argparse
-import pandas as pd
-import requests
+import os
 import shutil
 import shutil
 import time
 import time
-import os
 import zipfile
 import zipfile
 from datetime import date
 from datetime import date
+from pathlib import Path
+from random import randrange
+
+import pandas as pd
+import requests
 from selenium.webdriver import Firefox
 from selenium.webdriver import Firefox
 from selenium.webdriver.firefox.options import Options
 from selenium.webdriver.firefox.options import Options
-from random import randrange
-from pathlib import Path
 
 
-from UNFCCC_GHG_data.helper import root_path, downloaded_data_path_UNFCCC
+from unfccc_ghg_data.helper import downloaded_data_path_UNFCCC, root_path
 
 
 ###############
 ###############
 #
 #
@@ -60,7 +61,7 @@ if int(year) == 2019:
     )
     )
 elif int(year) in range(2020,2023):
 elif int(year) in range(2020,2023):
     url = (
     url = (
-        "https://unfccc.int/ghg-inventories-annex-i-parties/{}".format(year)
+        f"https://unfccc.int/ghg-inventories-annex-i-parties/{year}"
     )
     )
 elif int(year) >= 2023:
 elif int(year) >= 2023:
     url = (
     url = (
@@ -132,7 +133,7 @@ for idx, submission in items.iterrows():
         if Path(local_filename).stat().st_size in error_file_sizes:
         if Path(local_filename).stat().st_size in error_file_sizes:
             # found the error page. delete file
             # found the error page. delete file
             os.remove(local_filename)
             os.remove(local_filename)
-    
+
     # now we have removed error pages, so a present file should not be overwritten
     # now we have removed error pages, so a present file should not be overwritten
     if (not local_filename.exists()) and (not local_filename.is_symlink()):
     if (not local_filename.exists()) and (not local_filename.is_symlink()):
         i = 0  # reset counter
         i = 0  # reset counter
@@ -140,7 +141,7 @@ for idx, submission in items.iterrows():
             # for i = 0 and i = 5 try to get a new session ID
             # for i = 0 and i = 5 try to get a new session ID
             if i == 1 or i == 5:
             if i == 1 or i == 5:
                 driver = Firefox(options=options)
                 driver = Firefox(options=options)
-    
+
                 # visit the main data page once to create cookies
                 # visit the main data page once to create cookies
                 driver.get(url)
                 driver.get(url)
                 time.sleep(20)
                 time.sleep(20)
@@ -154,15 +155,15 @@ for idx, submission in items.iterrows():
             r = requests.get(url, stream=True, cookies=cookies)
             r = requests.get(url, stream=True, cookies=cookies)
             with open(str(local_filename), 'wb') as f:
             with open(str(local_filename), 'wb') as f:
                 shutil.copyfileobj(r.raw, f)
                 shutil.copyfileobj(r.raw, f)
-            
+
             # check file size. if 210 or 212 bytes it's the error page
             # check file size. if 210 or 212 bytes it's the error page
             if Path(local_filename).stat().st_size in error_file_sizes:
             if Path(local_filename).stat().st_size in error_file_sizes:
                 # found the error page. delete file
                 # found the error page. delete file
                 os.remove(local_filename)
                 os.remove(local_filename)
-            
+
             # sleep a bit to avoid running into captchas
             # sleep a bit to avoid running into captchas
             time.sleep(randrange(5, 15))
             time.sleep(randrange(5, 15))
-            
+
         if local_filename.exists():
         if local_filename.exists():
             new_downloaded.append(submission)
             new_downloaded.append(submission)
             print(f"Download => {local_filename.relative_to(root_path)}")
             print(f"Download => {local_filename.relative_to(root_path)}")

+ 13 - 11
UNFCCC_GHG_data/UNFCCC_downloader/download_ndc.py → src/unfccc_ghg_data/unfccc_downloader/download_ndc.py

@@ -1,13 +1,15 @@
-import pandas as pd
-import requests
-import shutil
-import time
 import os
 import os
 import re
 import re
+import shutil
+import time
 from datetime import date
 from datetime import date
-from random import randrange
-from UNFCCC_GHG_data.helper import downloaded_data_path_UNFCCC
 from pathlib import Path
 from pathlib import Path
+from random import randrange
+
+import pandas as pd
+import requests
+
+from unfccc_ghg_data.helper import downloaded_data_path_UNFCCC
 
 
 """
 """
 based on download_bur from national-inventory-submissions
 based on download_bur from national-inventory-submissions
@@ -73,7 +75,7 @@ for idx, submission in submissions.iterrows():
         if Path(local_filename_underscore).stat().st_size in error_file_sizes:
         if Path(local_filename_underscore).stat().st_size in error_file_sizes:
             # found the error page. delete file
             # found the error page. delete file
             os.remove(local_filename_underscore)
             os.remove(local_filename_underscore)
-    
+
     # now we have to remove error pages, so a present file should not be overwritten
     # now we have to remove error pages, so a present file should not be overwritten
     if (not local_filename_underscore.exists()) \
     if (not local_filename_underscore.exists()) \
             and (not local_filename_underscore.is_symlink()):
             and (not local_filename_underscore.is_symlink()):
@@ -83,15 +85,15 @@ for idx, submission in submissions.iterrows():
             r = requests.get(url, stream=True)
             r = requests.get(url, stream=True)
             with open(str(local_filename_underscore), 'wb') as f:
             with open(str(local_filename_underscore), 'wb') as f:
                 shutil.copyfileobj(r.raw, f)
                 shutil.copyfileobj(r.raw, f)
-            
+
             # check file size. if 210 or 212 bytes it's the error page
             # check file size. if 210 or 212 bytes it's the error page
             if Path(local_filename_underscore).stat().st_size in error_file_sizes:
             if Path(local_filename_underscore).stat().st_size in error_file_sizes:
                 # found the error page. delete file
                 # found the error page. delete file
                 os.remove(local_filename_underscore)
                 os.remove(local_filename_underscore)
-            
+
             # sleep a bit to avoid running into captchas
             # sleep a bit to avoid running into captchas
             time.sleep(randrange(5, 15))
             time.sleep(randrange(5, 15))
-            
+
         if local_filename_underscore.exists():
         if local_filename_underscore.exists():
             new_downloaded.append(submission)
             new_downloaded.append(submission)
             print("Download => downloaded_data/UNFCCC/" + country + "/" +
             print("Download => downloaded_data/UNFCCC/" + country + "/" +
@@ -105,4 +107,4 @@ for idx, submission in submissions.iterrows():
 
 
 
 
 df = pd.DataFrame(new_downloaded)
 df = pd.DataFrame(new_downloaded)
-df.to_csv(downloaded_data_path_UNFCCC / "00_new_downloads_ndc-{}.csv".format(date.today()), index=False)
+df.to_csv(downloaded_data_path_UNFCCC / f"00_new_downloads_ndc-{date.today()}.csv", index=False)

+ 13 - 11
UNFCCC_GHG_data/UNFCCC_downloader/download_non-annexI.py → src/unfccc_ghg_data/unfccc_downloader/download_non-annexI.py

@@ -1,15 +1,17 @@
 import argparse
 import argparse
-import pandas as pd
-import requests
+import os
 import shutil
 import shutil
 import time
 import time
-import os
 from datetime import date
 from datetime import date
+from pathlib import Path
+from random import randrange
+
+import pandas as pd
+import requests
 from selenium.webdriver import Firefox
 from selenium.webdriver import Firefox
 from selenium.webdriver.firefox.options import Options
 from selenium.webdriver.firefox.options import Options
-from random import randrange
-from pathlib import Path
-from UNFCCC_GHG_data.helper import root_path, downloaded_data_path_UNFCCC
+
+from unfccc_ghg_data.helper import downloaded_data_path_UNFCCC, root_path
 
 
 ###############
 ###############
 #
 #
@@ -94,7 +96,7 @@ for idx, submission in submissions.iterrows():
         if Path(local_filename).stat().st_size in error_file_sizes:
         if Path(local_filename).stat().st_size in error_file_sizes:
             # found the error page. delete file
             # found the error page. delete file
             os.remove(local_filename)
             os.remove(local_filename)
-    
+
     # now we have removed error pages, so a present file should not be overwritten
     # now we have removed error pages, so a present file should not be overwritten
     if (not local_filename.exists()) and (not local_filename.is_symlink()):
     if (not local_filename.exists()) and (not local_filename.is_symlink()):
         i = 0  # reset counter
         i = 0  # reset counter
@@ -102,7 +104,7 @@ for idx, submission in submissions.iterrows():
             # for i = 0 and i = 5 try to get a new session ID
             # for i = 0 and i = 5 try to get a new session ID
             if i == 1 or i == 5:
             if i == 1 or i == 5:
                 driver = Firefox(options=options)
                 driver = Firefox(options=options)
-    
+
                 # visit the main data page once to create cookies
                 # visit the main data page once to create cookies
                 driver.get(url)
                 driver.get(url)
                 time.sleep(20)
                 time.sleep(20)
@@ -116,15 +118,15 @@ for idx, submission in submissions.iterrows():
             r = requests.get(url, stream=True, cookies=cookies)
             r = requests.get(url, stream=True, cookies=cookies)
             with open(str(local_filename), 'wb') as f:
             with open(str(local_filename), 'wb') as f:
                 shutil.copyfileobj(r.raw, f)
                 shutil.copyfileobj(r.raw, f)
-            
+
             # check file size. if 210 or 212 bytes it's the error page
             # check file size. if 210 or 212 bytes it's the error page
             if Path(local_filename).stat().st_size in error_file_sizes:
             if Path(local_filename).stat().st_size in error_file_sizes:
                 # found the error page. delete file
                 # found the error page. delete file
                 os.remove(local_filename)
                 os.remove(local_filename)
-            
+
             # sleep a bit to avoid running into captchas
             # sleep a bit to avoid running into captchas
             time.sleep(randrange(5, 15))
             time.sleep(randrange(5, 15))
-            
+
         if local_filename.exists():
         if local_filename.exists():
             new_downloaded.append(submission)
             new_downloaded.append(submission)
             print(f"Download => {local_filename.relative_to(root_path)}")
             print(f"Download => {local_filename.relative_to(root_path)}")

+ 1 - 1
UNFCCC_GHG_data/UNFCCC_downloader/fetch_submissions_annexI.py → src/unfccc_ghg_data/unfccc_downloader/fetch_submissions_annexI.py

@@ -8,7 +8,7 @@ from selenium.webdriver import Firefox
 from selenium.webdriver.firefox.options import Options
 from selenium.webdriver.firefox.options import Options
 from random import randrange
 from random import randrange
 from unfccc_submission_info import get_unfccc_submission_info
 from unfccc_submission_info import get_unfccc_submission_info
-from UNFCCC_GHG_data.helper import downloaded_data_path_UNFCCC
+from unfccc_ghg_data.helper import downloaded_data_path_UNFCCC
 
 
 max_tries = 10
 max_tries = 10
 
 

+ 7 - 6
UNFCCC_GHG_data/UNFCCC_downloader/fetch_submissions_bur.py → src/unfccc_ghg_data/unfccc_downloader/fetch_submissions_bur.py

@@ -1,20 +1,21 @@
 #import requests
 #import requests
-import time
-import pandas as pd
 import re
 import re
-
+import time
 from pathlib import Path
 from pathlib import Path
+from random import randrange
+
+import pandas as pd
 from bs4 import BeautifulSoup
 from bs4 import BeautifulSoup
 from selenium.webdriver import Firefox
 from selenium.webdriver import Firefox
 from selenium.webdriver.firefox.options import Options
 from selenium.webdriver.firefox.options import Options
-from random import randrange
 from unfccc_submission_info import get_unfccc_submission_info
 from unfccc_submission_info import get_unfccc_submission_info
-from UNFCCC_GHG_data.helper import downloaded_data_path_UNFCCC
+
+from unfccc_ghg_data.helper import downloaded_data_path_UNFCCC
 
 
 """
 """
 Download UNFCCC Biennial Update Report submissions
 Download UNFCCC Biennial Update Report submissions
 from Non-Annex I Parties and create list of submissions as CSV file
 from Non-Annex I Parties and create list of submissions as CSV file
-Based on `process_bur` from national-inventory-submissions 
+Based on `process_bur` from national-inventory-submissions
 (https://github.com/openclimatedata/national-inventory-submisions)
 (https://github.com/openclimatedata/national-inventory-submisions)
 """
 """
 
 

+ 8 - 8
UNFCCC_GHG_data/UNFCCC_downloader/fetch_submissions_nc.py → src/unfccc_ghg_data/unfccc_downloader/fetch_submissions_nc.py

@@ -1,21 +1,21 @@
 #import requests
 #import requests
-import time
-import pandas as pd
 import re
 import re
-
+import time
 from pathlib import Path
 from pathlib import Path
+from random import randrange
+
+import pandas as pd
 from bs4 import BeautifulSoup
 from bs4 import BeautifulSoup
 from selenium.webdriver import Firefox
 from selenium.webdriver import Firefox
 from selenium.webdriver.firefox.options import Options
 from selenium.webdriver.firefox.options import Options
-from random import randrange
-from UNFCCC_GHG_data.UNFCCC_downloader import \
-    get_unfccc_submission_info
-from UNFCCC_GHG_data.helper import downloaded_data_path_UNFCCC
+
+from unfccc_ghg_data.helper import downloaded_data_path_UNFCCC
+from unfccc_ghg_data.UNFCCC_downloader import get_unfccc_submission_info
 
 
 """
 """
 Download UNFCCC Biennial Update Report submissions
 Download UNFCCC Biennial Update Report submissions
 from Non-Annex I Parties and create list of submissions as CSV file
 from Non-Annex I Parties and create list of submissions as CSV file
-Based on `process_bur` from national-inventory-submissions 
+Based on `process_bur` from national-inventory-submissions
 (https://github.com/openclimatedata/national-inventory-submisions)
 (https://github.com/openclimatedata/national-inventory-submisions)
 """
 """
 
 

+ 6 - 6
UNFCCC_GHG_data/UNFCCC_downloader/unfccc_submission_info.py → src/unfccc_ghg_data/unfccc_downloader/unfccc_submission_info.py

@@ -1,11 +1,11 @@
 # helper functions to gather submission info from UNFCCC website
 # helper functions to gather submission info from UNFCCC website
-import time
 import re
 import re
+import time
 from random import randrange
 from random import randrange
-from typing import Dict, List
-from selenium.webdriver import Firefox
-from selenium.common.exceptions import WebDriverException
+
 from bs4 import BeautifulSoup
 from bs4 import BeautifulSoup
+from selenium.common.exceptions import WebDriverException
+from selenium.webdriver import Firefox
 
 
 
 
 def get_unfccc_submission_info(
 def get_unfccc_submission_info(
@@ -13,7 +13,7 @@ def get_unfccc_submission_info(
         driver: Firefox,
         driver: Firefox,
         max_tries: int=10,
         max_tries: int=10,
 
 
-) -> List[Dict[str,str]]:
+) -> list[dict[str,str]]:
     info = []
     info = []
     pattern = re.compile(r"BUR ?\d")
     pattern = re.compile(r"BUR ?\d")
     pattern_NC = re.compile(r"NC ?\d")
     pattern_NC = re.compile(r"NC ?\d")
@@ -53,7 +53,7 @@ def get_unfccc_submission_info(
             subtree = html.find_all(
             subtree = html.find_all(
                 class_="field field--name-field-document-country field--type-termstore-entity-reference field--label-inline")
                 class_="field field--name-field-document-country field--type-termstore-entity-reference field--label-inline")
             country = subtree[0].find(class_="field--item").contents[0]
             country = subtree[0].find(class_="field--item").contents[0]
-        except (AttributeError, IndexError) as e:
+        except (AttributeError, IndexError):
             # author as backup for country
             # author as backup for country
             subtree = html.find_all(class_="field--name-field-document-ca")
             subtree = html.find_all(class_="field--name-field-document-ca")
             country = subtree[0].find(class_="field--item").contents[0]
             country = subtree[0].find(class_="field--item").contents[0]

+ 0 - 0
src/unfccc_ghg_data/unfccc_reader/Argentina/__init__.py


+ 10 - 9
UNFCCC_GHG_data/UNFCCC_reader/Argentina/read_ARG_BUR4_from_pdf.py → src/unfccc_ghg_data/unfccc_reader/Argentina/read_ARG_BUR4_from_pdf.py

@@ -2,13 +2,13 @@
 # Data is read from the xlsx file
 # Data is read from the xlsx file
 
 
 import sys
 import sys
+
 import camelot
 import camelot
 import primap2 as pm2
 import primap2 as pm2
 from primap2.pm2io._conversion import convert_ipcc_code_primap_to_primap2
 from primap2.pm2io._conversion import convert_ipcc_code_primap_to_primap2
-from UNFCCC_GHG_data.helper import downloaded_data_path, extracted_data_path, \
-    process_data_for_country
-from UNFCCC_GHG_data.UNFCCC_DI_reader.UNFCCC_DI_reader_config import gas_baskets
 
 
+from unfccc_ghg_data.helper import downloaded_data_path, extracted_data_path, process_data_for_country
+from unfccc_ghg_data.unfccc_di_reader.unfccc_di_reader_config import gas_baskets
 
 
 # ###
 # ###
 # configuration
 # configuration
@@ -83,7 +83,7 @@ cat_codes_manual = {  # conversion to PRIMAP1 format
     'S/N': 'MMULTIOP',
     'S/N': 'MMULTIOP',
 }
 }
 
 
-cat_code_regexp = r'(?P<UNFCCC_GHG_data>^[A-Z0-9]{1,8}).*'
+cat_code_regexp = r'(?P<code>^[A-Z0-9]{1,8}).*'
 
 
 time_format = "%Y"
 time_format = "%Y"
 
 
@@ -216,7 +216,7 @@ for page in pages_to_read:
     if page in range(232, 235):
     if page in range(232, 235):
         df_current.iloc[
         df_current.iloc[
             metadata["entity"][0], metadata["entity"][1]] = "KYOTOGHG (SARGWP100)"
             metadata["entity"][0], metadata["entity"][1]] = "KYOTOGHG (SARGWP100)"
-    # drop all rows where the index cols (category UNFCCC_GHG_data and name) are both NaN
+    # drop all rows where the index cols (category code and name) are both NaN
     # as without one of them there is no category information
     # as without one of them there is no category information
     df_current.dropna(axis=0, how='all', subset=index_cols, inplace=True)
     df_current.dropna(axis=0, how='all', subset=index_cols, inplace=True)
     # set index. necessary for the stack operation in the conversion to long format
     # set index. necessary for the stack operation in the conversion to long format
@@ -250,7 +250,8 @@ for page in pages_to_read:
 
 
     df_current["category"] = df_current["category"].replace(cat_codes_manual)
     df_current["category"] = df_current["category"].replace(cat_codes_manual)
     # then the regex replacements
     # then the regex replacements
-    repl = lambda m: convert_ipcc_code_primap_to_primap2('IPC' + m.group('UNFCCC_GHG_data'))
+    def repl(m):
+        return convert_ipcc_code_primap_to_primap2('IPC' + m.group('code'))
     df_current["category"] = df_current["category"].str.replace(cat_code_regexp, repl,
     df_current["category"] = df_current["category"].str.replace(cat_code_regexp, repl,
                                                                 regex=True)
                                                                 regex=True)
 
 
@@ -308,8 +309,7 @@ for page in pages_to_read_fgases:
         dict(zip(df_current.columns, list(df_current.loc[idx_header[0]]))), axis=1)
         dict(zip(df_current.columns, list(df_current.loc[idx_header[0]]))), axis=1)
     df_current = df_current.drop(idx_header)
     df_current = df_current.drop(idx_header)
 
 
-    # drop all rows where the index cols (category UNFCCC_GHG_data and name) are both NaN
-    # as without one of them there is no category information
+    # drop all rows where the index cols (category code
     df_current.dropna(axis=0, how='all', subset=index_cols_fgases, inplace=True)
     df_current.dropna(axis=0, how='all', subset=index_cols_fgases, inplace=True)
     # set index. necessary for the stack operation in the conversion to long format
     # set index. necessary for the stack operation in the conversion to long format
     # df_current = df_current.set_index(index_cols)
     # df_current = df_current.set_index(index_cols)
@@ -347,7 +347,8 @@ for page in pages_to_read_fgases:
 
 
     df_current["category"] = df_current["category"].replace(cat_codes_manual)
     df_current["category"] = df_current["category"].replace(cat_codes_manual)
     # then the regex repalcements
     # then the regex repalcements
-    repl = lambda m: convert_ipcc_code_primap_to_primap2('IPC' + m.group('UNFCCC_GHG_data'))
+    def repl(m):
+        return convert_ipcc_code_primap_to_primap2('IPC' + m.group('code'))
     df_current["category"] = df_current["category"].str.replace(cat_code_regexp, repl,
     df_current["category"] = df_current["category"].str.replace(cat_code_regexp, repl,
                                                                 regex=True)
                                                                 regex=True)
 
 

+ 0 - 0
src/unfccc_ghg_data/unfccc_reader/Chile/__init__.py


+ 6 - 6
UNFCCC_GHG_data/UNFCCC_reader/Chile/config_CHL_BUR4.py → src/unfccc_ghg_data/unfccc_reader/Chile/config_chl_bur4.py

@@ -42,8 +42,8 @@ filter_remove_IPCC2006 = {
             '3.G.1', '3.G.2',
             '3.G.1', '3.G.2',
             # additional subsector levels of 4.A.1 (3.A.1.a Forest land remaining forest land)
             # additional subsector levels of 4.A.1 (3.A.1.a Forest land remaining forest land)
             '4.A.1.a', '4.A.1.a.i', '4.A.1.a.i.1', '4.A.1.a.i.1.a', '4.A.1.a.i.1.b', '4.A.1.a.i.1.c',
             '4.A.1.a', '4.A.1.a.i', '4.A.1.a.i.1', '4.A.1.a.i.1.a', '4.A.1.a.i.1.b', '4.A.1.a.i.1.c',
-            '4.A.1.a.i.1.d', '4.A.1.a.i.1.e', '4.A.1.a.i.1.f', '4.A.1.a.i.1.g', '4.A.1.a.i.1.h', 
-            '4.A.1.a.i.1.i', '4.A.1.a.i.1.j', '4.A.1.a.i.1.k', '4.A.1.a.i.1.l', '4.A.1.a.i.2', 
+            '4.A.1.a.i.1.d', '4.A.1.a.i.1.e', '4.A.1.a.i.1.f', '4.A.1.a.i.1.g', '4.A.1.a.i.1.h',
+            '4.A.1.a.i.1.i', '4.A.1.a.i.1.j', '4.A.1.a.i.1.k', '4.A.1.a.i.1.l', '4.A.1.a.i.2',
             '4.A.1.a.i.2.a', '4.A.1.a.i.2.b', '4.A.1.a.i.2.c', '4.A.1.a.i.2.d', '4.A.1.a.i.2.e',
             '4.A.1.a.i.2.a', '4.A.1.a.i.2.b', '4.A.1.a.i.2.c', '4.A.1.a.i.2.d', '4.A.1.a.i.2.e',
             '4.A.1.a.i.2.f', '4.A.1.a.i.2.g', '4.A.1.a.i.2.h', '4.A.1.a.i.2.i', '4.A.1.a.i.2.j',
             '4.A.1.a.i.2.f', '4.A.1.a.i.2.g', '4.A.1.a.i.2.h', '4.A.1.a.i.2.i', '4.A.1.a.i.2.j',
             '4.A.1.a.i.2.k', '4.A.1.a.i.2.l', '4.A.1.a.i.3', '4.A.1.a.i.3.a', '4.A.1.a.i.3.b',
             '4.A.1.a.i.2.k', '4.A.1.a.i.2.l', '4.A.1.a.i.3', '4.A.1.a.i.3.a', '4.A.1.a.i.3.b',
@@ -90,7 +90,7 @@ cat_mapping = { # categories not listed here have the same UNFCCC_GHG_data as in
     '3.B.4.e': '3.A.2.i',
     '3.B.4.e': '3.A.2.i',
     '3.B.5': '3.C.6',
     '3.B.5': '3.C.6',
     '3.C': '3.C.7',
     '3.C': '3.C.7',
-    '3.D.1': '3.C.4', 
+    '3.D.1': '3.C.4',
     '3.D.2': '3.C.5',
     '3.D.2': '3.C.5',
     '3.D.2.a': '3.C.5.a', # not in climate_categories
     '3.D.2.a': '3.C.5.a', # not in climate_categories
     '3.D.2.b': '3.C.5.b', # not in climate_categories
     '3.D.2.b': '3.C.5.b', # not in climate_categories
@@ -166,10 +166,10 @@ cat_mapping = { # categories not listed here have the same UNFCCC_GHG_data as in
 # comments
 # comments
 # '2.F.1.a.': included in '2.F.1.a.3', # not in climate categories
 # '2.F.1.a.': included in '2.F.1.a.3', # not in climate categories
 # '2.F.1.b.': included in '2.F.1.a.2', # not in climate categories
 # '2.F.1.b.': included in '2.F.1.a.2', # not in climate categories
-# '2.F.1.c.': included in '2.F.1.a.1', # not in climate categories 
+# '2.F.1.c.': included in '2.F.1.a.1', # not in climate categories
 # '2.F.1.d.': included in 2.F.1.a (transport refigeration)
 # '2.F.1.d.': included in 2.F.1.a (transport refigeration)
 # '2.F.1.e.', includeded in 2.F.1.a (stationary air conditioning)
 # '2.F.1.e.', includeded in 2.F.1.a (stationary air conditioning)
-# '2.F.1.f.': 2.F.1.b, (mobile air conditioning) 
+# '2.F.1.f.': 2.F.1.b, (mobile air conditioning)
 #    '3.A.4.f.': included in '3.A.1.j',
 #    '3.A.4.f.': included in '3.A.1.j',
 # '3.A.4.g.': included in '3.A.1.j',
 # '3.A.4.g.': included in '3.A.1.j',
 # '3.A.4.g.i.',
 # '3.A.4.g.i.',
@@ -183,4 +183,4 @@ aggregate_cats = {
     '3.C': {'sources': ['3.C.1', '3.C.2', '3.C.3', '3.C.4', '3.C.5', '3.C.6', '3.C.7', '3.C.8'], 'name': 'Aggregate sources and non-CO2 emissions sources on land'},
     '3.C': {'sources': ['3.C.1', '3.C.2', '3.C.3', '3.C.4', '3.C.5', '3.C.6', '3.C.7', '3.C.8'], 'name': 'Aggregate sources and non-CO2 emissions sources on land'},
     '3.D': {'sources': ['3.D.1', '3.D.2'], 'name': 'Other'},
     '3.D': {'sources': ['3.D.1', '3.D.2'], 'name': 'Other'},
     '3': {'sources': ['3.A', '3.B', '3.C', '3.D'], 'name': 'AFOLU'},
     '3': {'sources': ['3.A', '3.B', '3.C', '3.D'], 'name': 'AFOLU'},
-}
+}

+ 6 - 6
UNFCCC_GHG_data/UNFCCC_reader/Chile/read_CHL_BUR4_from_xlsx.py → src/unfccc_ghg_data/unfccc_reader/Chile/read_CHL_BUR4_from_xlsx.py

@@ -3,13 +3,13 @@
 
 
 import os
 import os
 import sys
 import sys
+
 import pandas as pd
 import pandas as pd
 import primap2 as pm2
 import primap2 as pm2
+from config_chl_bur4 import aggregate_cats, cat_mapping, filter_remove_IPCC2006
+from primap2.pm2io._data_reading import filter_data, matches_time_format
 
 
-from config_CHL_BUR4 import cat_mapping, filter_remove_IPCC2006, aggregate_cats
-from UNFCCC_GHG_data.helper import downloaded_data_path, extracted_data_path
-from primap2.pm2io._data_reading import matches_time_format
-from primap2.pm2io._data_reading import filter_data
+from unfccc_ghg_data.helper import downloaded_data_path, extracted_data_path
 
 
 # ###
 # ###
 # configuration
 # configuration
@@ -47,7 +47,7 @@ unit_info = {
 }
 }
 cols_to_drop = ['Unnamed: 14', 'Unnamed: 16', 'Código IPCC.1',
 cols_to_drop = ['Unnamed: 14', 'Unnamed: 16', 'Código IPCC.1',
                 'Categorías de fuente y sumidero de gases de efecto invernadero.1']
                 'Categorías de fuente y sumidero de gases de efecto invernadero.1']
-# columns for category UNFCCC_GHG_data and original category name
+# columns for category code and original category name
 index_cols = ['Código IPCC', 'Categorías de fuente y sumidero de gases de efecto invernadero']
 index_cols = ['Código IPCC', 'Categorías de fuente y sumidero de gases de efecto invernadero']
 
 
 # operations on long format DF
 # operations on long format DF
@@ -164,7 +164,7 @@ for year in years_to_read:
     df_current = pd.read_excel(input_folder / inventory_file, sheet_name=str(year), skiprows=2, nrows=442, engine="openpyxl")
     df_current = pd.read_excel(input_folder / inventory_file, sheet_name=str(year), skiprows=2, nrows=442, engine="openpyxl")
     # drop the columns which are empty and repetition of the metadata for the second block
     # drop the columns which are empty and repetition of the metadata for the second block
     df_current.drop(cols_to_drop, axis=1, inplace=True)
     df_current.drop(cols_to_drop, axis=1, inplace=True)
-    # drop all rows where the index cols (category UNFCCC_GHG_data and name) are both NaN
+    # drop all rows where the index cols (category code and name) are both NaN
     # as without one of them there is no category information
     # as without one of them there is no category information
     df_current.dropna(axis=0, how='all', subset=index_cols, inplace=True)
     df_current.dropna(axis=0, how='all', subset=index_cols, inplace=True)
     # set multi-index. necessary for the stack operation in the conversion to long format
     # set multi-index. necessary for the stack operation in the conversion to long format

+ 6 - 6
UNFCCC_GHG_data/UNFCCC_reader/Chile/read_CHL_BUR5_from_xlsx.py → src/unfccc_ghg_data/unfccc_reader/Chile/read_CHL_BUR5_from_xlsx.py

@@ -3,13 +3,13 @@
 
 
 import os
 import os
 import sys
 import sys
+
 import pandas as pd
 import pandas as pd
 import primap2 as pm2
 import primap2 as pm2
+from config_chl_bur4 import aggregate_cats, cat_mapping, filter_remove_IPCC2006
+from primap2.pm2io._data_reading import filter_data, matches_time_format
 
 
-from config_CHL_BUR4 import cat_mapping, filter_remove_IPCC2006, aggregate_cats
-from UNFCCC_GHG_data.helper import downloaded_data_path, extracted_data_path
-from primap2.pm2io._data_reading import matches_time_format
-from primap2.pm2io._data_reading import filter_data
+from unfccc_ghg_data.helper import downloaded_data_path, extracted_data_path
 
 
 # ###
 # ###
 # configuration
 # configuration
@@ -48,7 +48,7 @@ unit_info = {
 }
 }
 cols_to_drop = ['Unnamed: 14', 'Unnamed: 16', 'Código IPCC.1',
 cols_to_drop = ['Unnamed: 14', 'Unnamed: 16', 'Código IPCC.1',
                 'Categorías de fuente y sumidero de gases de efecto invernadero.1']
                 'Categorías de fuente y sumidero de gases de efecto invernadero.1']
-# columns for category UNFCCC_GHG_data and original category name
+# columns for category code and original category name
 index_cols = ['Código IPCC', 'Categorías de fuente y sumidero de gases de efecto invernadero']
 index_cols = ['Código IPCC', 'Categorías de fuente y sumidero de gases de efecto invernadero']
 
 
 # operations on long format DF
 # operations on long format DF
@@ -165,7 +165,7 @@ for year in years_to_read:
     df_current = pd.read_excel(input_folder / inventory_file, sheet_name=str(year), skiprows=2, nrows=442, engine="openpyxl")
     df_current = pd.read_excel(input_folder / inventory_file, sheet_name=str(year), skiprows=2, nrows=442, engine="openpyxl")
     # drop the columns which are empty and repetition of the metadata for the second block
     # drop the columns which are empty and repetition of the metadata for the second block
     df_current.drop(cols_to_drop, axis=1, inplace=True)
     df_current.drop(cols_to_drop, axis=1, inplace=True)
-    # drop all rows where the index cols (category UNFCCC_GHG_data and name) are both NaN
+    # drop all rows where the index cols (category code and name) are both NaN
     # as without one of them there is no category information
     # as without one of them there is no category information
     df_current.dropna(axis=0, how='all', subset=index_cols, inplace=True)
     df_current.dropna(axis=0, how='all', subset=index_cols, inplace=True)
     # set multi-index. necessary for the stack operation in the conversion to long format
     # set multi-index. necessary for the stack operation in the conversion to long format

+ 0 - 0
src/unfccc_ghg_data/unfccc_reader/Colombia/__init__.py


+ 4 - 3
UNFCCC_GHG_data/UNFCCC_reader/Colombia/read_COL_BUR3_from_xlsx.py → src/unfccc_ghg_data/unfccc_reader/Colombia/read_COL_BUR3_from_xlsx.py

@@ -5,7 +5,8 @@
 import pandas as pd
 import pandas as pd
 import primap2 as pm2
 import primap2 as pm2
 from primap2.pm2io._data_reading import matches_time_format
 from primap2.pm2io._data_reading import matches_time_format
-from UNFCCC_GHG_data.helper import downloaded_data_path, extracted_data_path
+
+from unfccc_ghg_data.helper import downloaded_data_path, extracted_data_path
 
 
 # TODO: add fgases, sector summing (proc version)
 # TODO: add fgases, sector summing (proc version)
 
 
@@ -207,7 +208,7 @@ data_if = pm2.pm2io.convert_long_dataframe_if(
 
 
 
 
 # combine CO2 emissions and absorptions
 # combine CO2 emissions and absorptions
-data_CO2 = data_if[data_if[f"entity"].isin([
+data_CO2 = data_if[data_if["entity"].isin([
     'CO2 Absorptions', 'CO2 Emissions'])]
     'CO2 Absorptions', 'CO2 Emissions'])]
 
 
 time_format = '%Y'
 time_format = '%Y'
@@ -246,4 +247,4 @@ if not output_folder.exists():
 pm2.pm2io.write_interchange_format(output_folder / (output_filename + coords_terminologies["category"]), data_if)
 pm2.pm2io.write_interchange_format(output_folder / (output_filename + coords_terminologies["category"]), data_if)
 
 
 encoding = {var: compression for var in data_pm2.data_vars}
 encoding = {var: compression for var in data_pm2.data_vars}
-data_pm2.pr.to_netcdf(output_folder / (output_filename + coords_terminologies["category"] + ".nc"), encoding=encoding)
+data_pm2.pr.to_netcdf(output_folder / (output_filename + coords_terminologies["category"] + ".nc"), encoding=encoding)

+ 0 - 0
src/unfccc_ghg_data/unfccc_reader/Indonesia/__init__.py


+ 7 - 5
UNFCCC_GHG_data/UNFCCC_reader/Indonesia/read_IDN_BUR3_from_pdf.py → src/unfccc_ghg_data/unfccc_reader/Indonesia/read_IDN_BUR3_from_pdf.py

@@ -2,12 +2,13 @@
 # Data is read from pdf
 # Data is read from pdf
 # only the 2019 inventory is read as the BUR refers to BUR2 for earlier years
 # only the 2019 inventory is read as the BUR refers to BUR2 for earlier years
 
 
-import pandas as pd
-import primap2 as pm2
 import camelot
 import camelot
 import numpy as np
 import numpy as np
+import pandas as pd
+import primap2 as pm2
 from primap2.pm2io._data_reading import matches_time_format
 from primap2.pm2io._data_reading import matches_time_format
-from UNFCCC_GHG_data.helper import downloaded_data_path, extracted_data_path
+
+from unfccc_ghg_data.helper import downloaded_data_path, extracted_data_path
 
 
 # ###
 # ###
 # configuration
 # configuration
@@ -31,7 +32,7 @@ year = 2019
 entity_row = 0
 entity_row = 0
 unit_row = 1
 unit_row = 1
 index_cols = "Categories"
 index_cols = "Categories"
-# special header as category UNFCCC_GHG_data and name in one column
+# special header as category code and name in one column
 header_long = ["orig_cat_name", "entity", "unit", "time", "data"]
 header_long = ["orig_cat_name", "entity", "unit", "time", "data"]
 
 
 
 
@@ -195,7 +196,8 @@ df_all["category"] = df_all["orig_cat_name"]
 # first the manual replacements
 # first the manual replacements
 df_all["category"] = df_all["category"].replace(cat_codes_manual)
 df_all["category"] = df_all["category"].replace(cat_codes_manual)
 # then the regex replacements
 # then the regex replacements
-repl = lambda m: m.group('code')
+def repl(m):
+    return m.group('code')
 df_all["category"] = df_all["category"].str.replace(cat_code_regexp, repl, regex=True)
 df_all["category"] = df_all["category"].str.replace(cat_code_regexp, repl, regex=True)
 df_all = df_all.reset_index(drop=True)
 df_all = df_all.reset_index(drop=True)
 
 

+ 0 - 0
src/unfccc_ghg_data/unfccc_reader/Israel/__init__.py


+ 2 - 1
UNFCCC_GHG_data/UNFCCC_reader/Israel/config_ISR_BUR2.py → src/unfccc_ghg_data/unfccc_reader/Israel/config_isr_bur2.py

@@ -1,5 +1,6 @@
 #### configuration for trend tables
 #### configuration for trend tables
 import locale
 import locale
+
 gwp_to_use = 'SARGWP100'
 gwp_to_use = 'SARGWP100'
 terminology_proc = 'IPCC2006_PRIMAP'
 terminology_proc = 'IPCC2006_PRIMAP'
 # bunkers [0,1] need different specs
 # bunkers [0,1] need different specs
@@ -432,4 +433,4 @@ def is_int(input: str) -> bool:
         locale.atoi(input)
         locale.atoi(input)
         return True
         return True
     except:
     except:
-        return False
+        return False

+ 25 - 12
UNFCCC_GHG_data/UNFCCC_reader/Israel/read_ISR_BUR2_from_pdf.py → src/unfccc_ghg_data/unfccc_reader/Israel/read_ISR_BUR2_from_pdf.py

@@ -2,21 +2,34 @@
 
 
 # TODO: bunkers trend tables not read because of special format
 # TODO: bunkers trend tables not read because of special format
 
 
-from UNFCCC_GHG_data.helper import process_data_for_country, GWP_factors
-from UNFCCC_GHG_data.helper import downloaded_data_path, extracted_data_path
+import locale
+
 import camelot
 import camelot
-import primap2 as pm2
 import pandas as pd
 import pandas as pd
-import locale
+import primap2 as pm2
 
 
 # configuration import
 # configuration import
-from config_ISR_BUR2 import trend_table_def, gwp_to_use
-from config_ISR_BUR2 import inv_tab_conf, inv_table_def
-from config_ISR_BUR2 import coords_cols, coords_terminologies, coords_defaults, \
-    coords_value_mapping, filter_remove, filter_keep, meta_data
-from config_ISR_BUR2 import cat_conversion, sectors_to_save, downscaling, \
-    cats_to_agg, gas_baskets, terminology_proc
-from config_ISR_BUR2 import is_int, basket_copy
+from config_isr_bur2 import (
+    basket_copy,
+    cat_conversion,
+    cats_to_agg,
+    coords_cols,
+    coords_defaults,
+    coords_terminologies,
+    coords_value_mapping,
+    downscaling,
+    filter_remove,
+    gas_baskets,
+    inv_tab_conf,
+    inv_table_def,
+    is_int,
+    meta_data,
+    sectors_to_save,
+    terminology_proc,
+    trend_table_def,
+)
+
+from unfccc_ghg_data.helper import downloaded_data_path, extracted_data_path, process_data_for_country
 
 
 ### genral configuration
 ### genral configuration
 input_folder = downloaded_data_path / 'UNFCCC' / 'Israel' / 'BUR2'
 input_folder = downloaded_data_path / 'UNFCCC' / 'Israel' / 'BUR2'
@@ -298,4 +311,4 @@ pm2.pm2io.write_interchange_format(
 encoding = {var: compression for var in data_proc_pm2.data_vars}
 encoding = {var: compression for var in data_proc_pm2.data_vars}
 data_proc_pm2.pr.to_netcdf(
 data_proc_pm2.pr.to_netcdf(
     output_folder / (output_filename + terminology_proc + ".nc"),
     output_folder / (output_filename + terminology_proc + ".nc"),
-    encoding=encoding)
+    encoding=encoding)

+ 0 - 0
src/unfccc_ghg_data/unfccc_reader/Malaysia/__init__.py


+ 1 - 2
UNFCCC_GHG_data/UNFCCC_reader/Malaysia/config_MYS_BUR3.py → src/unfccc_ghg_data/unfccc_reader/Malaysia/config_mys_bur3.py

@@ -1,4 +1,3 @@
-import pandas as pd
 gwp_to_use = "AR4GWP100"
 gwp_to_use = "AR4GWP100"
 
 
 
 
@@ -673,4 +672,4 @@ gas_baskets = {
     'KYOTOGHG (AR4GWP100)': ['CO2', 'CH4', 'N2O', 'FGASES (AR4GWP100)'],
     'KYOTOGHG (AR4GWP100)': ['CO2', 'CH4', 'N2O', 'FGASES (AR4GWP100)'],
     'KYOTOGHG (AR5GWP100)': ['CO2', 'CH4', 'N2O', 'FGASES (AR5GWP100)'],
     'KYOTOGHG (AR5GWP100)': ['CO2', 'CH4', 'N2O', 'FGASES (AR5GWP100)'],
     'KYOTOGHG (AR6GWP100)': ['CO2', 'CH4', 'N2O', 'FGASES (AR6GWP100)'],
     'KYOTOGHG (AR6GWP100)': ['CO2', 'CH4', 'N2O', 'FGASES (AR6GWP100)'],
-}
+}

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików