Browse Source

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 year ago
parent
commit
cb6cc3fdd7
100 changed files with 6882 additions and 1148 deletions
  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
-__pycache__
+
+# private dev 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.
 
-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.**

+ 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
 from doit import get_var
 import os
+import sys
 
 # TODO: task for folder mapping
 
 # 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 {
-        '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
 def task_set_env():
     """
@@ -42,11 +53,11 @@ def task_map_folders():
     Create or update the folder mapping in the given folder
     """
     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']}"],
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 
@@ -57,10 +68,10 @@ def task_update_bur():
         'targets': ['downloaded_data/UNFCCC/submissions-bur.csv'],
         'actions': ['datalad run -m "Fetch BUR submissions" '
                     '-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'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 
@@ -72,13 +83,13 @@ def task_download_bur():
         # before download
         'actions': ['datalad run -m "Download BUR submissions" '
                     '-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"
                     ],
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 
@@ -88,10 +99,10 @@ def task_update_nc():
         'targets': ['downloaded_data/UNFCCC/submissions-nc.csv'],
         'actions': ['datalad run -m "Fetch NC submissions" '
                     '-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'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 
@@ -103,13 +114,13 @@ def task_download_nc():
         # before download
         'actions': ['datalad run -m "Download NC submissions" '
                     '-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"
                     ],
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 # 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']}' "
                     "--explicit "
                     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']}"],
         'task_dep': ['set_env'],
         '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 "
                     f"{update_aI_config['category']}{update_aI_config['year']}' "
                     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"./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"
                     ],
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 
@@ -160,13 +171,13 @@ def task_download_ndc():
     """ Download NDC submissions """
     return {
         '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"
                     ],
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 
@@ -180,16 +191,16 @@ read_config = {
 
 # TODO: make individual task for non-UNFCCC submissions
 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 {
-        '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"./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"
                     ],
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 
@@ -208,11 +219,12 @@ read_config_crf = {
 def task_read_unfccc_crf_submission():
     """ Read CRF submission for a country """
     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"--submission_year={read_config_crf['submission_year']} "
         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"
         ]
     if read_config_crf["re_read"] == "True":
@@ -221,16 +233,17 @@ def task_read_unfccc_crf_submission():
         'actions': actions,
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 
 def task_read_new_unfccc_crf_for_year():
     """ 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."""
-    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"./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"
                ]
     # 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,
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 
 def task_test_read_unfccc_crf_for_year():
     """ 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."""
-    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"--country={read_config_crf['country']} "
                ]
@@ -267,26 +280,26 @@ def task_test_read_unfccc_crf_for_year():
         'actions': actions,
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 
 def task_compile_raw_unfccc_crf_for_year():
     """ 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."""
-    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']} "
                ]
     return {
         'actions': actions,
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 # 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 = {
     "country": get_var('country', None),
     "date": get_var('date', None),
@@ -297,41 +310,43 @@ read_config_di = {
 def task_read_unfccc_di_for_country():
     """ Read DI data for a country """
     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"./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"
         ]
     return {
         'actions': actions,
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 def task_process_unfccc_di_for_country():
     """ Process DI data for a country """
     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"./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"
         ]
     return {
         'actions': actions,
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 def task_read_unfccc_di_for_country_group():
     """ Read DI data for a country group """
     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"
         ]
     if read_config_di["annexI"] == "True":
@@ -341,15 +356,16 @@ def task_read_unfccc_di_for_country_group():
         'actions': actions,
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 
 def task_process_unfccc_di_for_country_group():
     """ Process DI data for a country group """
     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",
         ]
     if read_config_di["annexI"] == "True":
@@ -361,7 +377,7 @@ def task_process_unfccc_di_for_country_group():
         'actions': actions,
         'task_dep': ['set_env'],
         'verbosity': 2,
-        'setup': ['setup_venv'],
+        'setup': ['in_venv'],
     }
 
 # general tasks
@@ -369,10 +385,10 @@ def task_country_info():
     """ Print information on submissions and datasets
     available for given country"""
     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']}"],
         'task_dep': ['set_env'],
         '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]
-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 UNFCCC_reader
-from . import UNFCCC_CRF_reader
-from . import UNFCCC_DI_reader
-from . import UNFCCC_downloader
 
 __all__ = [
     "helper",
@@ -12,4 +8,4 @@ __all__ = [
     "UNFCCC_CRF_reader",
     "UNFCCC_DI_reader",
     "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
-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
 # read the data using datalad run.
 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()
 country = args.country
 
@@ -19,4 +23,4 @@ print("")
 
 #print available datasets
 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
 from pathlib import 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)
     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:
         root_path = Path(root_path_env).resolve()
     return 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"
 extracted_data_path = root_path / "extracted_data"
 extracted_data_path_UNFCCC = extracted_data_path / "UNFCCC"
@@ -42,7 +45,7 @@ custom_folders = {
     'Bolivia_(Plurinational_State_of)': 'BOL',
     'Türkiye': 'TUR',
     'Iran_(Islamic_Republic_of)': 'IRN',
-    'Côte_dIvoire': 'CIV',
+    'Côte_d`Ivoire': 'CIV',
     'Democratic_Republic_of_the_Congo': "COD",
     'European_Union': 'EUA',
     'Taiwan': 'TWN',
@@ -154,4 +157,4 @@ gas_baskets = {
                             'PFCS (AR5GWP100)'],
     'KYOTOGHG (AR6GWP100)': ['CO2', 'CH4', 'N2O', 'SF6', 'NF3', 'HFCS (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
-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
 # 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 re
-import xarray as xr
-import pandas as pd
-import numpy as np
-from datetime import date
 from copy import deepcopy
-from typing import Dict, List, Optional
+from datetime import date
 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(
     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,
-    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:
     """
     Process data from DI interface (where necessary).
@@ -32,8 +44,38 @@ def process_data_for_country(
     * country specific sector aggregation
     * Conversion to IPCC2006 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
     countries = list(data_country.coords[data_country.attrs["area"]].values)
     if len(countries) > 1:
@@ -79,7 +121,7 @@ def process_data_for_country(
     # remove unused cats
     data_country = data_country.dropna(f"category ({cat_terminology_in})", how="all")
     # 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
     nan_vars_country = [
         var
@@ -367,7 +409,7 @@ def process_data_for_country(
 
 def convert_categories(
     ds_input: xr.Dataset,
-    conversion: Dict[str, Dict[str, str]],
+    conversion: dict[str, dict[str, str]],
     # terminology_from: str,
     terminology_to: str,
     debug: bool = False,
@@ -431,7 +473,7 @@ def convert_categories(
             nan_vars = [
                 var
                 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)
             if len(data_agg.data_vars) > 0:
@@ -464,7 +506,7 @@ def convert_categories(
 def get_country_name(
     country_code: str,
 ) -> str:
-    """get country name from code"""
+    """Get country name from code"""
     if country_code in custom_country_mapping:
         country_name = custom_country_mapping[country_code]
     else:
@@ -488,6 +530,7 @@ def get_country_code(
     is not a three letter code a search will be performed
 
     Parameters
+    ----------
     __________
     country_name: str
         Country code or name to get the three-letter code for.
@@ -502,7 +545,7 @@ def get_country_code(
         country_code = country_name
     else:
         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_code = country.alpha_3
         except:
@@ -513,7 +556,7 @@ def get_country_code(
             except:
                 raise ValueError(
                     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:
                 country_code = None
@@ -552,7 +595,6 @@ def create_folder_mapping(folder: str, extracted: bool = False) -> None:
         Nothing
 
     """
-
     folder = root_path / folder
     folder_mapping = {}
     # if not extracted:
@@ -595,16 +637,16 @@ def create_folder_mapping(folder: str, extracted: bool = False) -> None:
 def get_country_submissions(
     country_name: str,
     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.
 
     Parameters
     ----------
         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
             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
 
     """
-
     data_folder = downloaded_data_path
 
     country_code = get_country_code(country_name)
@@ -625,7 +666,7 @@ def get_country_submissions(
 
     country_submissions = {}
     if print_sub:
-        print(f"#" * 80)
+        print("#" * 80)
         print(f"The following submissions are available for {country_name}")
     for item in data_folder.iterdir():
         if item.is_dir():
@@ -634,7 +675,7 @@ def get_country_submissions(
                 print("-" * 80)
                 print(f"Data folder {item.name}")
                 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)
             if country_code in folder_mapping:
                 country_folders = folder_mapping[country_code]
@@ -664,11 +705,11 @@ def get_country_submissions(
 def get_country_datasets(
     country_name: str,
     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.
-    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
     ----------
@@ -684,11 +725,10 @@ def get_country_datasets(
         Each value is a list of folders
 
     """
-
     data_folder = extracted_data_path
     data_folder_legacy = legacy_data_path
 
-    # obtain country UNFCCC_GHG_data
+    # obtain country code
     country_code = get_country_code(country_name)
 
     if print_ds:
@@ -697,7 +737,7 @@ def get_country_datasets(
     rep_data = {}
     # data
     if print_ds:
-        print(f"#" * 80)
+        print("#" * 80)
         print(f"The following datasets are available for {country_name}")
     for item in data_folder.iterdir():
         if item.is_dir():
@@ -706,7 +746,7 @@ def get_country_datasets(
                 print("-" * 80)
                 print(f"Data folder {item.name}")
                 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)
             if country_code not in folder_mapping:
                 if print_ds:
@@ -757,7 +797,7 @@ def get_country_datasets(
                         if code_file:
                             data_info = data_info + f"code: {code_file.name}"
                         else:
-                            data_info = data_info + f"code: not found"
+                            data_info = data_info + "code: not found"
 
                         cleaned_datasets_current_folder[key] = data_info
 
@@ -775,7 +815,7 @@ def get_country_datasets(
 
     # legacy data
     if print_ds:
-        print(f"#" * 80)
+        print("#" * 80)
         print(f"The following legacy datasets are available for {country_name}")
     legacy_data = {}
     for item in data_folder_legacy.iterdir():
@@ -785,7 +825,7 @@ def get_country_datasets(
                 print("-" * 80)
                 print(f"Data folder {item.name}")
                 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)
             if country_code not in folder_mapping:
                 if print_ds:
@@ -815,7 +855,7 @@ def get_country_datasets(
                     parts = dataset.split("_")
                     if parts[0] != country_code:
                         cleaned_datasets_current_folder[
-                            f"Wrong UNFCCC_GHG_data: {parts[0]}"
+                            f"Wrong code: {parts[0]}"
                         ] = dataset
                     else:
                         terminology = "_".join(parts[3:])
@@ -865,42 +905,41 @@ def get_code_file(
     Parameters
     ----------
         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
             String of the submission
 
         print_info: bool = False
-            If True print information on UNFCCC_GHG_data found
+            If True print information on code found
 
     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
-    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.
     if submission[0:3] == "CRF":
-        return root_path / "UNFCCC_CRF_reader"
+        return root_path / "unfccc_crf_reader"
 
     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)
 
     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)
 
     if country_code not in folder_mapping:
         if print_info:
-            print("No UNFCCC_GHG_data available")
+            print("No code available")
             print("")
     else:
         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 code_file_path is not None:
                     raise ValueError(
-                        f"Found multiple UNFCCC_GHG_data candidates: "
+                        f"Found multiple code candidates: "
                         f"{code_file_path} and file.name. "
                         f"Please use only one file with name "
                         f"'read_ISO3_submission_XXX.YYY'."
@@ -918,7 +957,7 @@ def get_code_file(
                 else:
                     if print_info:
                         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
 
@@ -972,7 +1011,8 @@ def fix_rows(
         new_row = new_row.str.replace("- ", "-")
         # replace spaces in numbers
         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)
         data.loc[indices_to_merge[0]] = new_row
         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 . 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",
            "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
 
 import argparse
-import primap2 as pm2
-from pathlib import Path
 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.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
 print(f"The following countries are included in the dataset: {included_countries}")
 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
 specific items in categories 2, 3.H-G, 4
 
@@ -39,6 +39,7 @@ TODO:
 """
 
 import numpy as np
+
 from .util import unit_info
 
 CRF2021 = {
@@ -117,7 +118,7 @@ CRF2021 = {
             ['1. Transport of CO2', ['1.C.1']],
             ['2. Injection and storage', ['1.C.2']],
             ['3. Other', ['1.C.3']],
-            ['Memo items: (1)', ['\IGNORE']],
+            ['Memo items: (1)', ['\\IGNORE']],
             ['International bunkers', ['M.Memo.Int']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['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', 'Total'], 2],
             # 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
             ['Other non-specified', ['1.A.2.g.viii.1', 'Total'], 3],
             ['Liquid Fuels', ['1.A.2.g.viii.1', 'Liquid'], 4],
@@ -501,7 +502,7 @@ CRF2021 = {
             ['Peat', ['1.A.2.g.viii.1', 'Peat'], 4],
             ['Biomass', ['1.A.2.g.viii.1', 'Biomass'], 4],
             # DKE
-            ['Textile', ['\IGNORE', '\IGNORE'], 3],  # (empty)
+            ['Textile', ['\\IGNORE', '\\IGNORE'], 3],  # (empty)
             # DNK, DNM, FIN, DKE
             ['Other manufacturing industries', ['1.A.2.g.viii.3', 'Total'], 3],
             ['Liquid Fuels', ['1.A.2.g.viii.3', 'Liquid'], 4],
@@ -1390,10 +1391,10 @@ CRF2021 = {
             ['Biomass', ['1.A.5.b.iii', 'Biomass'], 3],
             # ESP, FIN
             # 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": {
             'EMISSIONS CH4': "CH4",
@@ -1537,7 +1538,7 @@ CRF2021 = {
             ['a. Injection', ['1.C.2.a']],
             ['b. Storage', ['1.C.2.b']],
             ['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 of imports for storage', ['M.Info.A.TAIS']],
             ['Total A', ['M.Info.A']],
@@ -1545,7 +1546,7 @@ CRF2021 = {
             ['Total amount of CO2 injected at storage sites', ['M.Info.B.TAI']],
             ['Total leakage from transport, injection and storage', ['M.Info.B.TLTIS']],
             ['Total B', ['M.Info.B']],
-            ['Difference (A-B)(6)', ['\IGNORE']],
+            ['Difference (A-B)(6)', ['\\IGNORE']],
         ],
         "entity_mapping": {
             'EMISSIONS CO2(2)': 'CO2',
@@ -1804,61 +1805,61 @@ CRF2021 = {
             # A. Enteric fermentation
             ['A. Enteric fermentation', ['3.A'], 2],
             ['1. Cattle(1)', ['3.A.1'], 3],
-            ['Option A:', ['\IGNORE'], 4],
+            ['Option A:', ['\\IGNORE'], 4],
             ['Dairy cattle', ['3.A.1.Aa'], 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],
             ['Other mature cattle', ['3.A.1.Bb'], 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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
             ['2. Sheep', ['3.A.2'], 3],
             ['3. Swine', ['3.A.3'], 3],
@@ -1879,60 +1880,60 @@ CRF2021 = {
             # Manure Management
             ['B. Manure management', ['3.B'], 2],
             ['1. Cattle(1)', ['3.B.1'], 3],
-            ['Option A:', ['\IGNORE'], 4],
+            ['Option A:', ['\\IGNORE'], 4],
             ['Dairy cattle', ['3.B.1.Aa'], 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],
             ['Other mature cattle', ['3.B.1.Bb'], 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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
             ['2. Sheep', ['3.B.2'], 3],
             ['3. Swine', ['3.B.3'], 3],
@@ -2023,15 +2024,15 @@ CRF2021 = {
             ['Flood prone', ['3.C.2.a']],
             ['Drought prone', ['3.C.2.b']],
             ['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']],
             ['4. Other (please specify)', ['3.C.4']],
             ['Non-specified', ['3.C.4.a']],  # EST
             ['Other', ['3.C.4.a']],  # DEU
             ['other', ['3.C.4.a']],  # LVA
             ['Other cultivation', ['3.C.4.a']],  # CZE
-            ['Upland rice(4)', ['\IGNORE']],
-            ['Total(4)', ['\IGNORE']],
+            ['Upland rice(4)', ['\\IGNORE']],
+            ['Total(4)', ['\\IGNORE']],
         ],
         "entity_mapping": {
             'EMISSIONS CH4': 'CH4',
@@ -2267,7 +2268,7 @@ CRF2021 = {
             ['Sludge spreading', ['5.E.7']],  # ESP
             ['Accidental combustion', ['5.E.3']],  # ESP
             ['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']],
             ['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']],

+ 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
 specific items in categories 2, 3.H-G, 4
 
@@ -39,6 +39,7 @@ TODO:
 """
 
 import numpy as np
+
 from .util import unit_info
 
 CRF2022 = {
@@ -117,7 +118,7 @@ CRF2022 = {
             ['1. Transport of CO2', ['1.C.1']],
             ['2. Injection and storage', ['1.C.2']],
             ['3. Other', ['1.C.3']],
-            ['Memo items: (1)', ['\IGNORE']],
+            ['Memo items: (1)', ['\\IGNORE']],
             ['International bunkers', ['M.Memo.Int']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['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', 'Total'], 2],
             # 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
             ['Other non-specified', ['1.A.2.g.viii.1', 'Total'], 3],
             ['Liquid Fuels', ['1.A.2.g.viii.1', 'Liquid'], 4],
@@ -501,7 +502,7 @@ CRF2022 = {
             ['Peat', ['1.A.2.g.viii.1', 'Peat'], 4],
             ['Biomass', ['1.A.2.g.viii.1', 'Biomass'], 4],
             # DKE
-            ['Textile', ['\IGNORE', '\IGNORE'], 3],  # (empty)
+            ['Textile', ['\\IGNORE', '\\IGNORE'], 3],  # (empty)
             # DNK, DNM, FIN, DKE
             ['Other manufacturing industries', ['1.A.2.g.viii.3', 'Total'], 3],
             ['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],
             ['Liquid Fuels', ['1.A.5.b.iv', 'Liquid'], 3],
             # 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": {
             'EMISSIONS CH4': "CH4",
@@ -1554,7 +1555,7 @@ CRF2022 = {
             ['a. Injection', ['1.C.2.a']],
             ['b. Storage', ['1.C.2.b']],
             ['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 of imports for storage', ['M.Info.A.TAIS']],
             ['Total A', ['M.Info.A']],
@@ -1562,7 +1563,7 @@ CRF2022 = {
             ['Total amount of CO2 injected at storage sites', ['M.Info.B.TAI']],
             ['Total leakage from transport, injection and storage', ['M.Info.B.TLTIS']],
             ['Total B', ['M.Info.B']],
-            ['Difference (A-B)(6)', ['\IGNORE']],
+            ['Difference (A-B)(6)', ['\\IGNORE']],
         ],
         "entity_mapping": {
             'EMISSIONS CO2(2)': 'CO2',
@@ -1821,61 +1822,61 @@ CRF2022 = {
             # A. Enteric fermentation
             ['A. Enteric fermentation', ['3.A'], 2],
             ['1. Cattle(1)', ['3.A.1'], 3],
-            ['Option A:', ['\IGNORE'], 4],
+            ['Option A:', ['\\IGNORE'], 4],
             ['Dairy cattle', ['3.A.1.Aa'], 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],
             ['Other mature cattle', ['3.A.1.Bb'], 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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
             ['2. Sheep', ['3.A.2'], 3],
             ['3. Swine', ['3.A.3'], 3],
@@ -1896,60 +1897,60 @@ CRF2022 = {
             # Manure Management
             ['B. Manure management', ['3.B'], 2],
             ['1. Cattle(1)', ['3.B.1'], 3],
-            ['Option A:', ['\IGNORE'], 4],
+            ['Option A:', ['\\IGNORE'], 4],
             ['Dairy cattle', ['3.B.1.Aa'], 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],
             ['Other mature cattle', ['3.B.1.Bb'], 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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
             ['2. Sheep', ['3.B.2'], 3],
             ['3. Swine', ['3.B.3'], 3],
@@ -2040,15 +2041,15 @@ CRF2022 = {
             ['Flood prone', ['3.C.2.a']],
             ['Drought prone', ['3.C.2.b']],
             ['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']],
             ['4. Other (please specify)', ['3.C.4']],
             ['Non-specified', ['3.C.4.a']],  # EST
             ['Other', ['3.C.4.a']],  # DEU
             ['other', ['3.C.4.a']],  # LVA
             ['Other cultivation', ['3.C.4.a']],  # CZE
-            ['Upland rice(4)', ['\IGNORE']],
-            ['Total(4)', ['\IGNORE']],
+            ['Upland rice(4)', ['\\IGNORE']],
+            ['Total(4)', ['\\IGNORE']],
         ],
         "entity_mapping": {
             'EMISSIONS CH4': 'CH4',
@@ -2286,7 +2287,7 @@ CRF2022 = {
             ['Other waste', ['5.E.5']],  # CZE
             ['5.E.1 Industrial Wastewater', ['5.E.8']],  # CAN, 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']],
             ['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']],
@@ -2641,7 +2642,7 @@ CRF2022 = {
             "unit_info": unit_info["summary"],
         },
         "sector_mapping": [
-            ['Memo items:(7)', ['\IGNORE']],
+            ['Memo items:(7)', ['\\IGNORE']],
             ['International bunkers', ['M.Memo.Int']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['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
 specific items in categories 2, 3.H-G, 4
 
@@ -40,6 +40,7 @@ TODO:
 """
 
 import numpy as np
+
 from .util import unit_info
 
 CRF2023_AUS = {
@@ -104,7 +105,7 @@ CRF2023_AUS = {
             ["1.C.1. Transport of CO2", ["1.C.1"]],
             ["1.C.2. Injection and storage", ["1.C.2"]],
             ["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.a. Aviation", ["M.Memo.Int.Avi"]],
             ["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],
             ["Peat (8)", ["1.A.1.a", "Peat"], 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", "Total"], 3],
             ["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],
             ["Peat (8)", ["1.A.1.c", "Peat"], 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", "Total"], 3],
             ["Liquid fuels", ["1.A.1.c.i", "Liquid"], 4],
@@ -331,7 +332,7 @@ CRF2023_AUS = {
             ["Biomass (3)", ["1.A.2.f", "Biomass"], 2],
             # g. other
             ["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", "Total"], 2],
             ["Liquid fuels", ["1.A.2.g.i", "Liquid"], 3],
@@ -398,7 +399,7 @@ CRF2023_AUS = {
             ["Diesel oil", ["1.A.2.g.vii", "DieselOil"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.2.g.vii", "LPG"], 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],
             ["Other fossil fuels (7)", ["1.A.2.g.vii", "OtherFF"], 3],
             ["Biomass (3)", ["1.A.2.g.vii", "Biomass"], 3],
@@ -454,7 +455,7 @@ CRF2023_AUS = {
             ["Diesel oil", ["1.A.3.b", "DieselOil"], 2],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b", "LPG"], 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],
             ["Biomass (3)", ["1.A.3.b", "Biomass"], 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],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.i", "LPG"], 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],
             ["Biomass (3)", ["1.A.3.b.i", "Biomass"], 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],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.ii", "LPG"], 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],
             ["Biomass (3)", ["1.A.3.b.ii", "Biomass"], 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],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.iii", "LPG"], 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],
             ["Biomass (3)", ["1.A.3.b.iii", "Biomass"], 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],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.iv", "LPG"], 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],
             ["Biomass (3)", ["1.A.3.b.iv", "Biomass"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.3.b.iv", "OtherFF"], 3],
             ["Lubricants", ["1.A.3.b.iv", "OFFLubricants"], 4],
             # v. Other
             ["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],
             ["Diesel oil", ["1.A.3.b.v", "DieselOil"], 4],
             ["Liquefied petroleum gases (LPG)", ["1.A.3.b.v", "LPG"], 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],
             ["Biomass (3)", ["1.A.3.b.v", "Biomass"], 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],
             ["Gasoline", ["1.A.3.d", "Gasoline"], 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],
             ["Biomass (3)", ["1.A.3.d", "Biomass"], 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],
             ["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],
-            ["NA", ["\IGNORE", "\IGNORE"], 5],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 5],
             ["Solid fuels", ["1.A.3.e.ii.1", "Solid"], 4],
             ["Gaseous fuels (6)", ["1.A.3.e.ii.1", "Gaseous"], 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],
             ["Peat (8)", ["1.A.4.a", "Peat"], 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", "Total"], 2],
             ["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],
             ["Peat (8)", ["1.A.4.b", "Peat"], 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", "Total"], 2],
             ["Liquid fuels", ["1.A.4.b.i", "Liquid"], 3],
@@ -680,22 +681,22 @@ CRF2023_AUS = {
             ["Diesel oil", ["1.A.4.c.ii", "DieselOil"], 3],
             ["Liquefied petroleum gases (LPG)", ["1.A.4.c.ii", "LPG"], 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],
             ["Biomass (3)", ["1.A.4.c.ii", "Biomass"], 3],
             ["Other fossil fuels (please specify)(7)", ["1.A.4.c.ii", "OtherFF"], 3],
-            ["NA", ["\IGNORE", "\IGNORE"], 4],
+            ["NA", ["\\IGNORE", "\\IGNORE"], 4],
             # iii. Fishing
             ["1.A.4.c.iii. Fishing", ["1.A.4.c.iii", "Total"], 2],
             ["Residual fuel oil", ["1.A.4.c.iii", "ResFuelOil"], 3],
             ["Gas/diesel oil", ["1.A.4.c.iii", "GasDieselOil"], 3],
             ["Gasoline", ["1.A.4.c.iii", "Gasoline"], 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],
             ["Biomass(3)", ["1.A.4.c.iii", "Biomass"], 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)(15)", ["1.A.5", "Total"], 0],
             ["Liquid fuels", ["1.A.5", "Liquid"], 1],
@@ -706,7 +707,7 @@ CRF2023_AUS = {
             ["Biomass (3)", ["1.A.5", "Biomass"], 1],
             # a. Stationary (please specify)
             ["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],
             ["Solid fuels", ["1.A.5.a", "Solid"], 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],
             ["Biomass(3)", ["1.A.5.b.xii", "Biomass"], 3],
             # Information Item
-            ["Information item: (16)", ["\IGNORE", "\IGNORE"], 0],
+            ["Information item: (16)", ["\\IGNORE", "\\IGNORE"], 0],
             [
                 "Waste incineration with energy recovery included as:",
-                ["\IGNORE", "\IGNORE"],
+                ["\\IGNORE", "\\IGNORE"],
                 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": {
             "EMISSIONS CH4": "CH4",
@@ -766,22 +767,22 @@ CRF2023_AUS = {
                 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.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.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],
-            ["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.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.iv. Gas to liquids", ["1.B.1.b.iv"], 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],
-            ["NA", ["\IGNORE"], 1],
+            ["NA", ["\\IGNORE"], 1],
         ],
         "entity_mapping": {
             "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.v. Distribution of oil products", ["1.B.2.a.5"], 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.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.i. Exploration", ["1.B.2.b.1"], 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.v. Distribution", ["1.B.2.b.5"], 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.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],
@@ -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.3. Combined", ["1.B.2.c-fla.iii"], 2],
             ["1.B.2.d. Other (please specify) (10)", ["1.B.2.d"], 0],
-            ["NA", ["\IGNORE"], 1],
+            ["NA", ["\\IGNORE"], 1],
         ],
         "entity_mapping": {
             "EMISSIONS CH4 (5)": "CH4",
@@ -882,13 +883,13 @@ CRF2023_AUS = {
             ["1.C.1.a. Pipelines", ["1.C.1.a"], 1],
             ["1.C.1.b. Ships", ["1.C.1.b"], 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.a. Injection", ["1.C.2.a"], 1],
             ["1.C.2.b. Storage", ["1.C.2.b"], 1],
             ["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 of imports for storage (7)", ["M.Info.A.TAIS"], 1],
             ["Total A", ["M.Info.A"], 1],
@@ -901,7 +902,7 @@ CRF2023_AUS = {
                 1,
             ],
             ["Total B", ["M.Info.B"], 1],
-            ["Difference (A-B)(6)", ["\IGNORE"], 1],
+            ["Difference (A-B)(6)", ["\\IGNORE"], 1],
         ],
         "entity_mapping": {
             "EMISSIONS CO2 (2)": "CO2",
@@ -1097,10 +1098,10 @@ CRF2023_AUS = {
             ["3. Total agriculture", ["3"], 0],
             # A. Enteric fermentation
             ["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.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],
             # Other livestock
             ["3.A.2. Sheep", ["3.A.2"], 2],
@@ -1109,10 +1110,10 @@ CRF2023_AUS = {
             # Manure Management
             ["3.B. Manure management", ["3.B"], 1],
             ["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.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.2. Sheep", ["3.B.2"], 2],
             ["3.B.3. Swine", ["3.B.3"], 2],
@@ -1140,7 +1141,7 @@ CRF2023_AUS = {
             ["3.H. Urea application", ["3.H"], 1],
             ["3.I. Other carbon-containing fertilizers", ["3.I"], 1],
             ["3.J. Other (please specify)", ["3.J"], 1],
-            ["NA", ["\IGNORE"], 2],
+            ["NA", ["\\IGNORE"], 2],
         ],
         "entity_mapping": {"Total GHG emissions (1)": "KYOTOGHG (AR4GWP100)"},
         "coords_defaults": {
@@ -1166,27 +1167,27 @@ CRF2023_AUS = {
         },
         "sector_mapping": [
             ["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.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],
             ["Dairy Cattle", ["3.A.1.C-AUS-a"], 4],
             ["Beef Cattle - Pasture", ["3.A.1.C-AUS-b"], 4],
             ["Beef Cattle - Feedlot", ["3.A.1.C-AUS-c"], 4],
             ["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.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],
-            ["Drop down list:", ["\IGNORE"], 1],
+            ["Drop down list:", ["\\IGNORE"], 1],
             ["3.A.4.a. Buffalo", ["3.A.4.a"], 2],
             ["3.A.4.b. Camels", ["3.A.4.b"], 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.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],
-            ["Alpacas", ["\IGNORE"], 4],
+            ["Alpacas", ["\\IGNORE"], 4],
         ],
         "entity_mapping": {"EMISSIONS CH4": "CH4"},
         "coords_defaults": {
@@ -1230,27 +1231,27 @@ CRF2023_AUS = {
         },
         "sector_mapping": [
             ["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.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],
             ["Dairy Cattle", ["3.B.1.C-AUS-a"], 4],
             ["Beef Cattle - Pasture", ["3.B.1.C-AUS-b"], 4],
             ["Beef Cattle - Feedlot", ["3.B.1.C-AUS-c"], 4],
             ["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.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],
-            ["Drop-down list:", ["\IGNORE"], 1],
+            ["Drop-down list:", ["\\IGNORE"], 1],
             ["3.B.4.a. Buffalo", ["3.B.4.a"], 2],
             ["3.B.4.b. Camels", ["3.B.4.b"], 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.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],
-            ["Alpacas", ["\IGNORE"], 4],
+            ["Alpacas", ["\\IGNORE"], 4],
         ],
         "entity_mapping": {
             "EMISSIONS CH4 producing potential (Bo) (2) (average) CH4": "CH4"
@@ -1330,27 +1331,27 @@ CRF2023_AUS = {
         },
         "sector_mapping": [
             ["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.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],
             ["Dairy Cattle", ["3.B.1.C-AUS-a"], 4],
             ["Beef Cattle - Pasture", ["3.B.1.C-AUS-b"], 4],
             ["Beef Cattle - Feedlot", ["3.B.1.C-AUS-c"], 4],
             ["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.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],
-            ["Drop-down list", ["\IGNORE"], 1],
+            ["Drop-down list", ["\\IGNORE"], 1],
             ["3.B.4.a. Buffalo", ["3.B.4.a"], 2],
             ["3.B.4.b. Camels", ["3.B.4.b"], 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.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],
-            ["Alpacas", ["\IGNORE"], 4],
+            ["Alpacas", ["\\IGNORE"], 4],
         ],
         "entity_mapping": {
             "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.b. Drought-prone", ["3.C.2.b"]],
             ["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.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": {
             "EMISSIONS CH4": "CH4",
@@ -1484,9 +1485,9 @@ CRF2023_AUS = {
         },
         "sector_mapping": [
             ["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],
-            ["NA", ["\IGNORE"], 1],
+            ["NA", ["\\IGNORE"], 1],
         ],
         "entity_mapping": {
             "EMISSIONS (2) CH4": "CH4",
@@ -1612,7 +1613,7 @@ CRF2023_AUS = {
             ["5.D.3. Other", ["5.D.3"]],
             ["5.E. Other (please specify)", ["5.E"]],
             ["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.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.E. Other (6)", ["5.E"]],
             ["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.a. Aviation", ["M.Memo.Int.Avi"]],
             ["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
 specific items in categories 2, 3.H-G, 4
 
@@ -40,6 +40,7 @@ TODO:
 """
 
 import numpy as np
+
 from .util import unit_info
 
 # 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']],
             ['2. Injection and storage', ['1.C.2']],
             ['3. Other', ['1.C.3']],
-            ['Memo items: (1)', ['\IGNORE']],
+            ['Memo items: (1)', ['\\IGNORE']],
             ['International bunkers', ['M.Memo.Int']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['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', 'Total'], 2],
             # 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
             ['Other non-specified', ['1.A.2.g.viii.1', 'Total'], 3],
             ['Liquid Fuels', ['1.A.2.g.viii.1', 'Liquid'], 4],
@@ -506,7 +507,7 @@ CRF2023 = {
             ['Peat', ['1.A.2.g.viii.1', 'Peat'], 4],
             ['Biomass', ['1.A.2.g.viii.1', 'Biomass'], 4],
             # DKE
-            ['Textile', ['\IGNORE', '\IGNORE'], 3],  # (empty)
+            ['Textile', ['\\IGNORE', '\\IGNORE'], 3],  # (empty)
             # DNK, DNM, FIN, DKE
             ['Other manufacturing industries', ['1.A.2.g.viii.3', 'Total'], 3],
             ['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],
             ['Liquid Fuels', ['1.A.5.b.iv', 'Liquid'], 3],
             # 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": {
             'EMISSIONS CH4': "CH4",
@@ -1570,7 +1571,7 @@ CRF2023 = {
             ['a. Injection', ['1.C.2.a']],
             ['b. Storage', ['1.C.2.b']],
             ['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 of imports for storage', ['M.Info.A.TAIS']],
             ['Total A', ['M.Info.A']],
@@ -1578,7 +1579,7 @@ CRF2023 = {
             ['Total amount of CO2 injected at storage sites', ['M.Info.B.TAI']],
             ['Total leakage from transport, injection and storage', ['M.Info.B.TLTIS']],
             ['Total B', ['M.Info.B']],
-            ['Difference (A-B)(6)', ['\IGNORE']],
+            ['Difference (A-B)(6)', ['\\IGNORE']],
         ],
         "entity_mapping": {
             'EMISSIONS CO2(2)': 'CO2',
@@ -1837,61 +1838,61 @@ CRF2023 = {
             # A. Enteric fermentation
             ['A. Enteric fermentation', ['3.A'], 2],
             ['1. Cattle(1)', ['3.A.1'], 3],
-            ['Option A:', ['\IGNORE'], 4],
+            ['Option A:', ['\\IGNORE'], 4],
             ['Dairy cattle', ['3.A.1.Aa'], 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],
             ['Other mature cattle', ['3.A.1.Bb'], 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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
             ['2. Sheep', ['3.A.2'], 3],
             ['3. Swine', ['3.A.3'], 3],
@@ -1912,60 +1913,60 @@ CRF2023 = {
             # Manure Management
             ['B. Manure management', ['3.B'], 2],
             ['1. Cattle(1)', ['3.B.1'], 3],
-            ['Option A:', ['\IGNORE'], 4],
+            ['Option A:', ['\\IGNORE'], 4],
             ['Dairy cattle', ['3.B.1.Aa'], 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],
             ['Other mature cattle', ['3.B.1.Bb'], 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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
-            ['\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
             ['2. Sheep', ['3.B.2'], 3],
             ['3. Swine', ['3.B.3'], 3],
@@ -2056,15 +2057,15 @@ CRF2023 = {
             ['Flood prone', ['3.C.2.a']],
             ['Drought prone', ['3.C.2.b']],
             ['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']],
             ['4. Other (please specify)', ['3.C.4']],
             ['Non-specified', ['3.C.4.a']],  # EST
             ['Other', ['3.C.4.a']],  # DEU
             ['other', ['3.C.4.a']],  # LVA
             ['Other cultivation', ['3.C.4.a']],  # CZE
-            ['Upland rice(4)', ['\IGNORE']],
-            ['Total(4)', ['\IGNORE']],
+            ['Upland rice(4)', ['\\IGNORE']],
+            ['Total(4)', ['\\IGNORE']],
         ],
         "entity_mapping": {
             'EMISSIONS CH4': 'CH4',
@@ -2304,7 +2305,7 @@ CRF2023 = {
             ['Other waste', ['5.E.5']],  # CZE
             ['5.E.1 Industrial Wastewater', ['5.E.8']],  # CAN, 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']],
             ['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']],
@@ -2663,7 +2664,7 @@ CRF2023 = {
             "unit_info": unit_info["summary"],
         },
         "sector_mapping": [
-            ['Memo items:(7)', ['\IGNORE']],
+            ['Memo items:(7)', ['\\IGNORE']],
             ['International bunkers', ['M.Memo.Int']],
             ['Aviation', ['M.Memo.Int.Avi']],
             ['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 = {
     "default": {
@@ -46,4 +46,4 @@ unit_info = {
         },
         "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
 """
 
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.UNFCCC_CRF_reader_prod import \
-    read_new_crf_for_year
 import argparse
 
+from unfccc_ghg_data.unfccc_crf_reader.unfccc_crf_reader_prod import read_new_crf_for_year
+
 parser = argparse.ArgumentParser()
 #parser.add_argument('--countries', help='List of country codes', default=None)
 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.
 """
 
-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
 
+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.add_argument('--countries', help='List of country codes', default=None)
 parser.add_argument('--submission_year', help='Submission round to read')
@@ -29,4 +30,4 @@ try:
         re_read=re_read
     )
 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
 """
 
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.UNFCCC_CRF_reader_prod import read_crf_for_country
 import argparse
 
+from unfccc_ghg_data.unfccc_crf_reader.unfccc_crf_reader_prod import read_crf_for_country
+
 parser = argparse.ArgumentParser()
 parser.add_argument('--country', help='Country name or code')
 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.
 """
 
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.UNFCCC_CRF_reader_prod import read_crf_for_country_datalad
 import argparse
 
+from unfccc_ghg_data.unfccc_crf_reader.unfccc_crf_reader_prod import read_crf_for_country_datalad
+
 parser = argparse.ArgumentParser()
 parser.add_argument('--country', help='Country name or code')
 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_date=submission_date,
     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
 """
 
-from UNFCCC_GHG_data.UNFCCC_CRF_reader.UNFCCC_CRF_reader_devel import read_year_to_test_specs
 import argparse
 
+from unfccc_ghg_data.unfccc_crf_reader.unfccc_crf_reader_devel import read_year_to_test_specs
+
 parser = argparse.ArgumentParser()
 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)

+ 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.
 """
 
-import re
-import os
 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 pandas as pd
 import primap2 as pm2
-from pathlib import Path
 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 .util import NoCRFFilesError
-from UNFCCC_GHG_data.helper import downloaded_data_path_UNFCCC
+
 
 ### reading functions
 def convert_crf_table_to_pm2if(
         df_table: pd.DataFrame,
         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:
     """
     Converts a given pandas long format crf table to PRIMAP2 interchange format
 
     Parameters
+    ----------
     __________
         df_table: pd.DataFrame
             Data to convert
@@ -60,12 +66,12 @@ def convert_crf_table_to_pm2if(
             are given as input the automatic values are overwritten.
 
     Returns
+    -------
     _______
         pd.DataFrame:
             Pandas DataFrame containing the data in PRIMAP2 interchange format
             Metadata is stored as attrs in the DataFrame
     """
-
     coords_cols = {
         "category": "category",
         "entity": "entity",
@@ -107,7 +113,7 @@ def convert_crf_table_to_pm2if(
 
     filter_remove = {
         "f1": {
-            "category": ["\IGNORE"],
+            "category": ["\\IGNORE"],
         }
     }
     if filter_remove_input is not None:
@@ -150,14 +156,14 @@ def convert_crf_table_to_pm2if(
 
 
 def read_crf_table(
-        country_codes: Union[str, List[str]],
+        country_codes: Union[str, list[str]],
         table: str,
         submission_year: int,
-        data_year: Optional[Union[int, List[int]]]=None,
+        data_year: Optional[Union[int, list[int]]]=None,
         date: Optional[str]=None,
         folder: Optional[str]=None,
         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
     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
 
     Parameters
+    ----------
     __________
 
     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
         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
 
     Returns
+    -------
     _______
         Tuple[pd.DataFrame, List[List], List[List]]:
         * 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:
             print(f"Found only {len(input_files)} input files for {country_codes}. "
                   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 = date_datetime - timedelta(days=1)
             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.")
                 input_files = input_files + more_input_files
             else:
-                print(f"Found no additional input files")
+                print("Found no additional input files")
 
     if input_files == []:
         raise NoCRFFilesError(f"No files found for {country_codes}, "
@@ -251,7 +259,7 @@ def read_crf_table(
     if len(country_codes) == 1:
         try:
             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]}")
         except:
             # no country specific specification, check for general specification
@@ -294,14 +302,15 @@ def read_crf_table(
 def read_crf_table_from_file(
         file: Path,
         table: str,
-        table_spec: Dict[str, Dict],
+        table_spec: dict[str, dict],
         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
     reading process as it reads the data from xls and performs the category mapping.
 
     Parameters
+    ----------
     __________
     file: Path
         file to read from
@@ -316,6 +325,7 @@ def read_crf_table_from_file(
         if true print some debug information like column headers
 
     Returns
+    -------
     _______
         Tuple[pd.DataFrame, List[List], List[List]]:
         * 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?
     """
+    # 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"]
     file_info = get_info_from_crf_filename(file.name)
@@ -366,7 +382,7 @@ def read_crf_table_from_file(
         last_row_nan = True
     else:
         last_row_nan = False
-    
+
 
     cols_to_drop = []
     # 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
     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
     if len(header) > 2:
@@ -451,7 +467,7 @@ def read_crf_table_from_file(
     # remove double spaces
     for col in cols_for_space_stripping:
         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
     # variables
@@ -571,20 +587,21 @@ def read_crf_table_from_file(
 
 
 def get_crf_files(
-        country_codes: Union[str, List[str]],
+        country_codes: Union[str, list[str]],
         submission_year: int,
-        data_year: Optional[Union[int, List[int]]] = None,
+        data_year: Optional[Union[int, list[int]]] = None,
         date: Optional[str] = None,
         folder: Optional[str] = None,
-) -> List[Path]:
+) -> list[Path]:
     """
     Finds all files according to given parameters
 
     Parameters
+    ----------
     __________
 
     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
         Year of the submission of the data
@@ -601,6 +618,7 @@ def get_crf_files(
         submissions_year and country_code variables
 
     Returns
+    -------
     _______
         List[Path]: list of Path objects for the files
     """
@@ -615,7 +633,7 @@ def get_crf_files(
         data_folder = downloaded_data_path_UNFCCC
         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)
 
         # use country default folders
@@ -625,8 +643,7 @@ def get_crf_files(
                 new_country_folders = folder_mapping[country_code]
                 if isinstance(new_country_folders, str):
                     # 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:
                     country_folders = country_folders + \
                                       [data_folder / folder / submission_folder
@@ -683,21 +700,23 @@ def get_crf_files(
 
 def get_info_from_crf_filename(
         filename: str,
-) -> Dict[str, Union[int, str]]:
+) -> dict[str, Union[int, str]]:
     """
     Parse given file name and return a dict with information
     on the contained data.
 
     Parameters
+    ----------
     __________
 
     filename: str
         The file to analyze (without path)
 
     Returns
+    -------
     _______
     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
         data_year: year in which the emissions took place
         date: date of the submission
@@ -724,22 +743,23 @@ def get_info_from_crf_filename(
 
 
 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,
         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
+    ----------
     __________
     files_to_filter: List[Path]
         List with pathlib.Path objects for the filenames to filter
 
     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)
         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(
-        file_info: Dict,
-        file_filter: Dict,
+        file_info: dict,
+        file_filter: dict,
 ) -> bool:
     """
     Check if a CRF file has given properties
 
     Parameters
+    ----------
     __________
     file_info: Dict
         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`
 
     Returns
+    -------
     _______
         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(
-        specification: List[List],
+        specification: list[list],
         table: str,
         country: Optional[str] = None,
 ) -> Tree:
@@ -831,6 +853,7 @@ def create_category_tree(
     correct categories to non-unique row headers.
 
     Parameters
+    ----------
     __________
 
     specification: List[List]
@@ -874,7 +897,7 @@ def create_category_tree(
                          for mapping in specification]
         # remove the categories for other countries
         specification = [mapping for mapping in specification
-                         if mapping[0] != "\REMOVE"]
+                         if mapping[0] != "\\REMOVE"]
 
     # build a tree from specification
     # when looping over the categories present in the table
@@ -922,31 +945,33 @@ def create_category_tree(
 
 
 def filter_category(
-        mapping: List,
+        mapping: list,
         country: str,
-) -> List[str]:
+) -> list[str]:
     """
     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 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.
 
     Parameters
+    ----------
     __________
         mapping: List
             mapping for a single category
         country: str
-            iso 3-letter UNFCCC_GHG_data of the country
+            iso 3-letter code of the country
 
     Returns
+    -------
     _______
         List: updated mapping
 
     """
-    string_exclude = f"\C!-"
+    string_exclude = "\\C!-"
     regex_exclude = 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}\\"
     new_mapping = mapping.copy()
     if mapping[0].startswith(string_exclude):
@@ -954,14 +979,14 @@ def filter_category(
         countries_ex = re_result.group(1)
         countries_ex = countries_ex.split("-")
         if country in countries_ex:
-            new_mapping[0] = "\REMOVE"
+            new_mapping[0] = "\\REMOVE"
         else:
             re_result = re.search(regex_exclude_full, mapping[0])
             new_mapping[0] = mapping[0][len(re_result.group(1)) + 1:]
     elif mapping[0].startswith(string_country):
         new_mapping[0] = mapping[0][len(string_country) + 1:]
     elif re.match(regex_countries, mapping[0]):
-        new_mapping[0] = "\REMOVE"
+        new_mapping[0] = "\\REMOVE"
 
     return new_mapping
 
@@ -974,19 +999,20 @@ def get_latest_date_for_country(
     Find the latest submission date for a country
 
     Parameters
+    ----------
     __________
     country: str
-        3-letter country UNFCCC_GHG_data
+        3-letter country code
 
     submission_year: int
         Year of the submission to find the l;atest date for
 
     Returns
+    -------
     _______
         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)
 
     if country_code in folder_mapping:
@@ -1014,12 +1040,13 @@ def get_latest_date_for_country(
 
 def get_submission_dates(
         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
 
     Parameters
+    ----------
     __________
     folder: Path
         Folder to analyze
@@ -1028,14 +1055,14 @@ def get_submission_dates(
         Dict with possible fields "party", "submission_year", "data_year"
 
     Returns
+    -------
     _______
         List[str]:
             List of dates as str
     """
-
     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():
         files = filter_filenames(folder.glob("*.xlsx"), **file_filter)
@@ -1050,12 +1077,13 @@ def get_submission_dates(
 
 def get_submission_parties(
         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
 
     Parameters
+    ----------
     __________
     folder: Path
         Folder to analyze
@@ -1064,14 +1092,14 @@ def get_submission_parties(
         Dict with possible fields "submission_year", "data_year", "date"
 
     Returns
+    -------
     _______
         List[str]:
             List of parties as str
     """
-
     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():
         files = filter_filenames(list(folder.glob("*.xlsx")), **file_filter)
@@ -1085,7 +1113,7 @@ def get_submission_parties(
 
 
 def find_latest_date(
-        dates: List[str],
+        dates: list[str],
         date_format: str='%d%m%Y',
 )-> str:
     """
@@ -1093,21 +1121,22 @@ def find_latest_date(
     ddmmyyyy
 
     Parameters
+    ----------
     __________
     dates: List[str]
         List of dates
 
     Returns
+    -------
     _______
         str: latest date
     """
-
     if len(dates) > 0:
         dates_datetime = [[date, datetime.strptime(date, date_format)] for date in
                           dates]
         dates_datetime = sorted(dates_datetime, key=itemgetter(1))
     else:
-        raise ValueError(f"Passed list of dates is empty")
+        raise ValueError("Passed list of dates is empty")
 
     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
 """
 
+from datetime import date
+from pathlib import Path
+from typing import Optional
+
 import pandas as pd
-import xarray as xr
 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 .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(
         submission_year: int,
@@ -35,6 +37,9 @@ def read_year_to_test_specs(
     if data_year is None:
         data_year=2000
 
+    if country_code=="None":
+        country_code=None
+
     unknown_categories = []
     last_row_info = []
     ds_all = None
@@ -43,43 +48,6 @@ def read_year_to_test_specs(
         print("Reading only tables to test.")
     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:
         countries_to_read = [country_code]
     else:
@@ -87,8 +55,42 @@ def read_year_to_test_specs(
     for country_code in countries_to_read:
         # get country name
         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
+           # 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:
             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:
             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(
                     country_code, table, submission_year, date=submission_date,
                     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
                     # them
                     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.
                         # If we have CO2 and removals but not emissions, CO2 already has
                         # removals subtracted and we do nothing here
@@ -146,8 +147,7 @@ def read_year_to_test_specs(
                         ds_table_pm2["CO2"].attrs["entity"] = "CO2"
 
                     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.
                         # If we have CH4 and removals but not emissions, CH4 already has
                         # removals subtracted and we do nothing here
@@ -227,13 +227,14 @@ def read_year_to_test_specs(
 
 
 def save_unknown_categories_info(
-        unknown_categories: List[List],
+        unknown_categories: list[list],
         file: Path,
 ) -> None:
     """
     Save information on unknown categories to a csv file.
 
     Parameters
+    ----------
     __________
 
     unknown_categories: List[List]
@@ -277,7 +278,7 @@ def save_unknown_categories_info(
 
 
 def save_last_row_info(
-        last_row_info: List[List],
+        last_row_info: list[list],
         file: Path,
     ) -> None:
     """
@@ -287,6 +288,7 @@ def save_last_row_info(
     given in the specification and thus we might not read the full table.
 
     Parameters
+    ----------
     __________
 
     last_row_info: List[List]
@@ -325,4 +327,4 @@ def save_last_row_info(
     if not file.parents[0].exists():
         file.parents[0].mkdir()
     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 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
 #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
 
 # 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
 # wrappers around this function to read for a whole country or for test reading where we also
 # write files with missing sectors etc.
@@ -67,10 +75,11 @@ def read_crf_for_country(
 
 
     Parameters
+    ----------
     __________
 
     country_codes: str
-        ISO 3-letter country UNFCCC_GHG_data
+        ISO 3-letter country code
 
     submission_year: int
         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
 
     Returns
+    -------
     _______
         return value is a Pandas DataFrame with the read data in PRIMAP2 format
     """
-
     # get country name
     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
             # them
             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.
                 # If we have CO2 and removals but not emissions, CO2 already has
                 # removals subtracted and we do nothing here
@@ -172,11 +180,10 @@ def read_crf_for_country(
                 ds_table_pm2["CO2"].attrs["entity"] = "CO2"
 
             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.
                 # 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",
                                                 "CH4 removals"]].pr.sum(
                     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
 
     Parameters
+    ----------
     __________
 
     country_codes: str
-        ISO 3-letter country UNFCCC_GHG_data
+        ISO 3-letter country code
 
     submission_year: int
         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
 
     """
-
     # get all the info for the country
     country_info = get_input_and_output_files_for_country(
         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("#"*80)
     print("")
-    print(f"Using the UNFCCC_CRF_reader")
+    print("Using the unfccc_crf_reader")
     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} "\
           f"--submission_year={submission_year} --submission_date={submission_date}"
     if re_read:
-        cmd = cmd + f" --re_read"
+        cmd = cmd + " --re_read"
     datalad.api.run(
         cmd=cmd,
         dataset=root_path,
@@ -283,7 +290,7 @@ def read_crf_for_country_datalad(
 
 def read_new_crf_for_year(
         submission_year: int,
-        countries: Optional[List[str]]=None,
+        countries: Optional[list[str]]=None,
         re_read: Optional[bool]=False,
 ) -> dict:
     """
@@ -302,6 +309,7 @@ def read_new_crf_for_year(
     read from different tables
 
     Parameters
+    ----------
     __________
 
     submission_year: int
@@ -317,11 +325,11 @@ def read_new_crf_for_year(
     TODO: write log with failed countries and what has been read
 
     Returns
+    -------
     _______
         list[str]: list with country codes for which the data has been read
 
     """
-
     if countries is None:
         countries = all_crf_countries
 
@@ -356,7 +364,7 @@ def read_new_crf_for_year(
 
 def read_new_crf_for_year_datalad(
         submission_year: int,
-        countries: Optional[List[str]] = None,
+        countries: Optional[list[str]] = None,
         re_read: Optional[bool] = False,
 ) -> None:
     """
@@ -364,6 +372,7 @@ def read_new_crf_for_year_datalad(
     and output files and using datalad run to trigger the data reading
 
     Parameters
+    ----------
     __________
 
     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 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:
-        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
     print("#" * 80)
     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
             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} "\
     #      f"--submission_year={submission_year}"
@@ -443,11 +451,10 @@ def get_input_and_output_files_for_country(
         submission_year: int,
         submission_date: Optional[str]=None,
         verbose: Optional[bool]=True,
-) -> Dict[str, Union[List, str]]:
+) -> dict[str, Union[list, str]]:
     """
     Get input and output files for a given country
     """
-
     country_info = {}
 
     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}")
     if submission_date is None:
         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)
     else:
         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"repository?")
     elif verbose:
-        print(f"Found the following input_files:")
+        print("Found the following input_files:")
         for file in input_files:
             print(file.name)
         print("")
@@ -504,7 +511,7 @@ def get_input_and_output_files_for_country(
                                     f"_{submission_date}.{suffix}" for suffix
                     in ['yaml', 'csv', 'nc']]
     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:
             print(file)
         print("")
@@ -551,4 +558,4 @@ def submission_has_been_read(
             print(f"No read data available for {country_code}, "
                   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):
-    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
-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.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.
 """
 
-from UNFCCC_GHG_data.UNFCCC_DI_reader import \
-    process_DI_for_country_datalad
 import argparse
 
+from unfccc_ghg_data.UNFCCC_DI_reader import process_DI_for_country_datalad
+
 parser = argparse.ArgumentParser()
 parser.add_argument('--country', help='Country name or code')
 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":
     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
-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.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.
 """
 
-from UNFCCC_GHG_data.UNFCCC_DI_reader import \
-    process_DI_for_country_group_datalad
 import argparse
 
+from unfccc_ghg_data.UNFCCC_DI_reader import process_DI_for_country_group_datalad
+
 parser = argparse.ArgumentParser()
 parser.add_argument('--annexI', help='read for AnnexI countries (default is for '
                                      '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
-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.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.
 """
 
-from UNFCCC_GHG_data.UNFCCC_DI_reader import \
-    read_DI_for_country_datalad
 import argparse
 
+from unfccc_ghg_data.UNFCCC_DI_reader import read_DI_for_country_datalad
+
 parser = argparse.ArgumentParser()
 parser.add_argument('--country', help='Country name or code')
 
 args = parser.parse_args()
 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
-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.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.
 """
 
-from UNFCCC_GHG_data.UNFCCC_DI_reader import \
-    read_DI_for_country_group_datalad
 import argparse
 
+from unfccc_ghg_data.UNFCCC_DI_reader import read_DI_for_country_group_datalad
+
 parser = argparse.ArgumentParser()
 parser.add_argument('--annexI', help='read for AnnexI countries (default is for '
                                      '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 xarray as xr
-
-from datetime import date
-from typing import Optional, Dict
+import itertools
 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(
         country_code: str,
-        category_groups: Optional[Dict]=None,
+        category_groups: Optional[dict]=None,
         read_subsectors: bool=False,
         save_data: Optional[bool]=True,
         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
     interchange format
     """
-
     # read the data
     if use_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(
         country_code: str,
-        category_groups: Optional[Dict]=None,
+        category_groups: Optional[dict]=None,
         read_subsectors: bool=False,
         debug: Optional[bool]=False,
 )->pd.DataFrame:
@@ -193,7 +191,7 @@ def read_UNFCCC_DI_for_country_df(
                     node_codes = node_codes + (
                         [sub_node.identifier for sub_node in sub_nodes])
                 else:
-                    node_codes = node_codes + [node.identifier]
+                    node_codes = [*node_codes, node.identifier]
             if debug:
                 print(f"Found node_codes: {node_codes}")
             # 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(
         country_code: str,
-        category_groups: Optional[Dict]=None,
+        category_groups: Optional[dict]=None,
         read_subsectors: bool=False,
         debug: Optional[bool]=False,
 )->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
     to overwrite certain parameters (makes sense if function is used in a broader context
     """
-
     print("Convert data to PRIMAP2 interchange format")
 
     # 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
     if date_str == "country":
-        pm2if_specifications["coords_defaults"]["scenario"] = f"DIrolling"
+        pm2if_specifications["coords_defaults"]["scenario"] = "DIrolling"
     elif date_str is None:
         today = date.today()
         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"]
 
     # 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,
                                                               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
     names are unknown beforehand datalad run uses explicit=false
     '''
-
     today = date.today()
     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 typing import Union, Optional
+from typing import Optional, Union
+
 import datalad.api
 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
 
+
 ## datalad and pydoit interface functions
 def read_DI_for_country_datalad(
         country: str,
@@ -16,13 +19,13 @@ def read_DI_for_country_datalad(
     and output files and using datalad run to trigger the data reading
 
     Parameters
+    ----------
     __________
 
     country: str
         country name or ISO 3-letter country code
 
     """
-
     # get date to determine output filename
     today = date.today()
     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("#"*80)
     print("")
-    print(f"Using the UNFCCC_DI_reader")
+    print("Using the unfccc_di_reader")
     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)
 
     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
 
     Parameters
+    ----------
     __________
 
     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
         no date is given the last data read will be processed.
     """
-
     # get all the info for the country
     country_info = get_input_and_output_files_for_country_DI(country, date_str,
                                                              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("#"*80)
     print("")
-    print(f"Using the UNFCCC_DI_reader")
+    print("Using the unfccc_di_reader")
     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)
 
     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
 
     Parameters
+    ----------
     __________
 
     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
         no date is given the last data read will be processed.
     """
-
     if annexI:
         country_group = "AnnexI"
     else:
@@ -134,15 +137,15 @@ def read_DI_for_country_group_datalad(
     print(f"Attempting to read DI data for {country_group}.")
     print("#"*80)
     print("")
-    print(f"Using the UNFCCC_DI_reader")
+    print("Using the unfccc_di_reader")
     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)
 
     cmd = f"./venv/bin/python3 {script.as_posix()} "
     if annexI:
-        cmd = cmd + f" --annexI"
+        cmd = cmd + " --annexI"
 
     try:
         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
 
     Parameters
+    ----------
     __________
 
     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
         no date is given the last data read will be processed.
     """
-
     if annexI:
         country_group = "AnnexI"
     else:
@@ -188,15 +191,15 @@ def process_DI_for_country_group_datalad(
     print(f"Attempting to process DI data for {country_group}.")
     print("#"*80)
     print("")
-    print(f"Using the UNFCCC_DI_reader")
+    print("Using the unfccc_di_reader")
     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)
 
     cmd = f"./venv/bin/python3 {script.as_posix()} "
     if annexI:
-        cmd = cmd + f" --annexI"
+        cmd = cmd + " --annexI"
     if date_str is not None:
         cmd = cmd + f" --date_str={date_str}"
     else:
@@ -216,4 +219,4 @@ def process_DI_for_country_group_datalad(
         print(f"IncompleteResultsError occurred when running {cmd}: {IRE}")
     except Exception as ex:
         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 re
-from typing import Optional, Dict, List, Union
-from pathlib import Path
 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
@@ -21,7 +27,6 @@ def determine_filename(
     """
     Determine the filename for a dataset from given country code and date string.
 
-
     Parameters
     ----------
     country_code: str
@@ -33,13 +38,13 @@ def determine_filename(
     hash: str
 
     Returns
+    -------
     _______
         pathlib Path object for the file name (without suffix)
 
     """
-
     # 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)
 
     if country_code in folder_mapping:
@@ -98,10 +103,10 @@ def determine_dataset_filename(
     hash: str
 
     Returns
+    -------
     _______
         pathlib Path object for the file name (without suffix)
     """
-
     # get the country folder
     if 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,
         raw: bool,
         verbose: Optional[bool]=True,
-) -> Dict[str, Union[List, str]]:
+) -> dict[str, Union[list, str]]:
     """
     Get input and output files for a given country
     """
-
     country_info = {}
 
     if country in custom_country_mapping:
@@ -175,7 +179,7 @@ def get_input_and_output_files_for_country_DI(
                         suffix in ['yaml', 'csv', 'nc']]
 
         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:
                 print(file)
             print("")
@@ -186,7 +190,7 @@ def get_input_and_output_files_for_country_DI(
                     suffix in ['yaml', 'csv', 'nc']]
 
     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:
             print(file)
         print("")
@@ -202,19 +206,18 @@ def get_input_and_output_files_for_country_DI(
 def get_present_hashes_for_country_DI(
         country_code: str,
         raw: bool,
-) -> List:
+) -> list:
     '''
     Get the hashes of outputs
     '''
-
     regex_hash = r"_([a-f0-9]*)_"
     if raw:
-        regex_hash = regex_hash + "raw_hash\.nc"
+        regex_hash = regex_hash + "raw_hash\\.nc"
     else:
-        regex_hash = regex_hash + "hash\.nc"
+        regex_hash = regex_hash + "hash\\.nc"
 
     # 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)
 
     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
     '''
-
     if raw:
         regex = f"{country_code}_DI_{regex_date}" + r"_raw\.nc"
     else:
@@ -260,7 +262,7 @@ def find_latest_DI_data(
         #regex = f"{country_code}_DI_{regex_date}" + r"\.nc"
 
     # 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)
 
     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
 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(
         data_pm2: xr.Dataset,
@@ -14,7 +15,6 @@ def save_DI_country_data(
     save primap2 and IF data to country folder
     can be used for raw and processed data but for a single country only
     '''
-
     # preparations
     data_if = data_pm2.pr.to_interchange_format()
 
@@ -88,7 +88,6 @@ def save_DI_dataset(
     save primap2 and IF data to dataset folder
     can be used for raw and processed data but not to save to country folders
     '''
-
     # preparations
     data_if = data_pm2.pr.to_interchange_format()
     if annexI:
@@ -149,4 +148,4 @@ def save_DI_dataset(
         file_hash = filename_hash.name + suffix
         if file_date.exists():
             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
 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(
@@ -25,7 +20,6 @@ def process_and_save_UNFCCC_DI_for_country(
     """
     process data and save them to disk using default parameters
     """
-
     # get latest dataset if no date given
     if date_str is None:
         # get the latest date
@@ -82,19 +76,19 @@ def process_and_save_UNFCCC_DI_for_country(
 
 def process_UNFCCC_DI_for_country(
         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:
     """
-        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
     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)
 
     Parameters
+    ----------
     __________
 
     annexI: bool (default False)
@@ -205,7 +200,7 @@ def process_UNFCCC_DI_for_country_group(
             data_country = data_country.assign_coords({"scenario (Access_Date)": [
                 f"DI{date_str_today}"]})
             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"]})
 
             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
-from UNFCCC_GHG_data.helper import code_path
+
+from unfccc_ghg_data.helper import code_path
 
 #reader = unfccc_di_api.UNFCCCApiReader()
 #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"])
 #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_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__ = [
     "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 pandas as pd
-import requests
+import os
 import shutil
 import time
-import os
 import zipfile
 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.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):
     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:
     url = (
@@ -132,7 +133,7 @@ for idx, submission in items.iterrows():
         if Path(local_filename).stat().st_size in error_file_sizes:
             # found the error page. delete file
             os.remove(local_filename)
-    
+
     # 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()):
         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
             if i == 1 or i == 5:
                 driver = Firefox(options=options)
-    
+
                 # visit the main data page once to create cookies
                 driver.get(url)
                 time.sleep(20)
@@ -154,15 +155,15 @@ for idx, submission in items.iterrows():
             r = requests.get(url, stream=True, cookies=cookies)
             with open(str(local_filename), 'wb') as f:
                 shutil.copyfileobj(r.raw, f)
-            
+
             # check file size. if 210 or 212 bytes it's the error page
             if Path(local_filename).stat().st_size in error_file_sizes:
                 # found the error page. delete file
                 os.remove(local_filename)
-            
+
             # sleep a bit to avoid running into captchas
             time.sleep(randrange(5, 15))
-            
+
         if local_filename.exists():
             new_downloaded.append(submission)
             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 re
+import shutil
+import time
 from datetime import date
-from random import randrange
-from UNFCCC_GHG_data.helper import downloaded_data_path_UNFCCC
 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
@@ -73,7 +75,7 @@ for idx, submission in submissions.iterrows():
         if Path(local_filename_underscore).stat().st_size in error_file_sizes:
             # found the error page. delete file
             os.remove(local_filename_underscore)
-    
+
     # now we have to remove error pages, so a present file should not be overwritten
     if (not local_filename_underscore.exists()) \
             and (not local_filename_underscore.is_symlink()):
@@ -83,15 +85,15 @@ for idx, submission in submissions.iterrows():
             r = requests.get(url, stream=True)
             with open(str(local_filename_underscore), 'wb') as f:
                 shutil.copyfileobj(r.raw, f)
-            
+
             # 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:
                 # found the error page. delete file
                 os.remove(local_filename_underscore)
-            
+
             # sleep a bit to avoid running into captchas
             time.sleep(randrange(5, 15))
-            
+
         if local_filename_underscore.exists():
             new_downloaded.append(submission)
             print("Download => downloaded_data/UNFCCC/" + country + "/" +
@@ -105,4 +107,4 @@ for idx, submission in submissions.iterrows():
 
 
 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 pandas as pd
-import requests
+import os
 import shutil
 import time
-import os
 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.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:
             # found the error page. delete file
             os.remove(local_filename)
-    
+
     # 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()):
         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
             if i == 1 or i == 5:
                 driver = Firefox(options=options)
-    
+
                 # visit the main data page once to create cookies
                 driver.get(url)
                 time.sleep(20)
@@ -116,15 +118,15 @@ for idx, submission in submissions.iterrows():
             r = requests.get(url, stream=True, cookies=cookies)
             with open(str(local_filename), 'wb') as f:
                 shutil.copyfileobj(r.raw, f)
-            
+
             # check file size. if 210 or 212 bytes it's the error page
             if Path(local_filename).stat().st_size in error_file_sizes:
                 # found the error page. delete file
                 os.remove(local_filename)
-            
+
             # sleep a bit to avoid running into captchas
             time.sleep(randrange(5, 15))
-            
+
         if local_filename.exists():
             new_downloaded.append(submission)
             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 random import randrange
 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
 

+ 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 time
-import pandas as pd
 import re
-
+import time
 from pathlib import Path
+from random import randrange
+
+import pandas as pd
 from bs4 import BeautifulSoup
 from selenium.webdriver import Firefox
 from selenium.webdriver.firefox.options import Options
-from random import randrange
 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
 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)
 """
 

+ 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 time
-import pandas as pd
 import re
-
+import time
 from pathlib import Path
+from random import randrange
+
+import pandas as pd
 from bs4 import BeautifulSoup
 from selenium.webdriver import Firefox
 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
 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)
 """
 

+ 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
-import time
 import re
+import time
 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 selenium.common.exceptions import WebDriverException
+from selenium.webdriver import Firefox
 
 
 def get_unfccc_submission_info(
@@ -13,7 +13,7 @@ def get_unfccc_submission_info(
         driver: Firefox,
         max_tries: int=10,
 
-) -> List[Dict[str,str]]:
+) -> list[dict[str,str]]:
     info = []
     pattern = re.compile(r"BUR ?\d")
     pattern_NC = re.compile(r"NC ?\d")
@@ -53,7 +53,7 @@ def get_unfccc_submission_info(
             subtree = html.find_all(
                 class_="field field--name-field-document-country field--type-termstore-entity-reference field--label-inline")
             country = subtree[0].find(class_="field--item").contents[0]
-        except (AttributeError, IndexError) as e:
+        except (AttributeError, IndexError):
             # author as backup for country
             subtree = html.find_all(class_="field--name-field-document-ca")
             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
 
 import sys
+
 import camelot
 import primap2 as pm2
 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
@@ -83,7 +83,7 @@ cat_codes_manual = {  # conversion to PRIMAP1 format
     '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"
 
@@ -216,7 +216,7 @@ for page in pages_to_read:
     if page in range(232, 235):
         df_current.iloc[
             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
     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
@@ -250,7 +250,8 @@ for page in pages_to_read:
 
     df_current["category"] = df_current["category"].replace(cat_codes_manual)
     # 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,
                                                                 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)
     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)
     # set index. necessary for the stack operation in the conversion to long format
     # 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)
     # 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,
                                                                 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',
             # 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.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.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',
@@ -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.5': '3.C.6',
     '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.a': '3.C.5.a', # 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
 # '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.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.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.g.': included in '3.A.1.j',
 # '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.D': {'sources': ['3.D.1', '3.D.2'], 'name': 'Other'},
     '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 sys
+
 import pandas as pd
 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
@@ -47,7 +47,7 @@ unit_info = {
 }
 cols_to_drop = ['Unnamed: 14', 'Unnamed: 16', 'Código IPCC.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']
 
 # 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")
     # 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)
-    # 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
     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

+ 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 sys
+
 import pandas as pd
 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
@@ -48,7 +48,7 @@ unit_info = {
 }
 cols_to_drop = ['Unnamed: 14', 'Unnamed: 16', 'Código IPCC.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']
 
 # 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")
     # 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)
-    # 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
     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

+ 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 primap2 as pm2
 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)
 
@@ -207,7 +208,7 @@ data_if = pm2.pm2io.convert_long_dataframe_if(
 
 
 # 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'])]
 
 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)
 
 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
 # 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 numpy as np
+import pandas as pd
+import primap2 as pm2
 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
@@ -31,7 +32,7 @@ year = 2019
 entity_row = 0
 unit_row = 1
 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"]
 
 
@@ -195,7 +196,8 @@ df_all["category"] = df_all["orig_cat_name"]
 # first the manual replacements
 df_all["category"] = df_all["category"].replace(cat_codes_manual)
 # 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 = 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
 import locale
+
 gwp_to_use = 'SARGWP100'
 terminology_proc = 'IPCC2006_PRIMAP'
 # bunkers [0,1] need different specs
@@ -432,4 +433,4 @@ def is_int(input: str) -> bool:
         locale.atoi(input)
         return True
     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
 
-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 primap2 as pm2
 import pandas as pd
-import locale
+import primap2 as pm2
 
 # 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
 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}
 data_proc_pm2.pr.to_netcdf(
     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"
 
 
@@ -673,4 +672,4 @@ gas_baskets = {
     'KYOTOGHG (AR4GWP100)': ['CO2', 'CH4', 'N2O', 'FGASES (AR4GWP100)'],
     'KYOTOGHG (AR5GWP100)': ['CO2', 'CH4', 'N2O', 'FGASES (AR5GWP100)'],
     'KYOTOGHG (AR6GWP100)': ['CO2', 'CH4', 'N2O', 'FGASES (AR6GWP100)'],
-}
+}

Some files were not shown because too many files changed in this diff