diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..0d3206e --- /dev/null +++ b/.flake8 @@ -0,0 +1,12 @@ +[flake8] +count = true +docstring-convention = "google" +exclude = ".git,__pycache__,docs,build,dist,.venv,.github" +filename = "*py" +ignore = "E4,E501" +max-complexity = 10 +max-line-length = 80 +require-plugins = "flake8-docstrings" +show-source = true +statistics = true +tee = true diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml new file mode 100644 index 0000000..85edd1a --- /dev/null +++ b/.github/workflows/run-tests.yaml @@ -0,0 +1,75 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions + +name: Run tests + +on: + push: + branches: + - main + - dev + pull_request: + branches: + - main + - dev + workflow_dispatch: + +jobs: + test: + runs-on: ${{ matrix.os }} + timeout-minutes: 10 + strategy: + fail-fast: false + matrix: + python-version: ["3.9", "3.10"] + os: [ubuntu-18.04, macOS-latest, windows-latest] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Run poetry image + uses: abatilo/actions-poetry@v2.0.0 + with: + poetry-version: 1.1.13 + - name: Install dependencies + run: | + poetry install + - name: Run tests + run: | + poetry run pytest --cov=pystatis tests + code-quality: + strategy: + fail-fast: false + matrix: + python-version: [3.10.2] + poetry-version: [1.1.13] + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Run poetry image + uses: abatilo/actions-poetry@v2.0.0 + with: + poetry-version: ${{ matrix.poetry-version }} + - name: Install dependencies + run: poetry install + - name: Run black + run: poetry run black . --check + - name: Run isort + run: poetry run isort . --check-only + - name: Run flake8 + run: poetry run flake8 src --output-file=flake8_report.txt + - name: Run pylint + run: poetry run pylint src --recursive=y + - name: Run bandit + run: poetry run bandit -r src + - name: Run safety + run: poetry run safety check + - name: Run mypy + run: poetry run mypy src diff --git a/.gitignore b/.gitignore index b6e4761..6ed180a 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,7 @@ dmypy.json # Pyre type checker .pyre/ + + +# VSC +.vscode diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..eed79bb --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,31 @@ +exclude: "(doc|dist)" +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.1.0 # Use the ref you want to point at + hooks: + - id: check-yaml + - id: check-toml + - id: end-of-file-fixer + - id: mixed-line-ending + - id: trailing-whitespace + args: [--markdown-linebreak-ext=md] + - id: check-added-large-files + - id: check-merge-conflict + - repo: https://github.com/pycqa/isort + rev: 5.10.1 + hooks: + - id: isort + name: isort (python) + args: ["--profile", "black", "--filter-files", "--line-length", "80"] + - repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.14.2 + hooks: + - id: check-jsonschema + name: "Check GitHub Workflows" + files: ^\.github/workflows/ + types: [yaml] + args: ["--schemafile", "https://json.schemastore.org/github-workflow"] diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..9b33a96 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,399 @@ +# This Pylint rcfile contains a best-effort configuration to uphold the +# best-practices and style described in the Google Python style guide: +# https://google.github.io/styleguide/pyguide.html +# +# Its canonical open-source location is: +# https://google.github.io/styleguide/pylintrc + +[MASTER] + +# Files or directories to be skipped. They should be base names, not paths. +ignore=third_party + +# Files or directories matching the regex patterns are skipped. The regex +# matches against base names, not paths. +ignore-patterns=test_.* + +# Pickle collected data for later comparisons. +persistent=no + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Use multiple processes to speed up Pylint. +jobs=4 + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=abstract-method, + apply-builtin, + backtick, + bad-option-value, + basestring-builtin, + buffer-builtin, + c-extension-no-member, + cmp-builtin, + cmp-method, + coerce-builtin, + coerce-method, + delslice-method, + div-method, + execfile-builtin, + file-builtin, + filter-builtin-not-iterating, + fixme, + getslice-method, + hex-method, + idiv-method, + input-builtin, + intern-builtin, + invalid-str-codec, + locally-disabled, + long-builtin, + long-suffix, + map-builtin-not-iterating, + no-absolute-import, + no-else-break, + no-else-continue, + no-else-raise, + no-else-return, + no-init, # added + no-member, + no-name-in-module, + no-self-use, + nonzero-method, + oct-method, + old-division, + old-ne-operator, + old-octal-literal, + old-raise-syntax, + parameter-unpacking, + raising-string, + range-builtin-not-iterating, + raw_input-builtin, + rdiv-method, + reduce-builtin, + relative-import, + reload-builtin, + round-builtin, + setslice-method, + signature-differs, + standarderror-builtin, + suppressed-message, + sys-max-int, + too-few-public-methods, + trailing-whitespace, + unichr-builtin, + unicode-builtin, + unnecessary-pass, + unpacking-in-except, + using-cmp-argument, + wrong-import-order, + xrange-builtin, + zip-builtin-not-iterating + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages +reports=no + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + + +[BASIC] + +# Good variable names which should always be accepted, separated by a comma +good-names=main,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl + +# Regular expression matching correct function names +function-rgx=^(?:(?PsetUp|tearDown|setUpModule|tearDownModule)|(?P_?[A-Z][a-zA-Z0-9]*)|(?P_?[a-z][a-z0-9_]*))$ + +# Regular expression matching correct variable names +variable-rgx=^[a-z][a-z0-9_]*$ + +# Regular expression matching correct constant names +const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ + +# Regular expression matching correct attribute names +attr-rgx=^_{0,2}[a-z][a-z0-9_]*$ + +# Regular expression matching correct argument names +argument-rgx=^[a-z][a-z0-9_]*$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=^[a-z][a-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=^_?[A-Z][a-zA-Z0-9]*$ + +# Regular expression matching correct module names +module-rgx=^(_?[a-z][a-z0-9_]*|__init__)$ + +# Regular expression matching correct method names +method-rgx=(?x)^(?:(?P_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P_{0,2}[a-z][a-z0-9_]*))$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test|^_.*)$ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=10 + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=120 + +# TODO(https://github.com/PyCQA/pylint/issues/3352): Direct pylint to exempt +# lines made too long by directives to pytype. + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=(?x)( + ^\s*(\#\ )??$| + ^\s*(from\s+\S+\s+)?import\s+.+$) + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=yes + +# Maximum number of lines in a module +max-module-lines=99999 + +# String used as indentation unit. The internal Google style guide mandates 2 +# spaces. Google's externaly-published style guide says 4, consistent with +# PEP 8. Here, we use 2 spaces, for conformity with many open-sourced Google +# projects (like TensorFlow). +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=TODO + + +[STRING] + +# This flag controls whether inconsistent-quotes generates a warning when the +# character used as a quote delimiter is used inconsistently within a module. +check-quote-consistency=yes + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_) + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging,absl.logging,tensorflow.io.logging + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub, + TERMIOS, + Bastion, + rexec, + sets + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant, absl + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict, + _fields, + _replace, + _source, + _make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls, + class_ + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=StandardError, + Exception, + BaseException diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..b3cc99b --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,7 @@ +Copyright © 2022 Michael Aydinbas + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b40f0fe --- /dev/null +++ b/README.md @@ -0,0 +1,172 @@ +# ``pystatis`` + +```pystatis``` is a Python wrapper for the GENESIS web service interface (API). It simplifies accessing the data from the German statistical federal office. + +The main features are: + +- **Simplified access** to the API. No more need to write cumbersome API calls. +- **Credential management** removes need to manually add credentials. +- **Integrated workflow** enables an end-to-end process from finding the relevant data to download it. +- **Pandas support** instead of manually parsing results. +- **Caching** to enable productive work despite strict query limits. +- **Starting and handling background jobs** for datasets that are to big to be downloaded directly from GENESIS. + +To learn more about GENESIS refer to the official documentation [here](https://www.destatis.de/EN/Service/OpenData/api-webservice.html). + +## Installation + +You can install the package via + +```bash +$ pip install pystatis +``` + +If everything worked out correctly, you should be able to import ``pystatis`` like this + +```python +import pystatis as pystat + +print("Version:", pystat.__version__) +``` + +## Get started + +To be able to use the web service/API of GENESIS-Online, you have to be a registered user. You can create your user [here](https://www-genesis.destatis.de/genesis/online?Menu=Anmeldung). + +Once you have a registered user, you can use your username and password as credentials for authentication against the GENESIS-Online API. + +To avoid entering your credentials each time you use ``pystatis``, your credentials will be stored locally with the `init_config()` helper function. This function accepts both a `username` and `password` argument and stores your credentials in a configuration file named `config.ini` that is stored under `/.pystatis/config.ini` by default. You can change this path with the optional `config_dir` argument. + +So before you can use ``pystatis`` you have to execute the following code **once**: + +```python +from pystatis import init_config + +init_config(username="myusername", password="mypassword") +``` + +After executing this code you should have a new `config.ini` file under the `/.pystatis` directory. + +Each time ``pystatis`` is communicating with GENESIS-Online via the API, it is automatically using the stored credentials in this `config.ini`, so you don't have to specify them again. In case of updated credentials, you can either run `init_config()` again or update the values directly in the `config.ini` file. + +GENESIS-Online provides a `helloworld` endpoint that can be used to check your credentials: + +```python +from pystatis import logincheck + +logincheck() +>>> '{"Status":"Sie wurden erfolgreich an- und abgemeldet!","Username":"ASFJ582LJ"}' +``` + +If you can see a response like this, your setup is complete and you can start downloading data. + +For more details, please study the provided sample notebook for [cache](./nb/cache.ipynb). + +## How to use + +### The GENESIS data model + +The Genesis data structure consists of multiple elements as summarized in the image below. +![Structure](assets/structure.png) + +This package currently supports retrieving the following data types: + +- Cubes: Multi-dimensional data objects +- Tables: Derivatives of cubes that are already packaged into logical units + +### Find the right data + +``pystatis`` offers the `Find` class to search for any piece of information with GENESIS. Behind the scene it's using the `find` endpoint. + +Example: + +```python +from pystatis import Find + +results = Find("Rohöl") # Initiates object that contains all variables, statistics, tables and cubes +results.run() # Runs the query +results.tables.df # Results for tables +results.tables.get_code([1,2,3]) # Gets the table codes, e.g. for downloading the table +results.tables.get_metadata([1,2]) # Gets the metadata for the table +``` + +A complete overview of all use cases is provided in the [sample notebook.](/nb/find.py) + +### Download data + +Data can be downloaded in to forms: as tables and as cubes. Both interfaces have been aligned to be as close as possible to each other. + +Example for downloading a Table: + +```python +from pystatis import Table + +t = Table(name="21311-0001") # data is not yet downloaded +t.get_data() # Only now the data is either fetched from GENESIS or loaded from cache. If the data is downloaded from online, it will be also cached, so next time the data is loaded from cache. +t.data # a pandas data frame +``` + +Example for downloading a Cube: + +```python +from pystatis import Cube + +c = Cube(name="22922KJ1141") # data is not yet downloaded +c.get_data() # Only now the data is either fetched from GENESIS or loaded from cache. If the data is downloaded from online, it will be also cached, so next time the data is loaded from cache. +c.data # a pandas data frame +``` + +For more details, please study the provided sample notebook for [tables](./nb/table.ipynb) and [cubes](./nb/cube.ipynb). + +### Clear Cache + +When a cube or table is queried, it will be put into cache automatically. The cache can be cleared using the following function: + +```python +from pystatis import clear_cache + +clear_cache("21311-0001") # only deletes the data for the object with the specified name +clear_cache() # deletes the complete cache +``` + +## License + +Distributed under the MIT License. See `LICENSE.txt` for more information. + +## Roadmap + +A few ideas we should implement in the maybe-near future: + +- Improve Table parsing. Right now, the parsing is really simple and we should align the cube and table format so that the data frame for tables is more convenient to use. +- Create a source code documentation with Sphinx or similar tools. +- Mechanism to download data that is newer than the cached version. Right now, once data is cached, it is always retrieved from cache no matter if there is a newer version online. However, this could be quite challenging as the GENESIS API is really bad in providing a good and consistent field for the last update datetime. +- Improve Table and Cube metadata so the user can look up the variables contained in the dataset and for each variable the values that this variable can have. +- Understand and support time series. + +## How to contribute? + +Contributions to this project are highly appreciated! You can either contact the maintainers or directly create a pull request for your proposed changes: + +1. Fork the Project +2. Create your Feature Branch (`git checkout -b feature/`) +3. Commit your changes (`git commit -m 'Added NewFeature'`) +4. Push to remote (`git push origin feature/`) +5. Open a Pull Request to be merged with dev + +## Developer information + +To contribute to this project, please follow these steps: + +1. Install [poetry](https://python-poetry.org/docs/). We recommend installing `poetry` via [pipx](https://pypa.github.io/pipx/) which gives you a global `poetry` command in an isolated virtual environment. +2. Clone the repository via git. +3. Change into the project root directory. +4. Run `poetry install` to create the virtual environment within `poetry`'s cache folder (run `poetry env info` to see the details of this new virtual environment). `poetry` has installed all dependencies for you, as well as the package itself. +5. Install pre-commit: `poetry run pre-commit install`. This will activate the pre-commit hooks that will run prior every commit to ensure code quality. +6. Do your changes. +7. Run `poetry run pytest` to see if all existing tests still run through. It is important to use `poetry run` to call `pytest` so that `poetry` uses the created virtual environment and not the system's default Python interpreter. Alternatively, you can run `poetry shell` to let `poetry` activate the virtual environment for the current session. Afterwards, you can run `pytest` as usual without any prefix. You can leave the poetry shell with the `exit` command. +8. Add new tests depending on your changes. +9. Run `poetry run pytest` again to make sure your tests are also passed. +10. Commit and push your changes. +11. Create a PR. + +To learn more about `poetry`, see [Dependency Management With Python Poetry](https://realpython.com/dependency-management-python-poetry/#command-reference) by realpython.com. diff --git a/assets/structure.png b/assets/structure.png new file mode 100644 index 0000000..02d899f Binary files /dev/null and b/assets/structure.png differ diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000..dd2284f --- /dev/null +++ b/mypy.ini @@ -0,0 +1,15 @@ +# Global options: + +[mypy] +python_version = 3.9 +warn_return_any = True +warn_unused_configs = True +show_error_codes=True + +# Per-module options: + +[mypy-pandas] +ignore_missing_imports = True + +[mypy-requests] +ignore_missing_imports = True diff --git a/nb/cache.ipynb b/nb/cache.ipynb new file mode 100644 index 0000000..474b9c6 --- /dev/null +++ b/nb/cache.ipynb @@ -0,0 +1,91 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "6a0fdd61", + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "logging.basicConfig(level=logging.INFO)\n", + "\n", + "import pystatis\n", + "from pystatis import Cube, Table, init_config, clear_cache" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c4b965e", + "metadata": {}, + "outputs": [], + "source": [ + "# only run this if you haven't done so earlier\n", + "# init_config()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "601075cc", + "metadata": {}, + "outputs": [], + "source": [ + "# first, let's download two data sets\n", + "# these will be cached under your \n", + "Cube(name=\"22922KJ1141\").get_data()\n", + "Table(name=\"21311-0001\").get_data()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa6c2498", + "metadata": {}, + "outputs": [], + "source": [ + "# You can now test the clear_cache function!\n", + "# Either with a particular name\n", + "clear_cache(\"21311-0001\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "836b9b2b", + "metadata": {}, + "outputs": [], + "source": [ + "# Or without a name to clear the whole cache at once\n", + "clear_cache()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.7 ('.venv': poetry)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + }, + "vscode": { + "interpreter": { + "hash": "02e23b522f8c3795158421909d41ced4ef90521258d58d1c53bee449d96f71e3" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/nb/cube.ipynb b/nb/cube.ipynb new file mode 100644 index 0000000..ef9584e --- /dev/null +++ b/nb/cube.ipynb @@ -0,0 +1,118 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "25e9250e", + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "logging.basicConfig(level=logging.INFO)\n", + "\n", + "from pystatis import Cube" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b28edfd3", + "metadata": {}, + "outputs": [], + "source": [ + "c = Cube(name=\"22922KJ1141\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ead4f13c", + "metadata": {}, + "outputs": [], + "source": [ + "c.get_data()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ac68d224", + "metadata": {}, + "outputs": [], + "source": [ + "c.name" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4bec2cdb", + "metadata": {}, + "outputs": [], + "source": [ + "for k,v in c.cube.items():\n", + " print(\"Cube section: \", k)\n", + " print(v)\n", + " print()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e69759d9", + "metadata": {}, + "outputs": [], + "source": [ + "c.data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b57fbeab", + "metadata": {}, + "outputs": [], + "source": [ + "c.data.info()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f2f260b3", + "metadata": {}, + "outputs": [], + "source": [ + "from pprint import pprint \n", + "\n", + "pprint(c.metadata)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.7 ('.venv': poetry)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + }, + "vscode": { + "interpreter": { + "hash": "02e23b522f8c3795158421909d41ced4ef90521258d58d1c53bee449d96f71e3" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/nb/find.ipynb b/nb/find.ipynb new file mode 100644 index 0000000..80b9447 --- /dev/null +++ b/nb/find.ipynb @@ -0,0 +1,436 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "logging.basicConfig(level=logging.INFO)\n", + "\n", + "from pystatis import Find" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can initiate a find object using a search query, after you execute .run() it will automatically find the data (tables, variables, statistics, ...)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "results = Find(\"Rohöl\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "##### Results #####\n", + "----------------------------------------\n", + "# Number of tables: 16\n", + "# Preview:\n", + "| | Code | Content | Time |\n", + "|---:|:-----------|:-------------------------------------------------------------------------------------------------------------------------------------------------|:-------|\n", + "| 0 | 42131-0003 | Produktionswert, -menge, -gewicht und Unternehmen der Vierteljährlichen Produktionserhebung: Deutschland, Jahre, Güterverzeichnis (9-Steller) | |\n", + "| 1 | 42131-0004 | Produktionswert, -menge, -gewicht und Unternehmen der Vierteljährlichen Produktionserhebung: Deutschland, Quartale, Güterverzeichnis (9-Steller) | |\n", + "| 2 | 51000-0005 | Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Warensystematik | |\n", + "| 3 | 51000-0006 | Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Warensystematik | |\n", + "| 4 | 51000-0009 | Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Land, Warenverzeichnis (4-/6-Steller) | |\n", + "----------------------------------------# Number of statistics: 3\n", + "# Preview:\n", + "| | Code | Content | Cubes | Information |\n", + "|---:|-------:|:---------------------------------------------------|--------:|:--------------|\n", + "| 0 | 42131 | Vierteljährliche Produktionserhebung i.Verarb.Gew. | 18 | true |\n", + "| 1 | 51000 | Außenhandel | 79 | true |\n", + "| 2 | 61241 | Index der Erzeugerpreise gewerblicher Produkte | 18 | true |\n", + "----------------------------------------\n", + "# Number of variables: 6\n", + "# Preview:\n", + "| | Code | Content | Type | Values | Information |\n", + "|---:|:-------|:---------------------------------------------------|:---------|---------:|:--------------|\n", + "| 0 | GP02A9 | GP2002 (9-Steller (Arten)) | sachlich | 6147 | true |\n", + "| 1 | GP09A9 | GP2009 (9-Steller (Arten)) | sachlich | 5250 | true |\n", + "| 2 | GP09N1 | GP2009 (ausgewählte 9-Steller): Gewerbl. Produkte | sachlich | 1350 | false |\n", + "| 3 | GP19A9 | GP2019 (9-Steller (Arten)) | sachlich | 5018 | true |\n", + "| 4 | WAM6 | Warenverzeichnis Außenhandelsstatistik (6-Steller) | sachlich | 6339 | true |\n", + "----------------------------------------\n", + "# Number of cubes: 16\n", + "# Preview:\n", + "| | Code | Content | State | Time | LatestUpdate | Information |\n", + "|---:|:-----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------|:--------------------------------|:---------------------|:--------------|\n", + "| 0 | 42131BJ003 | Vierteljährliche Produktionserhebung i.Verarb.Gew., Wert der zum Absatz bestimmten Produktion, Menge der zum Absatz bestimmten Produktion (BM), Gewicht der zum Absatz bestimmten Produktion, Gewicht der zum Absatz bestimmten Produktion (kg), Menge der zum Absatz bestimmten Produktion, Menge der Gesamtproduktion (BM), Gewicht der Gesamtproduktion, Gewicht der Gesamtproduktion (kg), Menge der Gesamtproduktion (Stück), Unternehmen mit zum Absatz bestimmter Produktion, Unternehmen mit Produktion, GP2002 (9-Steller (Arten)), Deutschland insgesamt, Jahr | vollständig mit Werten | 2002-2008 | 10.07.2019 11:54:06h | false |\n", + "| 1 | 42131BJ103 | Vierteljährliche Produktionserhebung i.Verarb.Gew., Wert der zum Absatz bestimmten Produktion, Menge der zum Absatz bestimmten Produktion (BM), Gewicht der zum Absatz bestimmten Produktion, Gewicht der zum Absatz bestimmten Produktion (kg), Menge der zum Absatz bestimmten Produktion, Menge der Gesamtproduktion (BM), Gewicht der Gesamtproduktion, Gewicht der Gesamtproduktion (kg), Menge der Gesamtproduktion (Stück), Unternehmen mit zum Absatz bestimmter Produktion, Unternehmen mit Produktion, GP2009 (9-Steller (Arten)), Deutschland insgesamt, Jahr | vollständig mit Werten | 2009-2018 | 16.08.2021 16:30:29h | false |\n", + "| 2 | 42131BJ203 | Vierteljährliche Produktionserhebung i.Verarb.Gew., Wert der zum Absatz bestimmten Produktion, Menge der zum Absatz bestimmten Produktion (BM), Gewicht der zum Absatz bestimmten Produktion, Gewicht der zum Absatz bestimmten Produktion (kg), Menge der zum Absatz bestimmten Produktion, Menge der Gesamtproduktion (BM), Gewicht der Gesamtproduktion, Gewicht der Gesamtproduktion (kg), Menge der Gesamtproduktion (Stück), Unternehmen mit zum Absatz bestimmter Produktion, Unternehmen mit Produktion, GP2019 (9-Steller (Arten)), Deutschland insgesamt, Jahr | vollständig mit Werten | 2019-2021 | 29.04.2022 08:02:58h | false |\n", + "| 3 | 42131BV003 | Vierteljährliche Produktionserhebung i.Verarb.Gew., Wert der zum Absatz bestimmten Produktion, Menge der zum Absatz bestimmten Produktion (BM), Gewicht der zum Absatz bestimmten Produktion, Gewicht der zum Absatz bestimmten Produktion (kg), Menge der zum Absatz bestimmten Produktion, Menge der Gesamtproduktion (BM), Gewicht der Gesamtproduktion, Gewicht der Gesamtproduktion (kg), Menge der Gesamtproduktion (Stück), Unternehmen mit zum Absatz bestimmter Produktion, Unternehmen mit Produktion, GP2002 (9-Steller (Arten)), Deutschland insgesamt, Quartale, Jahr | vollständig mit Werten | 1. Quartal 2002-4. Quartal 2008 | 10.07.2019 11:51:58h | false |\n", + "| 4 | 42131BV103 | Vierteljährliche Produktionserhebung i.Verarb.Gew., Wert der zum Absatz bestimmten Produktion, Menge der zum Absatz bestimmten Produktion (BM), Gewicht der zum Absatz bestimmten Produktion, Gewicht der zum Absatz bestimmten Produktion (kg), Menge der zum Absatz bestimmten Produktion, Menge der Gesamtproduktion (BM), Gewicht der Gesamtproduktion, Gewicht der Gesamtproduktion (kg), Menge der Gesamtproduktion (Stück), Unternehmen mit zum Absatz bestimmter Produktion, Unternehmen mit Produktion, GP2009 (9-Steller (Arten)), Deutschland insgesamt, Quartale, Jahr | vollständig mit Werten | 1. Quartal 2009-4. Quartal 2018 | 16.08.2021 16:32:10h | false |\n", + "----------------------------------------\n", + "# Use object.tables, object.statistics, object.variables or object.cubes to get all results.\n", + "----------------------------------------\n" + ] + } + ], + "source": [ + "results.run()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "| | Code | Content | Time |\n", + "|---:|:-----------|:-------------------------------------------------------------------------------------------------------------------------------------------------|:-------|\n", + "| 0 | 42131-0003 | Produktionswert, -menge, -gewicht und Unternehmen der Vierteljährlichen Produktionserhebung: Deutschland, Jahre, Güterverzeichnis (9-Steller) | |\n", + "| 1 | 42131-0004 | Produktionswert, -menge, -gewicht und Unternehmen der Vierteljährlichen Produktionserhebung: Deutschland, Quartale, Güterverzeichnis (9-Steller) | |\n", + "| 2 | 51000-0005 | Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Warensystematik | |\n", + "| 3 | 51000-0006 | Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Warensystematik | |\n", + "| 4 | 51000-0009 | Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Land, Warenverzeichnis (4-/6-Steller) | |\n", + "| 5 | 51000-0010 | Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Ware (4-/6-Steller), Länder | |\n", + "| 6 | 51000-0011 | Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Land, Warenverzeichnis (4-/6-Steller) | |\n", + "| 7 | 51000-0012 | Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Ware (4-/6-Steller), Länder | |\n", + "| 8 | 51000-0013 | Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Warenverzeichnis (8-Steller) | |\n", + "| 9 | 51000-0014 | Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Warenverzeichnis (8-Steller) | |\n", + "| 10 | 51000-0015 | Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Land, Warenverzeichnis (8-Steller) | |\n", + "| 11 | 51000-0016 | Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Ware (8-Steller), Länder | |\n", + "| 12 | 51000-0017 | Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Land, Warenverzeichnis (8-Steller) | |\n", + "| 13 | 51000-0018 | Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Ware (8-Steller), Länder | |\n", + "| 14 | 61241-0003 | Erzeugerpreisindex gewerblicher Produkte: Deutschland, Jahre, Güterverzeichnis (GP2009 2-/3-/4-/5-/6-/9-Steller/ Sonderpositionen) | |\n", + "| 15 | 61241-0004 | Erzeugerpreisindex gewerblicher Produkte: Deutschland, Monate, Güterverzeichnis (GP2009 2-/3-/4-/5-/6-/9-Steller/ Sonderpositionen) | |" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "results.tables" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
CodeContentTime
042131-0003Produktionswert, -menge, -gewicht und Unternehmen der Vierteljährlichen Produktionserhebung: Deutschland, Jahre, Güterverzeichnis (9-Steller)
142131-0004Produktionswert, -menge, -gewicht und Unternehmen der Vierteljährlichen Produktionserhebung: Deutschland, Quartale, Güterverzeichnis (9-Steller)
251000-0005Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Warensystematik
351000-0006Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Warensystematik
451000-0009Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Land, Warenverzeichnis (4-/6-Steller)
551000-0010Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Ware (4-/6-Steller), Länder
651000-0011Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Land, Warenverzeichnis (4-/6-Steller)
751000-0012Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Ware (4-/6-Steller), Länder
851000-0013Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Warenverzeichnis (8-Steller)
951000-0014Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Warenverzeichnis (8-Steller)
1051000-0015Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Land, Warenverzeichnis (8-Steller)
1151000-0016Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Ware (8-Steller), Länder
1251000-0017Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Land, Warenverzeichnis (8-Steller)
1351000-0018Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Ware (8-Steller), Länder
1461241-0003Erzeugerpreisindex gewerblicher Produkte: Deutschland, Jahre, Güterverzeichnis (GP2009 2-/3-/4-/5-/6-/9-Steller/ Sonderpositionen)
1561241-0004Erzeugerpreisindex gewerblicher Produkte: Deutschland, Monate, Güterverzeichnis (GP2009 2-/3-/4-/5-/6-/9-Steller/ Sonderpositionen)
\n", + "
" + ], + "text/plain": [ + " Code Content Time\n", + "0 42131-0003 Produktionswert, -menge, -gewicht und Unternehmen der Vierteljährlichen Produktionserhebung: Deutschland, Jahre, Güterverzeichnis (9-Steller) \n", + "1 42131-0004 Produktionswert, -menge, -gewicht und Unternehmen der Vierteljährlichen Produktionserhebung: Deutschland, Quartale, Güterverzeichnis (9-Steller) \n", + "2 51000-0005 Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Warensystematik \n", + "3 51000-0006 Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Warensystematik \n", + "4 51000-0009 Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Land, Warenverzeichnis (4-/6-Steller) \n", + "5 51000-0010 Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Ware (4-/6-Steller), Länder \n", + "6 51000-0011 Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Land, Warenverzeichnis (4-/6-Steller) \n", + "7 51000-0012 Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Ware (4-/6-Steller), Länder \n", + "8 51000-0013 Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Warenverzeichnis (8-Steller) \n", + "9 51000-0014 Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Warenverzeichnis (8-Steller) \n", + "10 51000-0015 Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Land, Warenverzeichnis (8-Steller) \n", + "11 51000-0016 Aus- und Einfuhr (Außenhandel): Deutschland, Jahre, Ware (8-Steller), Länder \n", + "12 51000-0017 Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Land, Warenverzeichnis (8-Steller) \n", + "13 51000-0018 Aus- und Einfuhr (Außenhandel): Deutschland, Monate, Ware (8-Steller), Länder \n", + "14 61241-0003 Erzeugerpreisindex gewerblicher Produkte: Deutschland, Jahre, Güterverzeichnis (GP2009 2-/3-/4-/5-/6-/9-Steller/ Sonderpositionen) \n", + "15 61241-0004 Erzeugerpreisindex gewerblicher Produkte: Deutschland, Monate, Güterverzeichnis (GP2009 2-/3-/4-/5-/6-/9-Steller/ Sonderpositionen) " + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "results.tables.df" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['42131-0004', '51000-0005', '51000-0006']" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "results.tables.get_code([1,2,3])" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "TABLES 42131-0004 - 1\n", + "Name:\n", + "Vierteljährliche Produktionserhebung i.Verarb.Gew.\n", + "--------------------\n", + "Columns:\n", + "Quartale\n", + "--------------------\n", + "Rows:\n", + "GP2019 (9-Steller (Arten))\n", + "----------------------------------------\n", + "TABLES 51000-0005 - 2\n", + "Name:\n", + "Außenhandel\n", + "--------------------\n", + "Columns:\n", + "Ausfuhr: Gewicht\n", + "Ausfuhr: Wert\n", + "Ausfuhr: Wert (US-Dollar)\n", + "Einfuhr: Gewicht\n", + "Einfuhr: Wert\n", + "Einfuhr: Wert (US-Dollar)\n", + "--------------------\n", + "Rows:\n", + "Warenverzeichnis Außenhandelsstatistik (2-Steller)\n", + "----------------------------------------\n" + ] + } + ], + "source": [ + "results.tables.get_metadata([1,2])" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CUBES 42131BJ103 - 1\n", + "Name:\n", + "Vierteljährliche Produktionserhebung i.Verarb.Gew., Wert der zum Absatz bestimmten Produktion, Menge der zum Absatz bestimmten Produktion (BM), Gewicht der zum Absatz bestimmten Produktion, Gewicht der zum Absatz bestimmten Produktion (kg), Menge der zum Absatz bestimmten Produktion, Menge der Gesamtproduktion (BM), Gewicht der Gesamtproduktion, Gewicht der Gesamtproduktion (kg), Menge der Gesamtproduktion (Stück), Unternehmen mit zum Absatz bestimmter Produktion, Unternehmen mit Produktion, GP2009 (9-Steller (Arten)), Deutschland insgesamt, Jahr\n", + "--------------------\n", + "Content:\n", + "GP2009 (9-Steller (Arten))\n", + "Deutschland insgesamt\n", + "Jahr\n", + "----------------------------------------\n", + "CUBES 42131BJ203 - 2\n", + "Name:\n", + "Vierteljährliche Produktionserhebung i.Verarb.Gew., Wert der zum Absatz bestimmten Produktion, Menge der zum Absatz bestimmten Produktion (BM), Gewicht der zum Absatz bestimmten Produktion, Gewicht der zum Absatz bestimmten Produktion (kg), Menge der zum Absatz bestimmten Produktion, Menge der Gesamtproduktion (BM), Gewicht der Gesamtproduktion, Gewicht der Gesamtproduktion (kg), Menge der Gesamtproduktion (Stück), Unternehmen mit zum Absatz bestimmter Produktion, Unternehmen mit Produktion, GP2019 (9-Steller (Arten)), Deutschland insgesamt, Jahr\n", + "--------------------\n", + "Content:\n", + "GP2019 (9-Steller (Arten))\n", + "Deutschland insgesamt\n", + "Jahr\n", + "----------------------------------------\n" + ] + } + ], + "source": [ + "results.cubes.get_metadata([1,2])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.7 ('.venv': poetry)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + }, + "vscode": { + "interpreter": { + "hash": "02e23b522f8c3795158421909d41ced4ef90521258d58d1c53bee449d96f71e3" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/nb/helloworld.ipynb b/nb/helloworld.ipynb new file mode 100644 index 0000000..4fb6fae --- /dev/null +++ b/nb/helloworld.ipynb @@ -0,0 +1,70 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "logging.basicConfig(level=logging.INFO)\n", + "\n", + "from pystatis import logincheck, whoami" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `helloworld` module allows you to run basic functions checking your login credentials (`logincheck`) and test calling the Destatis API (`whoami`)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# test calling Destatis API (e.g. whether it is currently online)\n", + "whoami()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# test your login credentials (set via config functions)\n", + "logincheck()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.7 ('.venv': poetry)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "02e23b522f8c3795158421909d41ced4ef90521258d58d1c53bee449d96f71e3" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/nb/jobs.ipynb b/nb/jobs.ipynb new file mode 100644 index 0000000..b3e1c43 --- /dev/null +++ b/nb/jobs.ipynb @@ -0,0 +1,543 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "# Jobs\n", + "\n", + "Die Funktion `load_data` unterstützt das Abrufen von Jobs für zu große Tabellen. Destatis verweigert bei zu großen Tabellen die initiale Abfrage und gibt einen Status Code 98 zurück. Mit dem speziellen Query-Parameter `job=true` kann man jedoch die Verarbeitung im Hintergrund anstoßen. Die Tabelle wird dann für den User nach einiger Zeit bereitgestellt. Diese Tabelle kann dann über `data/resultfile` statt `data/tablefile` abgerufen werden. All diese Details verbergen wir jedoch vor dem Benutzer. Die Klasse `Table` verbirgt diese Komplexität und stellt die Daten, die von einem Job kommen, genauso zur Verfügung wie Daten, die über den normalen Destatis Endpunkt kommen. Der Benutzer muss lediglich eine etwas längere Wartezeit in Kauf nehmen (aktuell ein Timeout von 1 Minute)." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "import logging\n", + "logging.basicConfig(level=logging.INFO)\n", + "\n", + "import json\n", + "\n", + "from pystatis import Table" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Die Tabelle ist zu groß, um direkt abgerufen zu werden. Es wird eine Verarbeitung im Hintergrund gestartet.\n" + ] + } + ], + "source": [ + "# Wir wollen die Tabelle mit der Nummer 42153-0001 laden\n", + "# Sofern die Daten nicht gecacht wurden, wird uns eine Warnmeldung darüber informieren, dass hier ein Job angestoßen wird\n", + "t = Table(name=\"42153-0001\")\n", + "t.get_data(timeslices=20) # timeslices muss hier relativ hoch gewählt werden, damit ein Job angestoßen wird " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "# Eine erneute Abfrage findet die Daten im Cache und stellt sie dementsprechend sofort bereit\n", + "t = Table(name=\"42153-0001\")\n", + "t.get_data(timeslices=20)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Statistik_CodeStatistik_LabelZeit_CodeZeit_LabelZeit1_Merkmal_Code1_Merkmal_Label1_Auspraegung_Code1_Auspraegung_Label2_Merkmal_Code...2_Auspraegung_Label3_Merkmal_Code3_Merkmal_Label3_Auspraegung_Code3_Auspraegung_Label4_Merkmal_Code4_Merkmal_Label4_Auspraegung_Code4_Auspraegung_LabelPRO101__Produktionsindex__2015=100
042153Indizes der Produktion im Verarbeitenden GewerbeJAHRJahr2003DINSGDeutschland insgesamtDGDeutschlandWERT03...OriginalwerteWZ08V1WZ2008 (Hauptgruppen, Aggregate): Verarb. GewerbeWZ08-B-05Produzierendes GewerbeMONATMonateMONAT01Januar76,9
142153Indizes der Produktion im Verarbeitenden GewerbeJAHRJahr2003DINSGDeutschland insgesamtDGDeutschlandWERT03...OriginalwerteWZ08V1WZ2008 (Hauptgruppen, Aggregate): Verarb. GewerbeWZ08-B-05Produzierendes GewerbeMONATMonateMONAT02Februar77,9
242153Indizes der Produktion im Verarbeitenden GewerbeJAHRJahr2003DINSGDeutschland insgesamtDGDeutschlandWERT03...OriginalwerteWZ08V1WZ2008 (Hauptgruppen, Aggregate): Verarb. GewerbeWZ08-B-05Produzierendes GewerbeMONATMonateMONAT03März84,9
342153Indizes der Produktion im Verarbeitenden GewerbeJAHRJahr2003DINSGDeutschland insgesamtDGDeutschlandWERT03...OriginalwerteWZ08V1WZ2008 (Hauptgruppen, Aggregate): Verarb. GewerbeWZ08-B-05Produzierendes GewerbeMONATMonateMONAT04April82,9
442153Indizes der Produktion im Verarbeitenden GewerbeJAHRJahr2003DINSGDeutschland insgesamtDGDeutschlandWERT03...OriginalwerteWZ08V1WZ2008 (Hauptgruppen, Aggregate): Verarb. GewerbeWZ08-B-05Produzierendes GewerbeMONATMonateMONAT05Mai81,4
..................................................................
6239542153Indizes der Produktion im Verarbeitenden GewerbeJAHRJahr2022DINSGDeutschland insgesamtDGDeutschlandWERT03...BV4.1 TrendWZ08V1WZ2008 (Hauptgruppen, Aggregate): Verarb. GewerbeWZ08-30-01Sonstiger Fahrzeugbau ohne H. v. Fahrzeugen a....MONATMonateMONAT08August...
6239642153Indizes der Produktion im Verarbeitenden GewerbeJAHRJahr2022DINSGDeutschland insgesamtDGDeutschlandWERT03...BV4.1 TrendWZ08V1WZ2008 (Hauptgruppen, Aggregate): Verarb. GewerbeWZ08-30-01Sonstiger Fahrzeugbau ohne H. v. Fahrzeugen a....MONATMonateMONAT09September...
6239742153Indizes der Produktion im Verarbeitenden GewerbeJAHRJahr2022DINSGDeutschland insgesamtDGDeutschlandWERT03...BV4.1 TrendWZ08V1WZ2008 (Hauptgruppen, Aggregate): Verarb. GewerbeWZ08-30-01Sonstiger Fahrzeugbau ohne H. v. Fahrzeugen a....MONATMonateMONAT10Oktober...
6239842153Indizes der Produktion im Verarbeitenden GewerbeJAHRJahr2022DINSGDeutschland insgesamtDGDeutschlandWERT03...BV4.1 TrendWZ08V1WZ2008 (Hauptgruppen, Aggregate): Verarb. GewerbeWZ08-30-01Sonstiger Fahrzeugbau ohne H. v. Fahrzeugen a....MONATMonateMONAT11November...
6239942153Indizes der Produktion im Verarbeitenden GewerbeJAHRJahr2022DINSGDeutschland insgesamtDGDeutschlandWERT03...BV4.1 TrendWZ08V1WZ2008 (Hauptgruppen, Aggregate): Verarb. GewerbeWZ08-30-01Sonstiger Fahrzeugbau ohne H. v. Fahrzeugen a....MONATMonateMONAT12Dezember...
\n", + "

62400 rows × 22 columns

\n", + "
" + ], + "text/plain": [ + " Statistik_Code Statistik_Label \\\n", + "0 42153 Indizes der Produktion im Verarbeitenden Gewerbe \n", + "1 42153 Indizes der Produktion im Verarbeitenden Gewerbe \n", + "2 42153 Indizes der Produktion im Verarbeitenden Gewerbe \n", + "3 42153 Indizes der Produktion im Verarbeitenden Gewerbe \n", + "4 42153 Indizes der Produktion im Verarbeitenden Gewerbe \n", + "... ... ... \n", + "62395 42153 Indizes der Produktion im Verarbeitenden Gewerbe \n", + "62396 42153 Indizes der Produktion im Verarbeitenden Gewerbe \n", + "62397 42153 Indizes der Produktion im Verarbeitenden Gewerbe \n", + "62398 42153 Indizes der Produktion im Verarbeitenden Gewerbe \n", + "62399 42153 Indizes der Produktion im Verarbeitenden Gewerbe \n", + "\n", + " Zeit_Code Zeit_Label Zeit 1_Merkmal_Code 1_Merkmal_Label \\\n", + "0 JAHR Jahr 2003 DINSG Deutschland insgesamt \n", + "1 JAHR Jahr 2003 DINSG Deutschland insgesamt \n", + "2 JAHR Jahr 2003 DINSG Deutschland insgesamt \n", + "3 JAHR Jahr 2003 DINSG Deutschland insgesamt \n", + "4 JAHR Jahr 2003 DINSG Deutschland insgesamt \n", + "... ... ... ... ... ... \n", + "62395 JAHR Jahr 2022 DINSG Deutschland insgesamt \n", + "62396 JAHR Jahr 2022 DINSG Deutschland insgesamt \n", + "62397 JAHR Jahr 2022 DINSG Deutschland insgesamt \n", + "62398 JAHR Jahr 2022 DINSG Deutschland insgesamt \n", + "62399 JAHR Jahr 2022 DINSG Deutschland insgesamt \n", + "\n", + " 1_Auspraegung_Code 1_Auspraegung_Label 2_Merkmal_Code ... \\\n", + "0 DG Deutschland WERT03 ... \n", + "1 DG Deutschland WERT03 ... \n", + "2 DG Deutschland WERT03 ... \n", + "3 DG Deutschland WERT03 ... \n", + "4 DG Deutschland WERT03 ... \n", + "... ... ... ... ... \n", + "62395 DG Deutschland WERT03 ... \n", + "62396 DG Deutschland WERT03 ... \n", + "62397 DG Deutschland WERT03 ... \n", + "62398 DG Deutschland WERT03 ... \n", + "62399 DG Deutschland WERT03 ... \n", + "\n", + " 2_Auspraegung_Label 3_Merkmal_Code \\\n", + "0 Originalwerte WZ08V1 \n", + "1 Originalwerte WZ08V1 \n", + "2 Originalwerte WZ08V1 \n", + "3 Originalwerte WZ08V1 \n", + "4 Originalwerte WZ08V1 \n", + "... ... ... \n", + "62395 BV4.1 Trend WZ08V1 \n", + "62396 BV4.1 Trend WZ08V1 \n", + "62397 BV4.1 Trend WZ08V1 \n", + "62398 BV4.1 Trend WZ08V1 \n", + "62399 BV4.1 Trend WZ08V1 \n", + "\n", + " 3_Merkmal_Label 3_Auspraegung_Code \\\n", + "0 WZ2008 (Hauptgruppen, Aggregate): Verarb. Gewerbe WZ08-B-05 \n", + "1 WZ2008 (Hauptgruppen, Aggregate): Verarb. Gewerbe WZ08-B-05 \n", + "2 WZ2008 (Hauptgruppen, Aggregate): Verarb. Gewerbe WZ08-B-05 \n", + "3 WZ2008 (Hauptgruppen, Aggregate): Verarb. Gewerbe WZ08-B-05 \n", + "4 WZ2008 (Hauptgruppen, Aggregate): Verarb. Gewerbe WZ08-B-05 \n", + "... ... ... \n", + "62395 WZ2008 (Hauptgruppen, Aggregate): Verarb. Gewerbe WZ08-30-01 \n", + "62396 WZ2008 (Hauptgruppen, Aggregate): Verarb. Gewerbe WZ08-30-01 \n", + "62397 WZ2008 (Hauptgruppen, Aggregate): Verarb. Gewerbe WZ08-30-01 \n", + "62398 WZ2008 (Hauptgruppen, Aggregate): Verarb. Gewerbe WZ08-30-01 \n", + "62399 WZ2008 (Hauptgruppen, Aggregate): Verarb. Gewerbe WZ08-30-01 \n", + "\n", + " 3_Auspraegung_Label 4_Merkmal_Code \\\n", + "0 Produzierendes Gewerbe MONAT \n", + "1 Produzierendes Gewerbe MONAT \n", + "2 Produzierendes Gewerbe MONAT \n", + "3 Produzierendes Gewerbe MONAT \n", + "4 Produzierendes Gewerbe MONAT \n", + "... ... ... \n", + "62395 Sonstiger Fahrzeugbau ohne H. v. Fahrzeugen a.... MONAT \n", + "62396 Sonstiger Fahrzeugbau ohne H. v. Fahrzeugen a.... MONAT \n", + "62397 Sonstiger Fahrzeugbau ohne H. v. Fahrzeugen a.... MONAT \n", + "62398 Sonstiger Fahrzeugbau ohne H. v. Fahrzeugen a.... MONAT \n", + "62399 Sonstiger Fahrzeugbau ohne H. v. Fahrzeugen a.... MONAT \n", + "\n", + " 4_Merkmal_Label 4_Auspraegung_Code 4_Auspraegung_Label \\\n", + "0 Monate MONAT01 Januar \n", + "1 Monate MONAT02 Februar \n", + "2 Monate MONAT03 März \n", + "3 Monate MONAT04 April \n", + "4 Monate MONAT05 Mai \n", + "... ... ... ... \n", + "62395 Monate MONAT08 August \n", + "62396 Monate MONAT09 September \n", + "62397 Monate MONAT10 Oktober \n", + "62398 Monate MONAT11 November \n", + "62399 Monate MONAT12 Dezember \n", + "\n", + " PRO101__Produktionsindex__2015=100 \n", + "0 76,9 \n", + "1 77,9 \n", + "2 84,9 \n", + "3 82,9 \n", + "4 81,4 \n", + "... ... \n", + "62395 ... \n", + "62396 ... \n", + "62397 ... \n", + "62398 ... \n", + "62399 ... \n", + "\n", + "[62400 rows x 22 columns]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t.data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.7 ('.venv': poetry)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + }, + "vscode": { + "interpreter": { + "hash": "02e23b522f8c3795158421909d41ced4ef90521258d58d1c53bee449d96f71e3" + } + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/nb/parse_cube.ipynb b/nb/parse_cube.ipynb new file mode 100644 index 0000000..1ade731 --- /dev/null +++ b/nb/parse_cube.ipynb @@ -0,0 +1,721 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# only if you get an error from below\n", + "# from pystatis import init_config\n", + "# init_config()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "logging.basicConfig(level=logging.INFO)\n", + "\n", + "import pandas as pd\n", + "\n", + "from pystatis.cube import parse_cube, rename_axes\n", + "from pystatis.http_helper import get_data_from_endpoint" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Download a cube file" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `get_cubefile()` function will download the cube as csv cubefile and return the data as string." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "params = {\"name\": \"47414BJ002\", \"area\": \"all\", \"values\": \"true\", \"metadata\": \"true\", \"additionals\": \"false\"}\n", + "data = get_data_from_endpoint(\"data\", \"cubefile\", params)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(str, 84324)" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(data), len(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['* Der Benutzer DEI6I4B3UW der Benutzergruppe DE0142 hat am 16.09.2022 um 23:24:58 diesen Export angestossen.',\n", + " 'K;DQ;FACH-SCHL;GHH-ART;GHM-WERTE-JN;GENESIS-VBD;REGIOSTAT;EU-VBD;\"mit Werten\"',\n", + " 'D;47414BJ002;;N;N;N;N',\n", + " 'K;DQ-ERH;FACH-SCHL',\n", + " 'D;47414',\n", + " 'K;DQA;NAME;RHF-BSR;RHF-ACHSE',\n", + " 'D;DINSG;1;1',\n", + " 'D;WZ08N7;2;2',\n", + " 'D;WERTE4;3;3',\n", + " 'K;DQZ;NAME;ZI-RHF-BSR;ZI-RHF-ACHSE',\n", + " 'D;JAHR;4;4',\n", + " 'K;DQI;NAME;ME-NAME;DST;TYP;NKM-STELLEN;GHH-ART;GHM-WERTE-JN',\n", + " 'D;UMS103;2015=100;FEST;PROZENT;1;;N',\n", + " 'K;QEI;FACH-SCHL;FACH-SCHL;FACH-SCHL;ZI-WERT;WERT;QUALITAET;GESPERRT;WERT-VERFAELSCHT',\n", + " 'D;DG;WZ08-49-01;NOMINAL;2015;100.0;e;;0.0',\n", + " 'D;DG;WZ08-49-01;NOMINAL;2016;99.3;e;;0.0',\n", + " 'D;DG;WZ08-49-01;NOMINAL;2017;105.7;e;;0.0',\n", + " 'D;DG;WZ08-49-01;NOMINAL;2018;111.6;e;;0.0',\n", + " 'D;DG;WZ08-49-01;NOMINAL;2019;115.6;e;;0.0',\n", + " 'D;DG;WZ08-49-01;NOMINAL;2020;96.0;e;;0.0']" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data.splitlines()[:20]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Parsing the cube file\n", + "\n", + "The `parse_cube(data)` function can parse the raw string and return a dictionary with the different headers and the data section. Data is stored as pandas `DataFrame`." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "cube = parse_cube(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'DQ': FACH-SCHL GHH-ART GHM-WERTE-JN GENESIS-VBD REGIOSTAT EU-VBD\n", + " 0 47414BJ002 N N N N,\n", + " 'DQ-ERH': FACH-SCHL\n", + " 0 47414,\n", + " 'DQA': NAME RHF-BSR RHF-ACHSE\n", + " 0 DINSG 1 1\n", + " 1 WZ08N7 2 2\n", + " 2 WERTE4 3 3,\n", + " 'DQZ': NAME ZI-RHF-BSR ZI-RHF-ACHSE\n", + " 0 JAHR 4 4,\n", + " 'DQI': NAME ME-NAME DST TYP NKM-STELLEN GHH-ART GHM-WERTE-JN\n", + " 0 UMS103 2015=100 FEST PROZENT 1 N,\n", + " 'QEI': FACH-SCHL-1 FACH-SCHL-2 FACH-SCHL-3 ZI-WERT UMS103_WERT UMS103_QUALITAET \\\n", + " 0 DG WZ08-49-01 NOMINAL 2015 100.0 e \n", + " 1 DG WZ08-49-01 NOMINAL 2016 99.3 e \n", + " 2 DG WZ08-49-01 NOMINAL 2017 105.7 e \n", + " 3 DG WZ08-49-01 NOMINAL 2018 111.6 e \n", + " 4 DG WZ08-49-01 NOMINAL 2019 115.6 e \n", + " ... ... ... ... ... ... ... \n", + " 2151 DG WZ08-N REAL 2017 108.4 e \n", + " 2152 DG WZ08-N REAL 2018 110.6 e \n", + " 2153 DG WZ08-N REAL 2019 110.8 e \n", + " 2154 DG WZ08-N REAL 2020 94.1 e \n", + " 2155 DG WZ08-N REAL 2021 101.2 p \n", + " \n", + " UMS103_GESPERRT UMS103_WERT-VERFAELSCHT \n", + " 0 0.0 \n", + " 1 0.0 \n", + " 2 0.0 \n", + " 3 0.0 \n", + " 4 0.0 \n", + " ... ... ... \n", + " 2151 0.0 \n", + " 2152 0.0 \n", + " 2153 0.0 \n", + " 2154 0.0 \n", + " 2155 0.0 \n", + " \n", + " [2156 rows x 8 columns]}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cube" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
FACH-SCHL-1FACH-SCHL-2FACH-SCHL-3ZI-WERTUMS103_WERTUMS103_QUALITAETUMS103_GESPERRTUMS103_WERT-VERFAELSCHT
0DGWZ08-49-01NOMINAL2015100.0e0.0
1DGWZ08-49-01NOMINAL201699.3e0.0
2DGWZ08-49-01NOMINAL2017105.7e0.0
3DGWZ08-49-01NOMINAL2018111.6e0.0
4DGWZ08-49-01NOMINAL2019115.6e0.0
...........................
2151DGWZ08-NREAL2017108.4e0.0
2152DGWZ08-NREAL2018110.6e0.0
2153DGWZ08-NREAL2019110.8e0.0
2154DGWZ08-NREAL202094.1e0.0
2155DGWZ08-NREAL2021101.2p0.0
\n", + "

2156 rows × 8 columns

\n", + "
" + ], + "text/plain": [ + " FACH-SCHL-1 FACH-SCHL-2 FACH-SCHL-3 ZI-WERT UMS103_WERT UMS103_QUALITAET \\\n", + "0 DG WZ08-49-01 NOMINAL 2015 100.0 e \n", + "1 DG WZ08-49-01 NOMINAL 2016 99.3 e \n", + "2 DG WZ08-49-01 NOMINAL 2017 105.7 e \n", + "3 DG WZ08-49-01 NOMINAL 2018 111.6 e \n", + "4 DG WZ08-49-01 NOMINAL 2019 115.6 e \n", + "... ... ... ... ... ... ... \n", + "2151 DG WZ08-N REAL 2017 108.4 e \n", + "2152 DG WZ08-N REAL 2018 110.6 e \n", + "2153 DG WZ08-N REAL 2019 110.8 e \n", + "2154 DG WZ08-N REAL 2020 94.1 e \n", + "2155 DG WZ08-N REAL 2021 101.2 p \n", + "\n", + " UMS103_GESPERRT UMS103_WERT-VERFAELSCHT \n", + "0 0.0 \n", + "1 0.0 \n", + "2 0.0 \n", + "3 0.0 \n", + "4 0.0 \n", + "... ... ... \n", + "2151 0.0 \n", + "2152 0.0 \n", + "2153 0.0 \n", + "2154 0.0 \n", + "2155 0.0 \n", + "\n", + "[2156 rows x 8 columns]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cube[\"QEI\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
NAMERHF-BSRRHF-ACHSE
0DINSG11
1WZ08N722
2WERTE433
\n", + "
" + ], + "text/plain": [ + " NAME RHF-BSR RHF-ACHSE\n", + "0 DINSG 1 1\n", + "1 WZ08N7 2 2\n", + "2 WERTE4 3 3" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cube[\"DQA\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Renaming Axes\n", + "\n", + "The `rename_axes(cube)` function can rename the columns of a data frame according to the metadata delivered with the cube file. `cube` has to be a dictionary as is returned by `parse_cube()`." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
DINSGWZ08N7WERTE4JAHRUMS103_WERTUMS103_QUALITAETUMS103_GESPERRTUMS103_WERT-VERFAELSCHT
0DGWZ08-49-01NOMINAL2015100.0e0.0
1DGWZ08-49-01NOMINAL201699.3e0.0
2DGWZ08-49-01NOMINAL2017105.7e0.0
3DGWZ08-49-01NOMINAL2018111.6e0.0
4DGWZ08-49-01NOMINAL2019115.6e0.0
...........................
2151DGWZ08-NREAL2017108.4e0.0
2152DGWZ08-NREAL2018110.6e0.0
2153DGWZ08-NREAL2019110.8e0.0
2154DGWZ08-NREAL202094.1e0.0
2155DGWZ08-NREAL2021101.2p0.0
\n", + "

2156 rows × 8 columns

\n", + "
" + ], + "text/plain": [ + " DINSG WZ08N7 WERTE4 JAHR UMS103_WERT UMS103_QUALITAET \\\n", + "0 DG WZ08-49-01 NOMINAL 2015 100.0 e \n", + "1 DG WZ08-49-01 NOMINAL 2016 99.3 e \n", + "2 DG WZ08-49-01 NOMINAL 2017 105.7 e \n", + "3 DG WZ08-49-01 NOMINAL 2018 111.6 e \n", + "4 DG WZ08-49-01 NOMINAL 2019 115.6 e \n", + "... ... ... ... ... ... ... \n", + "2151 DG WZ08-N REAL 2017 108.4 e \n", + "2152 DG WZ08-N REAL 2018 110.6 e \n", + "2153 DG WZ08-N REAL 2019 110.8 e \n", + "2154 DG WZ08-N REAL 2020 94.1 e \n", + "2155 DG WZ08-N REAL 2021 101.2 p \n", + "\n", + " UMS103_GESPERRT UMS103_WERT-VERFAELSCHT \n", + "0 0.0 \n", + "1 0.0 \n", + "2 0.0 \n", + "3 0.0 \n", + "4 0.0 \n", + "... ... ... \n", + "2151 0.0 \n", + "2152 0.0 \n", + "2153 0.0 \n", + "2154 0.0 \n", + "2155 0.0 \n", + "\n", + "[2156 rows x 8 columns]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rename_axes(cube)[\"QEI\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array(['2015', '2016', '2017', '2018', '2019', '2020', '2021'],\n", + " dtype=object)" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rename_axes(cube)[\"QEI\"][\"JAHR\"].unique()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.7 ('.venv': poetry)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + }, + "vscode": { + "interpreter": { + "hash": "02e23b522f8c3795158421909d41ced4ef90521258d58d1c53bee449d96f71e3" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/nb/profile.ipynb b/nb/profile.ipynb new file mode 100644 index 0000000..cf6c624 --- /dev/null +++ b/nb/profile.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "logging.basicConfig(level=logging.INFO)\n", + "\n", + "from pystatis import change_password, remove_result" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `profile` module allows you to change your password (`change_password`) and use the (unavailable) `remove_result` functionality, listed in the [documentation under 2.7.2](https://www-genesis.destatis.de/genesis/misc/GENESIS-Webservices_Einfuehrung.pdf)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# change your password\n", + "change_password(new_password=DoNotUseThisAccidentally)\n", + "\n", + "# use remove_result functionality\n", + "destatis_name_code = \"42131-0001\"\n", + "remove_result(name=destatis_name_code)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.7 ('.venv': poetry)", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.9.7" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "02e23b522f8c3795158421909d41ced4ef90521258d58d1c53bee449d96f71e3" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/nb/table.ipynb b/nb/table.ipynb new file mode 100644 index 0000000..b8e37cf --- /dev/null +++ b/nb/table.ipynb @@ -0,0 +1,556 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "165da3a1", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "import logging\n", + "logging.basicConfig(level=logging.INFO)\n", + "\n", + "from pystatis import Table" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "5d25c79a", + "metadata": {}, + "outputs": [], + "source": [ + "t = Table(name=\"21311-0001\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "632fc783", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:pystatis.cache:Data was successfully cached under C:\\Users\\micha\\.pystatis\\data\\21311-0001\\5d17194a9264f364cb40\\20220922.txt.\n", + "INFO:pystatis.http_helper:Code 0 : erfolgreich\n" + ] + } + ], + "source": [ + "t.get_data()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f5f1aded", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'21311-0001'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t.name" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "8fede338", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Statistik_Code;Statistik_Label;Zeit_Code;Zeit_Label;Zeit;1_Merkmal_Code;1_Merkmal_Label;1_Auspraegung_Code;1_Auspraegung_Label;2_Merkmal_Code;2_Merkmal_Label;2_Auspraegung_Code;2_Auspraegung_Label;3_Merkmal_Code;3_Merkmal_Label;3_Auspraegung_Code;3_Auspraegung_Label;BIL002__Studierende__Anzahl\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1998/99;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;907403\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1998/99;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;727254\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1998/99;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;1634657\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1998/99;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;92321\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1998/99;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;73673\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1998/99;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;165994\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1998/99;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;999724\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1998/99;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;800927\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1998/99;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;1800651\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1999/00;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;872178\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1999/00;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;723246\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1999/00;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;1595424\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1999/00;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;95460\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1999/00;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;79605\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1999/00;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;175065\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1999/00;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;967638\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1999/00;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;802851\\n21311;Statistik der Studenten;SEMEST;Semester;WS 1999/00;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;1770489\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2000/01;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;870016\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2000/01;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;741820\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2000/01;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;1611836\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2000/01;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;99906\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2000/01;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;87121\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2000/01;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;187027\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2000/01;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;969922\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2000/01;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;828941\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2000/01;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;1798863\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2001/02;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;887462\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2001/02;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;774628\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2001/02;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;1662090\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2001/02;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;107831\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2001/02;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;98410\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2001/02;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;206241\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2001/02;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;995293\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2001/02;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;873038\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2001/02;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;1868331\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2002/03;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;903218\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2002/03;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;808567\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2002/03;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;1711785\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2002/03;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;117205\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2002/03;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;109821\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2002/03;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;227026\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2002/03;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1020423\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2002/03;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;918388\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2002/03;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;1938811\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2003/04;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;935718\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2003/04;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;837611\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2003/04;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;1773329\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2003/04;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;125826\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2003/04;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;120310\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2003/04;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;246136\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2003/04;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1061544\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2003/04;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;957921\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2003/04;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2019465\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2004/05;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;901979\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2004/05;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;814795\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2004/05;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;1716774\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2004/05;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;124220\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2004/05;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;122114\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2004/05;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;246334\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2004/05;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1026199\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2004/05;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;936909\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2004/05;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;1963108\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2005/06;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;912696\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2005/06;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;824712\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2005/06;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;1737408\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2005/06;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;124447\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2005/06;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;123910\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2005/06;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;248357\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2005/06;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1037143\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2005/06;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;948622\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2005/06;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;1985765\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2006/07;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;909740\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2006/07;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;822934\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2006/07;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;1732674\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2006/07;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;122923\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2006/07;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;123446\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2006/07;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;246369\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2006/07;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1032663\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2006/07;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;946380\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2006/07;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;1979043\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2007/08;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;898061\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2007/08;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;809738\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2007/08;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;1707799\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2007/08;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;116700\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2007/08;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;116906\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2007/08;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;233606\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2007/08;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1014761\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2007/08;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;926644\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2007/08;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;1941405\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2008/09;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;938552\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2008/09;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;847612\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2008/09;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;1786164\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2008/09;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;119254\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2008/09;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;119889\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2008/09;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;239143\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2008/09;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1057806\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2008/09;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;967501\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2008/09;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2025307\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2009/10;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;984097\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2009/10;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;892306\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2009/10;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;1876403\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2009/10;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;122353\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2009/10;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;122422\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2009/10;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;244775\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2009/10;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1106450\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2009/10;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;1014728\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2009/10;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2121178\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2010/11;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;1031086\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2010/11;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;934176\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2010/11;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;1965262\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2010/11;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;126399\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2010/11;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;125633\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2010/11;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;252032\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2010/11;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1157485\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2010/11;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;1059809\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2010/11;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2217294\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2011/12;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;1122200\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2011/12;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;993482\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2011/12;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;2115682\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2011/12;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;133172\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2011/12;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;132120\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2011/12;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;265292\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2011/12;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1255372\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2011/12;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;1125602\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2011/12;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2380974\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2012/13;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;1171894\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2012/13;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;1045314\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2012/13;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;2217208\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2012/13;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;142123\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2012/13;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;140078\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2012/13;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;282201\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2012/13;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1314017\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2012/13;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;1185392\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2012/13;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2499409\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2013/14;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;1218965\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2013/14;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;1096566\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2013/14;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;2315531\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2013/14;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;152675\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2013/14;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;148675\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2013/14;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;301350\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2013/14;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1371640\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2013/14;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;1245241\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2013/14;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2616881\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2014/15;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;1245029\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2014/15;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;1132312\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2014/15;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;2377341\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2014/15;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;163505\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2014/15;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;158064\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2014/15;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;321569\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2014/15;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1408534\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2014/15;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;1290376\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2014/15;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2698910\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2015/16;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;1260203\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2015/16;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;1157291\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2015/16;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;2417494\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2015/16;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;173923\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2015/16;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;166382\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2015/16;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;340305\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2015/16;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1434126\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2015/16;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;1323673\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2015/16;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2757799\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2016/17;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;1269166\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2016/17;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;1178949\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2016/17;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;2448115\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2016/17;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;184459\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2016/17;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;174436\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2016/17;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;358895\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2016/17;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1453625\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2016/17;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;1353385\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2016/17;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2807010\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2017/18;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;1270098\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2017/18;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;1200297\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2017/18;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;2470395\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2017/18;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;194545\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2017/18;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;180038\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2017/18;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;374583\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2017/18;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1464643\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2017/18;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;1380335\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2017/18;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2844978\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2018/19;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;1258281\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2018/19;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;1215276\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2018/19;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;2473557\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2018/19;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;207697\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2018/19;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;186968\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2018/19;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;394665\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2018/19;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1465978\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2018/19;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;1402244\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2018/19;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2868222\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2019/20;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;1246852\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2019/20;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;1232596\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2019/20;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;2479448\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2019/20;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;218015\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2019/20;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;193586\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2019/20;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;411601\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2019/20;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1464867\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2019/20;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;1426182\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2019/20;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2891049\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2020/21;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;1253399\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2020/21;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;1274309\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2020/21;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;2527708\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2020/21;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;222967\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2020/21;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;193470\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2020/21;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;416437\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2020/21;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1476366\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2020/21;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;1467779\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2020/21;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2944145\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2021/22;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESM;männlich;1231256\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2021/22;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;GESW;weiblich;1270095\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2021/22;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATD;Deutsche;GES;Geschlecht;;Insgesamt;2501351\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2021/22;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESM;männlich;235026\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2021/22;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;GESW;weiblich;205538\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2021/22;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;NATA;Ausländer;GES;Geschlecht;;Insgesamt;440564\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2021/22;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESM;männlich;1466282\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2021/22;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;GESW;weiblich;1475633\\n21311;Statistik der Studenten;SEMEST;Semester;WS 2021/22;DINSG;Deutschland insgesamt;DG;Deutschland;NAT;Nationalität;;Insgesamt;GES;Geschlecht;;Insgesamt;2941915\\n'" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t.raw_data" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "874bbbb9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Statistik_CodeStatistik_LabelZeit_CodeZeit_LabelZeit1_Merkmal_Code1_Merkmal_Label1_Auspraegung_Code1_Auspraegung_Label2_Merkmal_Code2_Merkmal_Label2_Auspraegung_Code2_Auspraegung_Label3_Merkmal_Code3_Merkmal_Label3_Auspraegung_Code3_Auspraegung_LabelBIL002__Studierende__Anzahl
021311Statistik der StudentenSEMESTSemesterWS 1998/99DINSGDeutschland insgesamtDGDeutschlandNATNationalitätNATDDeutscheGESGeschlechtGESMmännlich907403
121311Statistik der StudentenSEMESTSemesterWS 1998/99DINSGDeutschland insgesamtDGDeutschlandNATNationalitätNATDDeutscheGESGeschlechtGESWweiblich727254
221311Statistik der StudentenSEMESTSemesterWS 1998/99DINSGDeutschland insgesamtDGDeutschlandNATNationalitätNATDDeutscheGESGeschlechtNaNInsgesamt1634657
321311Statistik der StudentenSEMESTSemesterWS 1998/99DINSGDeutschland insgesamtDGDeutschlandNATNationalitätNATAAusländerGESGeschlechtGESMmännlich92321
421311Statistik der StudentenSEMESTSemesterWS 1998/99DINSGDeutschland insgesamtDGDeutschlandNATNationalitätNATAAusländerGESGeschlechtGESWweiblich73673
.........................................................
21121311Statistik der StudentenSEMESTSemesterWS 2021/22DINSGDeutschland insgesamtDGDeutschlandNATNationalitätNATAAusländerGESGeschlechtGESWweiblich205538
21221311Statistik der StudentenSEMESTSemesterWS 2021/22DINSGDeutschland insgesamtDGDeutschlandNATNationalitätNATAAusländerGESGeschlechtNaNInsgesamt440564
21321311Statistik der StudentenSEMESTSemesterWS 2021/22DINSGDeutschland insgesamtDGDeutschlandNATNationalitätNaNInsgesamtGESGeschlechtGESMmännlich1466282
21421311Statistik der StudentenSEMESTSemesterWS 2021/22DINSGDeutschland insgesamtDGDeutschlandNATNationalitätNaNInsgesamtGESGeschlechtGESWweiblich1475633
21521311Statistik der StudentenSEMESTSemesterWS 2021/22DINSGDeutschland insgesamtDGDeutschlandNATNationalitätNaNInsgesamtGESGeschlechtNaNInsgesamt2941915
\n", + "

216 rows × 18 columns

\n", + "
" + ], + "text/plain": [ + " Statistik_Code Statistik_Label Zeit_Code Zeit_Label Zeit \\\n", + "0 21311 Statistik der Studenten SEMEST Semester WS 1998/99 \n", + "1 21311 Statistik der Studenten SEMEST Semester WS 1998/99 \n", + "2 21311 Statistik der Studenten SEMEST Semester WS 1998/99 \n", + "3 21311 Statistik der Studenten SEMEST Semester WS 1998/99 \n", + "4 21311 Statistik der Studenten SEMEST Semester WS 1998/99 \n", + ".. ... ... ... ... ... \n", + "211 21311 Statistik der Studenten SEMEST Semester WS 2021/22 \n", + "212 21311 Statistik der Studenten SEMEST Semester WS 2021/22 \n", + "213 21311 Statistik der Studenten SEMEST Semester WS 2021/22 \n", + "214 21311 Statistik der Studenten SEMEST Semester WS 2021/22 \n", + "215 21311 Statistik der Studenten SEMEST Semester WS 2021/22 \n", + "\n", + " 1_Merkmal_Code 1_Merkmal_Label 1_Auspraegung_Code \\\n", + "0 DINSG Deutschland insgesamt DG \n", + "1 DINSG Deutschland insgesamt DG \n", + "2 DINSG Deutschland insgesamt DG \n", + "3 DINSG Deutschland insgesamt DG \n", + "4 DINSG Deutschland insgesamt DG \n", + ".. ... ... ... \n", + "211 DINSG Deutschland insgesamt DG \n", + "212 DINSG Deutschland insgesamt DG \n", + "213 DINSG Deutschland insgesamt DG \n", + "214 DINSG Deutschland insgesamt DG \n", + "215 DINSG Deutschland insgesamt DG \n", + "\n", + " 1_Auspraegung_Label 2_Merkmal_Code 2_Merkmal_Label 2_Auspraegung_Code \\\n", + "0 Deutschland NAT Nationalität NATD \n", + "1 Deutschland NAT Nationalität NATD \n", + "2 Deutschland NAT Nationalität NATD \n", + "3 Deutschland NAT Nationalität NATA \n", + "4 Deutschland NAT Nationalität NATA \n", + ".. ... ... ... ... \n", + "211 Deutschland NAT Nationalität NATA \n", + "212 Deutschland NAT Nationalität NATA \n", + "213 Deutschland NAT Nationalität NaN \n", + "214 Deutschland NAT Nationalität NaN \n", + "215 Deutschland NAT Nationalität NaN \n", + "\n", + " 2_Auspraegung_Label 3_Merkmal_Code 3_Merkmal_Label 3_Auspraegung_Code \\\n", + "0 Deutsche GES Geschlecht GESM \n", + "1 Deutsche GES Geschlecht GESW \n", + "2 Deutsche GES Geschlecht NaN \n", + "3 Ausländer GES Geschlecht GESM \n", + "4 Ausländer GES Geschlecht GESW \n", + ".. ... ... ... ... \n", + "211 Ausländer GES Geschlecht GESW \n", + "212 Ausländer GES Geschlecht NaN \n", + "213 Insgesamt GES Geschlecht GESM \n", + "214 Insgesamt GES Geschlecht GESW \n", + "215 Insgesamt GES Geschlecht NaN \n", + "\n", + " 3_Auspraegung_Label BIL002__Studierende__Anzahl \n", + "0 männlich 907403 \n", + "1 weiblich 727254 \n", + "2 Insgesamt 1634657 \n", + "3 männlich 92321 \n", + "4 weiblich 73673 \n", + ".. ... ... \n", + "211 weiblich 205538 \n", + "212 Insgesamt 440564 \n", + "213 männlich 1466282 \n", + "214 weiblich 1475633 \n", + "215 Insgesamt 2941915 \n", + "\n", + "[216 rows x 18 columns]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t.data" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "81d27994", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'Copyright': '© Statistisches Bundesamt (Destatis), 2022',\n", + " 'Ident': {'Method': 'table', 'Service': 'metadata'},\n", + " 'Object': {'Code': '21311-0001',\n", + " 'Content': 'Studierende: Deutschland, Semester, Nationalität,\\n'\n", + " 'Geschlecht',\n", + " 'Structure': {'Columns': [{'Code': 'NAT',\n", + " 'Content': 'Nationalität',\n", + " 'Selected': None,\n", + " 'Structure': [{'Code': 'GES',\n", + " 'Content': 'Geschlecht',\n", + " 'Selected': None,\n", + " 'Structure': None,\n", + " 'Type': 'Merkmal',\n", + " 'Updated': 'see parent',\n", + " 'Values': None}],\n", + " 'Type': 'Merkmal',\n", + " 'Updated': 'see parent',\n", + " 'Values': None}],\n", + " 'Head': {'Code': '21311',\n", + " 'Content': 'Statistik der Studenten',\n", + " 'Selected': None,\n", + " 'Structure': [{'Code': 'DINSG',\n", + " 'Content': 'Deutschland '\n", + " 'insgesamt',\n", + " 'Selected': '1',\n", + " 'Structure': [{'Code': 'BIL002',\n", + " 'Content': 'Studierende',\n", + " 'Selected': None,\n", + " 'Structure': None,\n", + " 'Type': 'Merkmal',\n", + " 'Updated': 'see '\n", + " 'parent',\n", + " 'Values': None}],\n", + " 'Type': 'Merkmal',\n", + " 'Updated': 'see parent',\n", + " 'Values': '1'}],\n", + " 'Type': 'Statistik',\n", + " 'Updated': 'see parent',\n", + " 'Values': None},\n", + " 'Rows': [{'Code': 'SEMEST',\n", + " 'Content': 'Semester',\n", + " 'Selected': None,\n", + " 'Structure': None,\n", + " 'Type': 'Merkmal',\n", + " 'Updated': 'see parent',\n", + " 'Values': None}],\n", + " 'Subheading': None,\n", + " 'Subtitel': None},\n", + " 'Time': {'From': 'WS 1998/99', 'To': 'WS 2021/22'},\n", + " 'Updated': '13.08.2013 13:41:54h',\n", + " 'Valid': 'false'},\n", + " 'Parameter': {'area': 'Alle',\n", + " 'language': 'de',\n", + " 'name': '21311-0001',\n", + " 'password': '********************',\n", + " 'username': '********************'},\n", + " 'Status': {'Code': 0, 'Content': 'erfolgreich', 'Type': 'Information'}}\n" + ] + } + ], + "source": [ + "from pprint import pprint\n", + "\n", + "pprint(t.metadata)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.7 ('.venv': poetry)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + }, + "vscode": { + "interpreter": { + "hash": "02e23b522f8c3795158421909d41ced4ef90521258d58d1c53bee449d96f71e3" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..0a3b3e8 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,2549 @@ +[[package]] +name = "appnope" +version = "0.1.3" +description = "Disable App Nap on macOS >= 10.9" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "argon2-cffi" +version = "21.3.0" +description = "The secure Argon2 password hashing algorithm." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +argon2-cffi-bindings = "*" + +[package.extras] +dev = ["pre-commit", "cogapp", "tomli", "coverage[toml] (>=5.0.2)", "hypothesis", "pytest", "sphinx", "sphinx-notfound-page", "furo"] +docs = ["sphinx", "sphinx-notfound-page", "furo"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pytest"] + +[[package]] +name = "argon2-cffi-bindings" +version = "21.2.0" +description = "Low-level CFFI bindings for Argon2" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +cffi = ">=1.0.1" + +[package.extras] +dev = ["pytest", "cogapp", "pre-commit", "wheel"] +tests = ["pytest"] + +[[package]] +name = "astroid" +version = "2.12.10" +description = "An abstract syntax tree for Python with inference support." +category = "dev" +optional = false +python-versions = ">=3.7.2" + +[package.dependencies] +lazy-object-proxy = ">=1.4.0" +typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} +wrapt = [ + {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, + {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, +] + +[[package]] +name = "asttokens" +version = "2.0.8" +description = "Annotate AST trees with source code positions" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +six = "*" + +[package.extras] +test = ["astroid (<=2.5.3)", "pytest"] + +[[package]] +name = "attrs" +version = "22.1.0" +description = "Classes Without Boilerplate" +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.extras] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] +docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "cloudpickle"] + +[[package]] +name = "backcall" +version = "0.2.0" +description = "Specifications for callback functions passed in to an API" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "bandit" +version = "1.7.4" +description = "Security oriented static analyser for python code." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} +GitPython = ">=1.0.1" +PyYAML = ">=5.3.1" +stevedore = ">=1.20.0" + +[package.extras] +test = ["coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml", "beautifulsoup4 (>=4.8.0)", "pylint (==1.9.4)"] +toml = ["toml"] +yaml = ["pyyaml"] + +[[package]] +name = "beautifulsoup4" +version = "4.11.1" +description = "Screen-scraping library" +category = "dev" +optional = false +python-versions = ">=3.6.0" + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +html5lib = ["html5lib"] +lxml = ["lxml"] + +[[package]] +name = "black" +version = "22.10.0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} +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 = "bleach" +version = "5.0.1" +description = "An easy safelist-based HTML-sanitizing tool." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +six = ">=1.9.0" +webencodings = "*" + +[package.extras] +css = ["tinycss2 (>=1.1.0,<1.2)"] +dev = ["build (==0.8.0)", "flake8 (==4.0.1)", "hashin (==0.17.0)", "pip-tools (==6.6.2)", "pytest (==7.1.2)", "Sphinx (==4.3.2)", "tox (==3.25.0)", "twine (==4.0.1)", "wheel (==0.37.1)", "black (==22.3.0)", "mypy (==0.961)"] + +[[package]] +name = "certifi" +version = "2022.9.24" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "cffi" +version = "1.15.1" +description = "Foreign Function Interface for Python calling C code." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +pycparser = "*" + +[[package]] +name = "cfgv" +version = "3.3.1" +description = "Validate configuration and produce human readable error messages." +category = "dev" +optional = false +python-versions = ">=3.6.1" + +[[package]] +name = "charset-normalizer" +version = "2.1.1" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.6.0" + +[package.extras] +unicode_backport = ["unicodedata2"] + +[[package]] +name = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.5" +description = "Cross-platform colored terminal text." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "coverage" +version = "6.5.0" +description = "Code coverage measurement for Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "debugpy" +version = "1.6.3" +description = "An implementation of the Debug Adapter Protocol for Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +category = "dev" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "dill" +version = "0.3.5.1" +description = "serialize all of python" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" + +[package.extras] +graph = ["objgraph (>=1.7.2)"] + +[[package]] +name = "distlib" +version = "0.3.6" +description = "Distribution utilities" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "dparse" +version = "0.6.2" +description = "A parser for Python dependency files" +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +packaging = "*" +toml = "*" + +[package.extras] +pipenv = ["pipenv"] +conda = ["pyyaml"] + +[[package]] +name = "entrypoints" +version = "0.4" +description = "Discover and load entry points from installed packages." +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "executing" +version = "1.1.1" +description = "Get the currently executing AST node of a frame, and other information" +category = "dev" +optional = false +python-versions = "*" + +[package.extras] +tests = ["rich", "littleutils", "pytest", "asttokens"] + +[[package]] +name = "fastjsonschema" +version = "2.16.2" +description = "Fastest Python implementation of JSON schema" +category = "dev" +optional = false +python-versions = "*" + +[package.extras] +devel = ["colorama", "jsonschema", "json-spec", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] + +[[package]] +name = "filelock" +version = "3.8.0" +description = "A platform independent file lock." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo (>=2022.6.21)", "sphinx (>=5.1.1)", "sphinx-autodoc-typehints (>=1.19.1)"] +testing = ["covdefaults (>=2.2)", "coverage (>=6.4.2)", "pytest (>=7.1.2)", "pytest-cov (>=3)", "pytest-timeout (>=2.1)"] + +[[package]] +name = "flake8" +version = "4.0.1" +description = "the modular source code checker: pep8 pyflakes and co" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +mccabe = ">=0.6.0,<0.7.0" +pycodestyle = ">=2.8.0,<2.9.0" +pyflakes = ">=2.4.0,<2.5.0" + +[[package]] +name = "flake8-docstrings" +version = "1.6.0" +description = "Extension for flake8 which uses pydocstyle to check docstrings" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = ">=3" +pydocstyle = ">=2.1" + +[[package]] +name = "gitdb" +version = "4.0.9" +description = "Git Object Database" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.28" +description = "GitPython is a python library used to interact with Git repositories" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[[package]] +name = "identify" +version = "2.5.6" +description = "File identification library for Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "importlib-metadata" +version = "5.0.0" +description = "Read metadata from Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["sphinx (>=3.5)", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "furo", "jaraco.tidelift (>=1.4)"] +perf = ["ipython"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "flake8 (<5)", "pytest-cov", "pytest-enabler (>=1.3)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] + +[[package]] +name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "ipykernel" +version = "6.16.0" +description = "IPython Kernel for Jupyter" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +appnope = {version = "*", markers = "platform_system == \"Darwin\""} +debugpy = ">=1.0" +ipython = ">=7.23.1" +jupyter-client = ">=6.1.12" +matplotlib-inline = ">=0.1" +nest-asyncio = "*" +packaging = "*" +psutil = "*" +pyzmq = ">=17" +tornado = ">=6.1" +traitlets = ">=5.1.0" + +[package.extras] +test = ["flaky", "ipyparallel", "pre-commit", "pytest-cov", "pytest-timeout", "pytest (>=6.0)"] + +[[package]] +name = "ipython" +version = "8.5.0" +description = "IPython: Productive Interactive Computing" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +appnope = {version = "*", markers = "sys_platform == \"darwin\""} +backcall = "*" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +decorator = "*" +jedi = ">=0.16" +matplotlib-inline = "*" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} +pickleshare = "*" +prompt-toolkit = ">3.0.1,<3.1.0" +pygments = ">=2.4.0" +stack-data = "*" +traitlets = ">=5" + +[package.extras] +all = ["black", "Sphinx (>=1.3)", "ipykernel", "nbconvert", "nbformat", "ipywidgets", "notebook", "ipyparallel", "qtconsole", "pytest (<7.1)", "pytest-asyncio", "testpath", "curio", "matplotlib (!=3.2.0)", "numpy (>=1.19)", "pandas", "trio"] +black = ["black"] +doc = ["Sphinx (>=1.3)"] +kernel = ["ipykernel"] +nbconvert = ["nbconvert"] +nbformat = ["nbformat"] +notebook = ["ipywidgets", "notebook"] +parallel = ["ipyparallel"] +qtconsole = ["qtconsole"] +test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] +test_extra = ["pytest (<7.1)", "pytest-asyncio", "testpath", "curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pandas", "trio"] + +[[package]] +name = "ipython-genutils" +version = "0.2.0" +description = "Vestigial utilities from IPython" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "ipywidgets" +version = "8.0.2" +description = "Jupyter interactive widgets" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +ipykernel = ">=4.5.1" +ipython = ">=6.1.0" +jupyterlab-widgets = ">=3.0,<4.0" +traitlets = ">=4.3.1" +widgetsnbextension = ">=4.0,<5.0" + +[package.extras] +test = ["jsonschema", "pytest (>=3.6.0)", "pytest-cov", "pytz"] + +[[package]] +name = "isort" +version = "5.10.1" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.6.1,<4.0" + +[package.extras] +pipfile_deprecated_finder = ["pipreqs", "requirementslib"] +requirements_deprecated_finder = ["pipreqs", "pip-api"] +colors = ["colorama (>=0.4.3,<0.5.0)"] +plugins = ["setuptools"] + +[[package]] +name = "jedi" +version = "0.18.1" +description = "An autocompletion tool for Python that can be used for text editors." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +parso = ">=0.8.0,<0.9.0" + +[package.extras] +qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] +testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"] + +[[package]] +name = "jinja2" +version = "3.1.2" +description = "A very fast and expressive template engine." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "jsonschema" +version = "4.16.0" +description = "An implementation of JSON Schema validation for Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +attrs = ">=17.4.0" +pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" + +[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 = "jupyter" +version = "1.0.0" +description = "Jupyter metapackage. Install all the Jupyter components in one go." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +ipykernel = "*" +ipywidgets = "*" +jupyter-console = "*" +nbconvert = "*" +notebook = "*" +qtconsole = "*" + +[[package]] +name = "jupyter-client" +version = "7.3.5" +description = "Jupyter protocol implementation and client libraries" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +entrypoints = "*" +jupyter-core = ">=4.9.2" +nest-asyncio = ">=1.5.4" +python-dateutil = ">=2.8.2" +pyzmq = ">=23.0" +tornado = ">=6.2" +traitlets = "*" + +[package.extras] +doc = ["ipykernel", "myst-parser", "sphinx-rtd-theme", "sphinx (>=1.3.6)", "sphinxcontrib-github-alt"] +test = ["codecov", "coverage", "ipykernel (>=6.5)", "ipython", "mypy", "pre-commit", "pytest", "pytest-asyncio (>=0.18)", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "jupyter-console" +version = "6.4.4" +description = "Jupyter terminal console" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +ipykernel = "*" +ipython = "*" +jupyter-client = ">=7.0.0" +prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" +pygments = "*" + +[package.extras] +test = ["pexpect"] + +[[package]] +name = "jupyter-core" +version = "4.11.1" +description = "Jupyter core package. A base package on which Jupyter projects rely." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +pywin32 = {version = ">=1.0", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} +traitlets = "*" + +[package.extras] +test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "jupyterlab-pygments" +version = "0.2.2" +description = "Pygments theme using JupyterLab CSS variables" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "jupyterlab-widgets" +version = "3.0.3" +description = "Jupyter interactive widgets for JupyterLab" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "lazy-object-proxy" +version = "1.7.1" +description = "A fast and thorough lazy object proxy." +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "markupsafe" +version = "2.1.1" +description = "Safely add untrusted strings to HTML/XML markup." +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "matplotlib-inline" +version = "0.1.6" +description = "Inline Matplotlib backend for Jupyter" +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +traitlets = "*" + +[[package]] +name = "mccabe" +version = "0.6.1" +description = "McCabe checker, plugin for flake8" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "mistune" +version = "2.0.4" +description = "A sane Markdown parser with useful plugins and renderers" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "mypy" +version = "0.942" +description = "Optional static typing for Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +mypy-extensions = ">=0.4.3" +tomli = ">=1.1.0" +typing-extensions = ">=3.10" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +python2 = ["typed-ast (>=1.4.0,<2)"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "0.4.3" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "nbclient" +version = "0.7.0" +description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." +category = "dev" +optional = false +python-versions = ">=3.7.0" + +[package.dependencies] +jupyter-client = ">=6.1.5" +nbformat = ">=5.0" +nest-asyncio = "*" +traitlets = ">=5.2.2" + +[package.extras] +test = ["xmltodict", "twine (>=1.11.0)", "testpath", "setuptools (>=60.0)", "pytest-cov (>=2.6.1)", "pytest-asyncio", "pytest (>=4.1)", "pre-commit", "pip (>=18.1)", "nbconvert", "mypy", "ipywidgets", "ipython", "ipykernel", "flake8", "check-manifest", "black"] +sphinx = ["sphinx-book-theme", "Sphinx (>=1.7)", "myst-parser", "moto", "mock", "autodoc-traits"] + +[[package]] +name = "nbconvert" +version = "7.2.1" +description = "Converting Jupyter Notebooks" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +beautifulsoup4 = "*" +bleach = "*" +defusedxml = "*" +importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} +jinja2 = ">=3.0" +jupyter-core = ">=4.7" +jupyterlab-pygments = "*" +markupsafe = ">=2.0" +mistune = ">=2.0.3,<3" +nbclient = ">=0.5.0" +nbformat = ">=5.1" +packaging = "*" +pandocfilters = ">=1.4.1" +pygments = ">=2.4.1" +tinycss2 = "*" +traitlets = ">=5.0" + +[package.extras] +all = ["ipykernel", "ipython", "ipywidgets (>=7)", "myst-parser", "nbsphinx (>=0.2.12)", "pre-commit", "pyppeteer (>=1,<1.1)", "pyqtwebengine (>=5.15)", "pytest", "pytest-cov", "pytest-dependency", "sphinx-rtd-theme", "sphinx (==5.0.2)", "tornado (>=6.1)"] +docs = ["ipython", "myst-parser", "nbsphinx (>=0.2.12)", "sphinx-rtd-theme", "sphinx (==5.0.2)"] +qtpdf = ["pyqtwebengine (>=5.15)"] +qtpng = ["pyqtwebengine (>=5.15)"] +serve = ["tornado (>=6.1)"] +test = ["ipykernel", "ipywidgets (>=7)", "pre-commit", "pyppeteer (>=1,<1.1)", "pytest", "pytest-cov", "pytest-dependency"] +webpdf = ["pyppeteer (>=1,<1.1)"] + +[[package]] +name = "nbformat" +version = "5.6.1" +description = "The Jupyter Notebook format" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +fastjsonschema = "*" +jsonschema = ">=2.6" +jupyter-core = "*" +traitlets = ">=5.1" + +[package.extras] +test = ["check-manifest", "pep440", "pre-commit", "pytest", "testpath"] + +[[package]] +name = "nest-asyncio" +version = "1.5.6" +description = "Patch asyncio to allow nested event loops" +category = "dev" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "nodeenv" +version = "1.7.0" +description = "Node.js virtual environment builder" +category = "dev" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" + +[[package]] +name = "notebook" +version = "6.4.12" +description = "A web-based notebook environment for interactive computing" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +argon2-cffi = "*" +ipykernel = "*" +ipython-genutils = "*" +jinja2 = "*" +jupyter-client = ">=5.3.4" +jupyter-core = ">=4.6.1" +nbconvert = ">=5" +nbformat = "*" +nest-asyncio = ">=1.5" +prometheus-client = "*" +pyzmq = ">=17" +Send2Trash = ">=1.8.0" +terminado = ">=0.8.3" +tornado = ">=6.1" +traitlets = ">=4.2.1" + +[package.extras] +docs = ["sphinx", "nbsphinx", "sphinxcontrib-github-alt", "sphinx-rtd-theme", "myst-parser"] +json-logging = ["json-logging"] +test = ["pytest", "coverage", "requests", "testpath", "nbval", "selenium", "pytest-cov", "requests-unixsocket"] + +[[package]] +name = "numpy" +version = "1.23.3" +description = "NumPy is the fundamental package for array computing with Python." +category = "main" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "packaging" +version = "21.3" +description = "Core utilities for Python packages" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" + +[[package]] +name = "pandas" +version = "1.5.0" +description = "Powerful data structures for data analysis, time series, and statistics" +category = "main" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +numpy = [ + {version = ">=1.21.0", markers = "python_version >= \"3.10\""}, + {version = ">=1.20.3", markers = "python_version < \"3.10\""}, +] +python-dateutil = ">=2.8.1" +pytz = ">=2020.1" + +[package.extras] +test = ["pytest-xdist (>=1.31)", "pytest (>=6.0)", "hypothesis (>=5.5.3)"] + +[[package]] +name = "pandocfilters" +version = "1.5.0" +description = "Utilities for writing pandoc filters in python" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "parso" +version = "0.8.3" +description = "A Python Parser" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] +testing = ["docopt", "pytest (<6.0.0)"] + +[[package]] +name = "pathspec" +version = "0.10.1" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "pbr" +version = "5.10.0" +description = "Python Build Reasonableness" +category = "dev" +optional = false +python-versions = ">=2.6" + +[[package]] +name = "pexpect" +version = "4.8.0" +description = "Pexpect allows easy control of interactive console applications." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +ptyprocess = ">=0.5" + +[[package]] +name = "pickleshare" +version = "0.7.5" +description = "Tiny 'shelve'-like database with concurrency support" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "platformdirs" +version = "2.5.2" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] +test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] + +[[package]] +name = "pluggy" +version = "1.0.0" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pre-commit" +version = "2.20.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +toml = "*" +virtualenv = ">=20.0.8" + +[[package]] +name = "prometheus-client" +version = "0.14.1" +description = "Python client for the Prometheus monitoring system." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +twisted = ["twisted"] + +[[package]] +name = "prompt-toolkit" +version = "3.0.31" +description = "Library for building powerful interactive command lines in Python" +category = "dev" +optional = false +python-versions = ">=3.6.2" + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "psutil" +version = "5.9.2" +description = "Cross-platform lib for process and system monitoring in Python." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.extras] +test = ["ipaddress", "mock", "enum34", "pywin32", "wmi"] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +description = "Run a subprocess in a pseudo terminal" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "pure-eval" +version = "0.2.2" +description = "Safely evaluate AST nodes without side effects" +category = "dev" +optional = false +python-versions = "*" + +[package.extras] +tests = ["pytest"] + +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "pycodestyle" +version = "2.8.0" +description = "Python style guide checker" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "pycparser" +version = "2.21" +description = "C parser in Python" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "pydocstyle" +version = "6.1.1" +description = "Python docstring style checker" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +snowballstemmer = "*" + +[package.extras] +toml = ["toml"] + +[[package]] +name = "pyflakes" +version = "2.4.0" +description = "passive checker of Python programs" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "pygments" +version = "2.13.0" +description = "Pygments is a syntax highlighting package written in Python." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +plugins = ["importlib-metadata"] + +[[package]] +name = "pylint" +version = "2.15.3" +description = "python code static checker" +category = "dev" +optional = false +python-versions = ">=3.7.2" + +[package.dependencies] +astroid = ">=2.12.10,<=2.14.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = ">=0.2" +isort = ">=4.2.5,<6" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + +[[package]] +name = "pyparsing" +version = "3.0.9" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +category = "dev" +optional = false +python-versions = ">=3.6.8" + +[package.extras] +diagrams = ["railroad-diagrams", "jinja2"] + +[[package]] +name = "pyrsistent" +version = "0.18.1" +description = "Persistent/Functional/Immutable data structures" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "pytest" +version = "7.1.3" +description = "pytest: simple powerful testing with Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +py = ">=1.8.2" +tomli = ">=1.0.0" + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "3.0.0" +description = "Pytest plugin for measuring coverage." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] + +[[package]] +name = "pytest-mock" +version = "3.10.0" +description = "Thin-wrapper around the mock package for easier use with pytest" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +pytest = ">=5.0" + +[package.extras] +dev = ["pre-commit", "tox", "pytest-asyncio"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytz" +version = "2022.4" +description = "World timezone definitions, modern and historical" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "pywin32" +version = "304" +description = "Python for Window Extensions" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "pywinpty" +version = "2.0.8" +description = "Pseudo terminal support for Windows from Python." +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "pyzmq" +version = "24.0.1" +description = "Python bindings for 0MQ" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +cffi = {version = "*", markers = "implementation_name == \"pypy\""} +py = {version = "*", markers = "implementation_name == \"pypy\""} + +[[package]] +name = "qtconsole" +version = "5.3.2" +description = "Jupyter Qt console" +category = "dev" +optional = false +python-versions = ">= 3.7" + +[package.dependencies] +ipykernel = ">=4.1" +ipython-genutils = "*" +jupyter-client = ">=4.1" +jupyter-core = "*" +pygments = "*" +pyzmq = ">=17.1" +qtpy = ">=2.0.1" +traitlets = "<5.2.1 || >5.2.1,<5.2.2 || >5.2.2" + +[package.extras] +doc = ["Sphinx (>=1.3)"] +test = ["flaky", "pytest", "pytest-qt"] + +[[package]] +name = "qtpy" +version = "2.2.1" +description = "Provides an abstraction layer on top of the various Qt bindings (PyQt5/6 and PySide2/6)." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +packaging = "*" + +[package.extras] +test = ["pytest (>=6,!=7.0.0,!=7.0.1)", "pytest-cov (>=3.0.0)", "pytest-qt"] + +[[package]] +name = "requests" +version = "2.28.1" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=3.7, <4" + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<3" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "ruamel.yaml" +version = "0.17.21" +description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +category = "dev" +optional = false +python-versions = ">=3" + +[package.dependencies] +"ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""} + +[package.extras] +docs = ["ryd"] +jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] + +[[package]] +name = "ruamel.yaml.clib" +version = "0.2.6" +description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +category = "dev" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "safety" +version = "2.3.1" +description = "Checks installed dependencies for known vulnerabilities and licenses." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +Click = ">=8.0.2" +dparse = ">=0.6.2" +packaging = ">=21.0" +requests = "*" +"ruamel.yaml" = ">=0.17.21" + +[package.extras] +github = ["pygithub (>=1.43.3)", "jinja2 (>=3.1.0)"] +gitlab = ["python-gitlab (>=1.3.0)"] + +[[package]] +name = "send2trash" +version = "1.8.0" +description = "Send file to trash natively under Mac OS X, Windows and Linux." +category = "dev" +optional = false +python-versions = "*" + +[package.extras] +nativelib = ["pyobjc-framework-cocoa", "pywin32"] +objc = ["pyobjc-framework-cocoa"] +win32 = ["pywin32"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "smmap" +version = "5.0.0" +description = "A pure Python implementation of a sliding window memory map manager" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "soupsieve" +version = "2.3.2.post1" +description = "A modern CSS selector implementation for Beautiful Soup." +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "stack-data" +version = "0.5.1" +description = "Extract data from python stack frames and tracebacks for informative displays" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +asttokens = "*" +executing = "*" +pure-eval = "*" + +[package.extras] +tests = ["cython", "littleutils", "pygments", "typeguard", "pytest"] + +[[package]] +name = "stevedore" +version = "4.0.0" +description = "Manage dynamic plugins for Python applications" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +pbr = ">=2.0.0,<2.1.0 || >2.1.0" + +[[package]] +name = "tabulate" +version = "0.8.10" +description = "Pretty-print tabular data" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.extras] +widechars = ["wcwidth"] + +[[package]] +name = "terminado" +version = "0.16.0" +description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +ptyprocess = {version = "*", markers = "os_name != \"nt\""} +pywinpty = {version = ">=1.1.0", markers = "os_name == \"nt\""} +tornado = ">=6.1.0" + +[package.extras] +test = ["pre-commit", "pytest-timeout", "pytest (>=6.0)"] + +[[package]] +name = "tinycss2" +version = "1.1.1" +description = "A tiny CSS parser" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +webencodings = ">=0.4" + +[package.extras] +doc = ["sphinx", "sphinx-rtd-theme"] +test = ["pytest", "pytest-cov", "pytest-flake8", "pytest-isort", "coverage"] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "dev" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "tomlkit" +version = "0.11.5" +description = "Style preserving TOML library" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[[package]] +name = "tornado" +version = "6.2" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +category = "dev" +optional = false +python-versions = ">= 3.7" + +[[package]] +name = "traitlets" +version = "5.4.0" +description = "" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +test = ["pre-commit", "pytest"] + +[[package]] +name = "typing-extensions" +version = "4.4.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "urllib3" +version = "1.26.12" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" + +[package.extras] +brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "urllib3-secure-extra", "ipaddress"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "virtualenv" +version = "20.16.5" +description = "Virtual Python Environment builder" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +distlib = ">=0.3.5,<1" +filelock = ">=3.4.1,<4" +platformdirs = ">=2.4,<3" + +[package.extras] +docs = ["proselint (>=0.13)", "sphinx (>=5.1.1)", "sphinx-argparse (>=0.3.1)", "sphinx-rtd-theme (>=1)", "towncrier (>=21.9)"] +testing = ["coverage (>=6.2)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=21.3)", "pytest (>=7.0.1)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.6.1)", "pytest-randomly (>=3.10.3)", "pytest-timeout (>=2.1)"] + +[[package]] +name = "wcwidth" +version = "0.2.5" +description = "Measures the displayed width of unicode strings in a terminal" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "widgetsnbextension" +version = "4.0.3" +description = "Jupyter interactive widgets for Jupyter Notebook" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "wrapt" +version = "1.14.1" +description = "Module for decorators, wrappers and monkey patching." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[[package]] +name = "zipp" +version = "3.9.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["sphinx (>=3.5)", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "furo", "jaraco.tidelift (>=1.4)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "flake8 (<5)", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "func-timeout", "jaraco.functools", "more-itertools", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] + +[metadata] +lock-version = "1.1" +python-versions = "^3.9" +content-hash = "b98400d2fd75045beb31ea54ad12a6a2edef2b34404b2fe33e14142e44fccf49" + +[metadata.files] +appnope = [ + {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, + {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, +] +argon2-cffi = [ + {file = "argon2-cffi-21.3.0.tar.gz", hash = "sha256:d384164d944190a7dd7ef22c6aa3ff197da12962bd04b17f64d4e93d934dba5b"}, + {file = "argon2_cffi-21.3.0-py3-none-any.whl", hash = "sha256:8c976986f2c5c0e5000919e6de187906cfd81fb1c72bf9d88c01177e77da7f80"}, +] +argon2-cffi-bindings = [ + {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f"}, + {file = "argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a"}, +] +astroid = [ + {file = "astroid-2.12.10-py3-none-any.whl", hash = "sha256:997e0c735df60d4a4caff27080a3afc51f9bdd693d3572a4a0b7090b645c36c5"}, + {file = "astroid-2.12.10.tar.gz", hash = "sha256:81f870105d892e73bf535da77a8261aa5bde838fa4ed12bb2f435291a098c581"}, +] +asttokens = [ + {file = "asttokens-2.0.8-py2.py3-none-any.whl", hash = "sha256:e3305297c744ae53ffa032c45dc347286165e4ffce6875dc662b205db0623d86"}, + {file = "asttokens-2.0.8.tar.gz", hash = "sha256:c61e16246ecfb2cde2958406b4c8ebc043c9e6d73aaa83c941673b35e5d3a76b"}, +] +attrs = [ + {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, + {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, +] +backcall = [ + {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, + {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, +] +bandit = [ + {file = "bandit-1.7.4-py3-none-any.whl", hash = "sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a"}, + {file = "bandit-1.7.4.tar.gz", hash = "sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2"}, +] +beautifulsoup4 = [ + {file = "beautifulsoup4-4.11.1-py3-none-any.whl", hash = "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30"}, + {file = "beautifulsoup4-4.11.1.tar.gz", hash = "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"}, +] +black = [ + {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, + {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, + {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, + {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, + {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, + {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, + {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, + {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, + {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, + {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, + {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, + {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, + {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, + {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, + {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, + {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, + {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, + {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, + {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, + {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, + {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, +] +bleach = [] +certifi = [ + {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"}, + {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"}, +] +cffi = [] +cfgv = [ + {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, + {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, +] +charset-normalizer = [ + {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, + {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, +] +click = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] +colorama = [] +coverage = [ + {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"}, + {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"}, + {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"}, + {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"}, + {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"}, + {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"}, + {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"}, + {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"}, + {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"}, + {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"}, + {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"}, + {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"}, + {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"}, + {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"}, + {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"}, + {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"}, + {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"}, + {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"}, + {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"}, + {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"}, +] +debugpy = [ + {file = "debugpy-1.6.3-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:c4b2bd5c245eeb49824bf7e539f95fb17f9a756186e51c3e513e32999d8846f3"}, + {file = "debugpy-1.6.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b8deaeb779699350deeed835322730a3efec170b88927debc9ba07a1a38e2585"}, + {file = "debugpy-1.6.3-cp310-cp310-win32.whl", hash = "sha256:fc233a0160f3b117b20216f1169e7211b83235e3cd6749bcdd8dbb72177030c7"}, + {file = "debugpy-1.6.3-cp310-cp310-win_amd64.whl", hash = "sha256:dda8652520eae3945833e061cbe2993ad94a0b545aebd62e4e6b80ee616c76b2"}, + {file = "debugpy-1.6.3-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:d5c814596a170a0a58fa6fad74947e30bfd7e192a5d2d7bd6a12156c2899e13a"}, + {file = "debugpy-1.6.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c4cd6f37e3c168080d61d698390dfe2cd9e74ebf80b448069822a15dadcda57d"}, + {file = "debugpy-1.6.3-cp37-cp37m-win32.whl", hash = "sha256:3c9f985944a30cfc9ae4306ac6a27b9c31dba72ca943214dad4a0ab3840f6161"}, + {file = "debugpy-1.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:5ad571a36cec137ae6ed951d0ff75b5e092e9af6683da084753231150cbc5b25"}, + {file = "debugpy-1.6.3-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:adcfea5ea06d55d505375995e150c06445e2b20cd12885bcae566148c076636b"}, + {file = "debugpy-1.6.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:daadab4403427abd090eccb38d8901afd8b393e01fd243048fab3f1d7132abb4"}, + {file = "debugpy-1.6.3-cp38-cp38-win32.whl", hash = "sha256:6efc30325b68e451118b795eff6fe8488253ca3958251d5158106d9c87581bc6"}, + {file = "debugpy-1.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:86d784b72c5411c833af1cd45b83d80c252b77c3bfdb43db17c441d772f4c734"}, + {file = "debugpy-1.6.3-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:4e255982552b0edfe3a6264438dbd62d404baa6556a81a88f9420d3ed79b06ae"}, + {file = "debugpy-1.6.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cca23cb6161ac89698d629d892520327dd1be9321c0960e610bbcb807232b45d"}, + {file = "debugpy-1.6.3-cp39-cp39-win32.whl", hash = "sha256:7c302095a81be0d5c19f6529b600bac971440db3e226dce85347cc27e6a61908"}, + {file = "debugpy-1.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:34d2cdd3a7c87302ba5322b86e79c32c2115be396f3f09ca13306d8a04fe0f16"}, + {file = "debugpy-1.6.3-py2.py3-none-any.whl", hash = "sha256:84c39940a0cac410bf6aa4db00ba174f973eef521fbe9dd058e26bcabad89c4f"}, + {file = "debugpy-1.6.3.zip", hash = "sha256:e8922090514a890eec99cfb991bab872dd2e353ebb793164d5f01c362b9a40bf"}, +] +decorator = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] +defusedxml = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] +dill = [ + {file = "dill-0.3.5.1-py2.py3-none-any.whl", hash = "sha256:33501d03270bbe410c72639b350e941882a8b0fd55357580fbc873fba0c59302"}, + {file = "dill-0.3.5.1.tar.gz", hash = "sha256:d75e41f3eff1eee599d738e76ba8f4ad98ea229db8b085318aa2b3333a208c86"}, +] +distlib = [ + {file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"}, + {file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"}, +] +dparse = [ + {file = "dparse-0.6.2-py3-none-any.whl", hash = "sha256:8097076f1dd26c377f30d4745e6ec18fef42f3bf493933b842ac5bafad8c345f"}, + {file = "dparse-0.6.2.tar.gz", hash = "sha256:d45255bda21f998bc7ddf2afd5e62505ba6134756ba2d42a84c56b0826614dfe"}, +] +entrypoints = [ + {file = "entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f"}, + {file = "entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4"}, +] +executing = [ + {file = "executing-1.1.1-py2.py3-none-any.whl", hash = "sha256:236ea5f059a38781714a8bfba46a70fad3479c2f552abee3bbafadc57ed111b8"}, + {file = "executing-1.1.1.tar.gz", hash = "sha256:b0d7f8dcc2bac47ce6e39374397e7acecea6fdc380a6d5323e26185d70f38ea8"}, +] +fastjsonschema = [ + {file = "fastjsonschema-2.16.2-py3-none-any.whl", hash = "sha256:21f918e8d9a1a4ba9c22e09574ba72267a6762d47822db9add95f6454e51cc1c"}, + {file = "fastjsonschema-2.16.2.tar.gz", hash = "sha256:01e366f25d9047816fe3d288cbfc3e10541daf0af2044763f3d0ade42476da18"}, +] +filelock = [ + {file = "filelock-3.8.0-py3-none-any.whl", hash = "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4"}, + {file = "filelock-3.8.0.tar.gz", hash = "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc"}, +] +flake8 = [ + {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, + {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, +] +flake8-docstrings = [ + {file = "flake8-docstrings-1.6.0.tar.gz", hash = "sha256:9fe7c6a306064af8e62a055c2f61e9eb1da55f84bb39caef2b84ce53708ac34b"}, + {file = "flake8_docstrings-1.6.0-py2.py3-none-any.whl", hash = "sha256:99cac583d6c7e32dd28bbfbef120a7c0d1b6dde4adb5a9fd441c4227a6534bde"}, +] +gitdb = [ + {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"}, + {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"}, +] +gitpython = [ + {file = "GitPython-3.1.28-py3-none-any.whl", hash = "sha256:77bfbd299d8709f6af7e0c70840ef26e7aff7cf0c1ed53b42dd7fc3a310fcb02"}, + {file = "GitPython-3.1.28.tar.gz", hash = "sha256:6bd3451b8271132f099ceeaf581392eaf6c274af74bb06144307870479d0697c"}, +] +identify = [ + {file = "identify-2.5.6-py2.py3-none-any.whl", hash = "sha256:b276db7ec52d7e89f5bc4653380e33054ddc803d25875952ad90b0f012cbcdaa"}, + {file = "identify-2.5.6.tar.gz", hash = "sha256:6c32dbd747aa4ceee1df33f25fed0b0f6e0d65721b15bd151307ff7056d50245"}, +] +idna = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] +importlib-metadata = [ + {file = "importlib_metadata-5.0.0-py3-none-any.whl", hash = "sha256:ddb0e35065e8938f867ed4928d0ae5bf2a53b7773871bfe6bcc7e4fcdc7dea43"}, + {file = "importlib_metadata-5.0.0.tar.gz", hash = "sha256:da31db32b304314d044d3c12c79bd59e307889b287ad12ff387b3500835fc2ab"}, +] +iniconfig = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] +ipykernel = [ + {file = "ipykernel-6.16.0-py3-none-any.whl", hash = "sha256:d3d95241cd4dd302fea9d5747b00509b58997356d1f6333c9a074c3eccb78cb3"}, + {file = "ipykernel-6.16.0.tar.gz", hash = "sha256:7fe42c0d58435e971dc15fd42189f20d66bf35f3056bda4f6554271bc1fa3d0d"}, +] +ipython = [ + {file = "ipython-8.5.0-py3-none-any.whl", hash = "sha256:6f090e29ab8ef8643e521763a4f1f39dc3914db643122b1e9d3328ff2e43ada2"}, + {file = "ipython-8.5.0.tar.gz", hash = "sha256:097bdf5cd87576fd066179c9f7f208004f7a6864ee1b20f37d346c0bcb099f84"}, +] +ipython-genutils = [ + {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, + {file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"}, +] +ipywidgets = [ + {file = "ipywidgets-8.0.2-py3-none-any.whl", hash = "sha256:1dc3dd4ee19ded045ea7c86eb273033d238d8e43f9e7872c52d092683f263891"}, + {file = "ipywidgets-8.0.2.tar.gz", hash = "sha256:08cb75c6e0a96836147cbfdc55580ae04d13e05d26ffbc377b4e1c68baa28b1f"}, +] +isort = [ + {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, + {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, +] +jedi = [ + {file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"}, + {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"}, +] +jinja2 = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] +jsonschema = [ + {file = "jsonschema-4.16.0-py3-none-any.whl", hash = "sha256:9e74b8f9738d6a946d70705dc692b74b5429cd0960d58e79ffecfc43b2221eb9"}, + {file = "jsonschema-4.16.0.tar.gz", hash = "sha256:165059f076eff6971bae5b742fc029a7b4ef3f9bcf04c14e4776a7605de14b23"}, +] +jupyter = [ + {file = "jupyter-1.0.0-py2.py3-none-any.whl", hash = "sha256:5b290f93b98ffbc21c0c7e749f054b3267782166d72fa5e3ed1ed4eaf34a2b78"}, + {file = "jupyter-1.0.0.tar.gz", hash = "sha256:d9dc4b3318f310e34c82951ea5d6683f67bed7def4b259fafbfe4f1beb1d8e5f"}, + {file = "jupyter-1.0.0.zip", hash = "sha256:3e1f86076bbb7c8c207829390305a2b1fe836d471ed54be66a3b8c41e7f46cc7"}, +] +jupyter-client = [ + {file = "jupyter_client-7.3.5-py3-none-any.whl", hash = "sha256:b33222bdc9dd1714228bd286af006533a0abe2bbc093e8f3d29dc0b91bdc2be4"}, + {file = "jupyter_client-7.3.5.tar.gz", hash = "sha256:3c58466a1b8d55dba0bf3ce0834e4f5b7760baf98d1d73db0add6f19de9ecd1d"}, +] +jupyter-console = [ + {file = "jupyter_console-6.4.4-py3-none-any.whl", hash = "sha256:756df7f4f60c986e7bc0172e4493d3830a7e6e75c08750bbe59c0a5403ad6dee"}, + {file = "jupyter_console-6.4.4.tar.gz", hash = "sha256:172f5335e31d600df61613a97b7f0352f2c8250bbd1092ef2d658f77249f89fb"}, +] +jupyter-core = [] +jupyterlab-pygments = [ + {file = "jupyterlab_pygments-0.2.2-py2.py3-none-any.whl", hash = "sha256:2405800db07c9f770863bcf8049a529c3dd4d3e28536638bd7c1c01d2748309f"}, + {file = "jupyterlab_pygments-0.2.2.tar.gz", hash = "sha256:7405d7fde60819d905a9fa8ce89e4cd830e318cdad22a0030f7a901da705585d"}, +] +jupyterlab-widgets = [ + {file = "jupyterlab_widgets-3.0.3-py3-none-any.whl", hash = "sha256:6aa1bc0045470d54d76b9c0b7609a8f8f0087573bae25700a370c11f82cb38c8"}, + {file = "jupyterlab_widgets-3.0.3.tar.gz", hash = "sha256:c767181399b4ca8b647befe2d913b1260f51bf9d8ef9b7a14632d4c1a7b536bd"}, +] +lazy-object-proxy = [ + {file = "lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-win32.whl", hash = "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win32.whl", hash = "sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win32.whl", hash = "sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-win32.whl", hash = "sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-win32.whl", hash = "sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61"}, + {file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"}, +] +markupsafe = [ + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, + {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, +] +matplotlib-inline = [ + {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"}, + {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"}, +] +mccabe = [ + {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, + {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, +] +mistune = [ + {file = "mistune-2.0.4-py2.py3-none-any.whl", hash = "sha256:182cc5ee6f8ed1b807de6b7bb50155df7b66495412836b9a74c8fbdfc75fe36d"}, + {file = "mistune-2.0.4.tar.gz", hash = "sha256:9ee0a66053e2267aba772c71e06891fa8f1af6d4b01d5e84e267b4570d4d9808"}, +] +mypy = [ + {file = "mypy-0.942-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5bf44840fb43ac4074636fd47ee476d73f0039f4f54e86d7265077dc199be24d"}, + {file = "mypy-0.942-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dcd955f36e0180258a96f880348fbca54ce092b40fbb4b37372ae3b25a0b0a46"}, + {file = "mypy-0.942-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6776e5fa22381cc761df53e7496a805801c1a751b27b99a9ff2f0ca848c7eca0"}, + {file = "mypy-0.942-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:edf7237137a1a9330046dbb14796963d734dd740a98d5e144a3eb1d267f5f9ee"}, + {file = "mypy-0.942-cp310-cp310-win_amd64.whl", hash = "sha256:64235137edc16bee6f095aba73be5334677d6f6bdb7fa03cfab90164fa294a17"}, + {file = "mypy-0.942-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b840cfe89c4ab6386c40300689cd8645fc8d2d5f20101c7f8bd23d15fca14904"}, + {file = "mypy-0.942-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2b184db8c618c43c3a31b32ff00cd28195d39e9c24e7c3b401f3db7f6e5767f5"}, + {file = "mypy-0.942-cp36-cp36m-win_amd64.whl", hash = "sha256:1a0459c333f00e6a11cbf6b468b870c2b99a906cb72d6eadf3d1d95d38c9352c"}, + {file = "mypy-0.942-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4c3e497588afccfa4334a9986b56f703e75793133c4be3a02d06a3df16b67a58"}, + {file = "mypy-0.942-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6f6ad963172152e112b87cc7ec103ba0f2db2f1cd8997237827c052a3903eaa6"}, + {file = "mypy-0.942-cp37-cp37m-win_amd64.whl", hash = "sha256:0e2dd88410937423fba18e57147dd07cd8381291b93d5b1984626f173a26543e"}, + {file = "mypy-0.942-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:246e1aa127d5b78488a4a0594bd95f6d6fb9d63cf08a66dafbff8595d8891f67"}, + {file = "mypy-0.942-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d8d3ba77e56b84cd47a8ee45b62c84b6d80d32383928fe2548c9a124ea0a725c"}, + {file = "mypy-0.942-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2bc249409a7168d37c658e062e1ab5173300984a2dada2589638568ddc1db02b"}, + {file = "mypy-0.942-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9521c1265ccaaa1791d2c13582f06facf815f426cd8b07c3a485f486a8ffc1f3"}, + {file = "mypy-0.942-cp38-cp38-win_amd64.whl", hash = "sha256:e865fec858d75b78b4d63266c9aff770ecb6a39dfb6d6b56c47f7f8aba6baba8"}, + {file = "mypy-0.942-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6ce34a118d1a898f47def970a2042b8af6bdcc01546454726c7dd2171aa6dfca"}, + {file = "mypy-0.942-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:10daab80bc40f84e3f087d896cdb53dc811a9f04eae4b3f95779c26edee89d16"}, + {file = "mypy-0.942-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3841b5433ff936bff2f4dc8d54cf2cdbfea5d8e88cedfac45c161368e5770ba6"}, + {file = "mypy-0.942-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6f7106cbf9cc2f403693bf50ed7c9fa5bb3dfa9007b240db3c910929abe2a322"}, + {file = "mypy-0.942-cp39-cp39-win_amd64.whl", hash = "sha256:7742d2c4e46bb5017b51c810283a6a389296cda03df805a4f7869a6f41246534"}, + {file = "mypy-0.942-py3-none-any.whl", hash = "sha256:a1b383fe99678d7402754fe90448d4037f9512ce70c21f8aee3b8bf48ffc51db"}, + {file = "mypy-0.942.tar.gz", hash = "sha256:17e44649fec92e9f82102b48a3bf7b4a5510ad0cd22fa21a104826b5db4903e2"}, +] +mypy-extensions = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] +nbclient = [ + {file = "nbclient-0.7.0-py3-none-any.whl", hash = "sha256:434c91385cf3e53084185334d675a0d33c615108b391e260915d1aa8e86661b8"}, + {file = "nbclient-0.7.0.tar.gz", hash = "sha256:a1d844efd6da9bc39d2209bf996dbd8e07bf0f36b796edfabaa8f8a9ab77c3aa"}, +] +nbconvert = [ + {file = "nbconvert-7.2.1-py3-none-any.whl", hash = "sha256:50a54366ab53da20e82668818b7b2f3f7b85c0bcd46ec8e18836f12b39180dfa"}, + {file = "nbconvert-7.2.1.tar.gz", hash = "sha256:1e180801205ad831b6e2480c5a03307dfb6327fa5b2f9b156d6fed45f9700686"}, +] +nbformat = [ + {file = "nbformat-5.6.1-py3-none-any.whl", hash = "sha256:9c071f0f615c1b0f4f9bf6745ecfd3294fc02daf279a05c76004c901e9dc5893"}, + {file = "nbformat-5.6.1.tar.gz", hash = "sha256:146b5b9969391387c2089256359f5da7c718b1d8a88ba814320273ea410e646e"}, +] +nest-asyncio = [ + {file = "nest_asyncio-1.5.6-py3-none-any.whl", hash = "sha256:b9a953fb40dceaa587d109609098db21900182b16440652454a146cffb06e8b8"}, + {file = "nest_asyncio-1.5.6.tar.gz", hash = "sha256:d267cc1ff794403f7df692964d1d2a3fa9418ffea2a3f6859a439ff482fef290"}, +] +nodeenv = [ + {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, + {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, +] +notebook = [] +numpy = [ + {file = "numpy-1.23.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c9f707b5bb73bf277d812ded9896f9512a43edff72712f31667d0a8c2f8e71ee"}, + {file = "numpy-1.23.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffcf105ecdd9396e05a8e58e81faaaf34d3f9875f137c7372450baa5d77c9a54"}, + {file = "numpy-1.23.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ea3f98a0ffce3f8f57675eb9119f3f4edb81888b6874bc1953f91e0b1d4f440"}, + {file = "numpy-1.23.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:004f0efcb2fe1c0bd6ae1fcfc69cc8b6bf2407e0f18be308612007a0762b4089"}, + {file = "numpy-1.23.3-cp310-cp310-win32.whl", hash = "sha256:98dcbc02e39b1658dc4b4508442a560fe3ca5ca0d989f0df062534e5ca3a5c1a"}, + {file = "numpy-1.23.3-cp310-cp310-win_amd64.whl", hash = "sha256:39a664e3d26ea854211867d20ebcc8023257c1800ae89773cbba9f9e97bae036"}, + {file = "numpy-1.23.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1f27b5322ac4067e67c8f9378b41c746d8feac8bdd0e0ffede5324667b8a075c"}, + {file = "numpy-1.23.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ad3ec9a748a8943e6eb4358201f7e1c12ede35f510b1a2221b70af4bb64295c"}, + {file = "numpy-1.23.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdc9febce3e68b697d931941b263c59e0c74e8f18861f4064c1f712562903411"}, + {file = "numpy-1.23.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:301c00cf5e60e08e04d842fc47df641d4a181e651c7135c50dc2762ffe293dbd"}, + {file = "numpy-1.23.3-cp311-cp311-win32.whl", hash = "sha256:7cd1328e5bdf0dee621912f5833648e2daca72e3839ec1d6695e91089625f0b4"}, + {file = "numpy-1.23.3-cp311-cp311-win_amd64.whl", hash = "sha256:8355fc10fd33a5a70981a5b8a0de51d10af3688d7a9e4a34fcc8fa0d7467bb7f"}, + {file = "numpy-1.23.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc6e8da415f359b578b00bcfb1d08411c96e9a97f9e6c7adada554a0812a6cc6"}, + {file = "numpy-1.23.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:22d43376ee0acd547f3149b9ec12eec2f0ca4a6ab2f61753c5b29bb3e795ac4d"}, + {file = "numpy-1.23.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a64403f634e5ffdcd85e0b12c08f04b3080d3e840aef118721021f9b48fc1460"}, + {file = "numpy-1.23.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efd9d3abe5774404becdb0748178b48a218f1d8c44e0375475732211ea47c67e"}, + {file = "numpy-1.23.3-cp38-cp38-win32.whl", hash = "sha256:f8c02ec3c4c4fcb718fdf89a6c6f709b14949408e8cf2a2be5bfa9c49548fd85"}, + {file = "numpy-1.23.3-cp38-cp38-win_amd64.whl", hash = "sha256:e868b0389c5ccfc092031a861d4e158ea164d8b7fdbb10e3b5689b4fc6498df6"}, + {file = "numpy-1.23.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:09f6b7bdffe57fc61d869a22f506049825d707b288039d30f26a0d0d8ea05164"}, + {file = "numpy-1.23.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8c79d7cf86d049d0c5089231a5bcd31edb03555bd93d81a16870aa98c6cfb79d"}, + {file = "numpy-1.23.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5d5420053bbb3dd64c30e58f9363d7a9c27444c3648e61460c1237f9ec3fa14"}, + {file = "numpy-1.23.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5422d6a1ea9b15577a9432e26608c73a78faf0b9039437b075cf322c92e98e7"}, + {file = "numpy-1.23.3-cp39-cp39-win32.whl", hash = "sha256:c1ba66c48b19cc9c2975c0d354f24058888cdc674bebadceb3cdc9ec403fb5d1"}, + {file = "numpy-1.23.3-cp39-cp39-win_amd64.whl", hash = "sha256:78a63d2df1d947bd9d1b11d35564c2f9e4b57898aae4626638056ec1a231c40c"}, + {file = "numpy-1.23.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:17c0e467ade9bda685d5ac7f5fa729d8d3e76b23195471adae2d6a6941bd2c18"}, + {file = "numpy-1.23.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91b8d6768a75247026e951dce3b2aac79dc7e78622fc148329135ba189813584"}, + {file = "numpy-1.23.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:94c15ca4e52671a59219146ff584488907b1f9b3fc232622b47e2cf832e94fb8"}, + {file = "numpy-1.23.3.tar.gz", hash = "sha256:51bf49c0cd1d52be0a240aa66f3458afc4b95d8993d2d04f0d91fa60c10af6cd"}, +] +packaging = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] +pandas = [ + {file = "pandas-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0d8d7433d19bfa33f11c92ad9997f15a902bda4f5ad3a4814a21d2e910894484"}, + {file = "pandas-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5cc47f2ebaa20ef96ae72ee082f9e101b3dfbf74f0e62c7a12c0b075a683f03c"}, + {file = "pandas-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e8e5edf97d8793f51d258c07c629bd49d271d536ce15d66ac00ceda5c150eb3"}, + {file = "pandas-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41aec9f87455306496d4486df07c1b98c15569c714be2dd552a6124cd9fda88f"}, + {file = "pandas-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c76f1d104844c5360c21d2ef0e1a8b2ccf8b8ebb40788475e255b9462e32b2be"}, + {file = "pandas-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:1642fc6138b4e45d57a12c1b464a01a6d868c0148996af23f72dde8d12486bbc"}, + {file = "pandas-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:171cef540bfcec52257077816a4dbbac152acdb8236ba11d3196ae02bf0959d8"}, + {file = "pandas-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a68a9b9754efff364b0c5ee5b0f18e15ca640c01afe605d12ba8b239ca304d6b"}, + {file = "pandas-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:86d87279ebc5bc20848b4ceb619073490037323f80f515e0ec891c80abad958a"}, + {file = "pandas-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:207d63ac851e60ec57458814613ef4b3b6a5e9f0b33c57623ba2bf8126c311f8"}, + {file = "pandas-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e252a9e49b233ff96e2815c67c29702ac3a062098d80a170c506dff3470fd060"}, + {file = "pandas-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:de34636e2dc04e8ac2136a8d3c2051fd56ebe9fd6cd185581259330649e73ca9"}, + {file = "pandas-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:1d34b1f43d9e3f4aea056ba251f6e9b143055ebe101ed04c847b41bb0bb4a989"}, + {file = "pandas-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b82ccc7b093e0a93f8dffd97a542646a3e026817140e2c01266aaef5fdde11b"}, + {file = "pandas-1.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4e30a31039574d96f3d683df34ccb50bb435426ad65793e42a613786901f6761"}, + {file = "pandas-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62e61003411382e20d7c2aec1ee8d7c86c8b9cf46290993dd8a0a3be44daeb38"}, + {file = "pandas-1.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc987f7717e53d372f586323fff441263204128a1ead053c1b98d7288f836ac9"}, + {file = "pandas-1.5.0-cp38-cp38-win32.whl", hash = "sha256:e178ce2d7e3b934cf8d01dc2d48d04d67cb0abfaffdcc8aa6271fd5a436f39c8"}, + {file = "pandas-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:33a9d9e21ab2d91e2ab6e83598419ea6a664efd4c639606b299aae8097c1c94f"}, + {file = "pandas-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:73844e247a7b7dac2daa9df7339ecf1fcf1dfb8cbfd11e3ffe9819ae6c31c515"}, + {file = "pandas-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e9c5049333c5bebf993033f4bf807d163e30e8fada06e1da7fa9db86e2392009"}, + {file = "pandas-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:85a516a7f6723ca1528f03f7851fa8d0360d1d6121cf15128b290cf79b8a7f6a"}, + {file = "pandas-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:947ed9f896ee61adbe61829a7ae1ade493c5a28c66366ec1de85c0642009faac"}, + {file = "pandas-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7f38d91f21937fe2bec9449570d7bf36ad7136227ef43b321194ec249e2149d"}, + {file = "pandas-1.5.0-cp39-cp39-win32.whl", hash = "sha256:2504c032f221ef9e4a289f5e46a42b76f5e087ecb67d62e342ccbba95a32a488"}, + {file = "pandas-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:8a4fc04838615bf0a8d3a03ed68197f358054f0df61f390bcc64fbe39e3d71ec"}, + {file = "pandas-1.5.0.tar.gz", hash = "sha256:3ee61b881d2f64dd90c356eb4a4a4de75376586cd3c9341c6c0fcaae18d52977"}, +] +pandocfilters = [ + {file = "pandocfilters-1.5.0-py2.py3-none-any.whl", hash = "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f"}, + {file = "pandocfilters-1.5.0.tar.gz", hash = "sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38"}, +] +parso = [ + {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, + {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, +] +pathspec = [ + {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, + {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, +] +pbr = [ + {file = "pbr-5.10.0-py2.py3-none-any.whl", hash = "sha256:da3e18aac0a3c003e9eea1a81bd23e5a3a75d745670dcf736317b7d966887fdf"}, + {file = "pbr-5.10.0.tar.gz", hash = "sha256:cfcc4ff8e698256fc17ea3ff796478b050852585aa5bae79ecd05b2ab7b39b9a"}, +] +pexpect = [ + {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, + {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, +] +pickleshare = [ + {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, + {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, +] +platformdirs = [ + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, +] +pluggy = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] +pre-commit = [ + {file = "pre_commit-2.20.0-py2.py3-none-any.whl", hash = "sha256:51a5ba7c480ae8072ecdb6933df22d2f812dc897d5fe848778116129a681aac7"}, + {file = "pre_commit-2.20.0.tar.gz", hash = "sha256:a978dac7bc9ec0bcee55c18a277d553b0f419d259dadb4b9418ff2d00eb43959"}, +] +prometheus-client = [ + {file = "prometheus_client-0.14.1-py3-none-any.whl", hash = "sha256:522fded625282822a89e2773452f42df14b5a8e84a86433e3f8a189c1d54dc01"}, + {file = "prometheus_client-0.14.1.tar.gz", hash = "sha256:5459c427624961076277fdc6dc50540e2bacb98eebde99886e59ec55ed92093a"}, +] +prompt-toolkit = [ + {file = "prompt_toolkit-3.0.31-py3-none-any.whl", hash = "sha256:9696f386133df0fc8ca5af4895afe5d78f5fcfe5258111c2a79a1c3e41ffa96d"}, + {file = "prompt_toolkit-3.0.31.tar.gz", hash = "sha256:9ada952c9d1787f52ff6d5f3484d0b4df8952787c087edf6a1f7c2cb1ea88148"}, +] +psutil = [ + {file = "psutil-5.9.2-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:8f024fbb26c8daf5d70287bb3edfafa22283c255287cf523c5d81721e8e5d82c"}, + {file = "psutil-5.9.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:b2f248ffc346f4f4f0d747ee1947963613216b06688be0be2e393986fe20dbbb"}, + {file = "psutil-5.9.2-cp27-cp27m-win32.whl", hash = "sha256:b1928b9bf478d31fdffdb57101d18f9b70ed4e9b0e41af751851813547b2a9ab"}, + {file = "psutil-5.9.2-cp27-cp27m-win_amd64.whl", hash = "sha256:404f4816c16a2fcc4eaa36d7eb49a66df2d083e829d3e39ee8759a411dbc9ecf"}, + {file = "psutil-5.9.2-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:94e621c6a4ddb2573d4d30cba074f6d1aa0186645917df42c811c473dd22b339"}, + {file = "psutil-5.9.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:256098b4f6ffea6441eb54ab3eb64db9ecef18f6a80d7ba91549195d55420f84"}, + {file = "psutil-5.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:614337922702e9be37a39954d67fdb9e855981624d8011a9927b8f2d3c9625d9"}, + {file = "psutil-5.9.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:39ec06dc6c934fb53df10c1672e299145ce609ff0611b569e75a88f313634969"}, + {file = "psutil-5.9.2-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3ac2c0375ef498e74b9b4ec56df3c88be43fe56cac465627572dbfb21c4be34"}, + {file = "psutil-5.9.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:dc9bda7d5ced744622f157cc8d8bdd51735dafcecff807e928ff26bdb0ff097d"}, + {file = "psutil-5.9.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75291912b945a7351d45df682f9644540d564d62115d4a20d45fa17dc2d48f8"}, + {file = "psutil-5.9.2-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4018d5f9b6651f9896c7a7c2c9f4652e4eea53f10751c4e7d08a9093ab587ec"}, + {file = "psutil-5.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:42638876b7f5ef43cef8dcf640d3401b27a51ee3fa137cb2aa2e72e188414c32"}, + {file = "psutil-5.9.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91aa0dac0c64688667b4285fa29354acfb3e834e1fd98b535b9986c883c2ce1d"}, + {file = "psutil-5.9.2-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fb54941aac044a61db9d8eb56fc5bee207db3bc58645d657249030e15ba3727"}, + {file = "psutil-5.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fd331866628d18223a4265371fd255774affd86244fc307ef66eaf00de0633d5"}, + {file = "psutil-5.9.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b315febaebae813326296872fdb4be92ad3ce10d1d742a6b0c49fb619481ed0b"}, + {file = "psutil-5.9.2-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7929a516125f62399d6e8e026129c8835f6c5a3aab88c3fff1a05ee8feb840d"}, + {file = "psutil-5.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b3591616fa07b15050b2f87e1cdefd06a554382e72866fcc0ab2be9d116486c8"}, + {file = "psutil-5.9.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14b29f581b5edab1f133563272a6011925401804d52d603c5c606936b49c8b97"}, + {file = "psutil-5.9.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4642fd93785a29353d6917a23e2ac6177308ef5e8be5cc17008d885cb9f70f12"}, + {file = "psutil-5.9.2.tar.gz", hash = "sha256:feb861a10b6c3bb00701063b37e4afc754f8217f0f09c42280586bd6ac712b5c"}, +] +ptyprocess = [ + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, +] +pure-eval = [ + {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, + {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, +] +py = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] +pycodestyle = [ + {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, + {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, +] +pycparser = [ + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, +] +pydocstyle = [ + {file = "pydocstyle-6.1.1-py3-none-any.whl", hash = "sha256:6987826d6775056839940041beef5c08cc7e3d71d63149b48e36727f70144dc4"}, + {file = "pydocstyle-6.1.1.tar.gz", hash = "sha256:1d41b7c459ba0ee6c345f2eb9ae827cab14a7533a88c5c6f7e94923f72df92dc"}, +] +pyflakes = [ + {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, + {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, +] +pygments = [ + {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, + {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, +] +pylint = [ + {file = "pylint-2.15.3-py3-none-any.whl", hash = "sha256:7f6aad1d8d50807f7bc64f89ac75256a9baf8e6ed491cc9bc65592bc3f462cf1"}, + {file = "pylint-2.15.3.tar.gz", hash = "sha256:5fdfd44af182866999e6123139d265334267339f29961f00c89783155eacc60b"}, +] +pyparsing = [] +pyrsistent = [ + {file = "pyrsistent-0.18.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:df46c854f490f81210870e509818b729db4488e1f30f2a1ce1698b2295a878d1"}, + {file = "pyrsistent-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d45866ececf4a5fff8742c25722da6d4c9e180daa7b405dc0a2a2790d668c26"}, + {file = "pyrsistent-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ed6784ceac462a7d6fcb7e9b663e93b9a6fb373b7f43594f9ff68875788e01e"}, + {file = "pyrsistent-0.18.1-cp310-cp310-win32.whl", hash = "sha256:e4f3149fd5eb9b285d6bfb54d2e5173f6a116fe19172686797c056672689daf6"}, + {file = "pyrsistent-0.18.1-cp310-cp310-win_amd64.whl", hash = "sha256:636ce2dc235046ccd3d8c56a7ad54e99d5c1cd0ef07d9ae847306c91d11b5fec"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e92a52c166426efbe0d1ec1332ee9119b6d32fc1f0bbfd55d5c1088070e7fc1b"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7a096646eab884bf8bed965bad63ea327e0d0c38989fc83c5ea7b8a87037bfc"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cdfd2c361b8a8e5d9499b9082b501c452ade8bbf42aef97ea04854f4a3f43b22"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-win32.whl", hash = "sha256:7ec335fc998faa4febe75cc5268a9eac0478b3f681602c1f27befaf2a1abe1d8"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-win_amd64.whl", hash = "sha256:6455fc599df93d1f60e1c5c4fe471499f08d190d57eca040c0ea182301321286"}, + {file = "pyrsistent-0.18.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fd8da6d0124efa2f67d86fa70c851022f87c98e205f0594e1fae044e7119a5a6"}, + {file = "pyrsistent-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bfe2388663fd18bd8ce7db2c91c7400bf3e1a9e8bd7d63bf7e77d39051b85ec"}, + {file = "pyrsistent-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e3e1fcc45199df76053026a51cc59ab2ea3fc7c094c6627e93b7b44cdae2c8c"}, + {file = "pyrsistent-0.18.1-cp38-cp38-win32.whl", hash = "sha256:b568f35ad53a7b07ed9b1b2bae09eb15cdd671a5ba5d2c66caee40dbf91c68ca"}, + {file = "pyrsistent-0.18.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1b96547410f76078eaf66d282ddca2e4baae8964364abb4f4dcdde855cd123a"}, + {file = "pyrsistent-0.18.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f87cc2863ef33c709e237d4b5f4502a62a00fab450c9e020892e8e2ede5847f5"}, + {file = "pyrsistent-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bc66318fb7ee012071b2792024564973ecc80e9522842eb4e17743604b5e045"}, + {file = "pyrsistent-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:914474c9f1d93080338ace89cb2acee74f4f666fb0424896fcfb8d86058bf17c"}, + {file = "pyrsistent-0.18.1-cp39-cp39-win32.whl", hash = "sha256:1b34eedd6812bf4d33814fca1b66005805d3640ce53140ab8bbb1e2651b0d9bc"}, + {file = "pyrsistent-0.18.1-cp39-cp39-win_amd64.whl", hash = "sha256:e24a828f57e0c337c8d8bb9f6b12f09dfdf0273da25fda9e314f0b684b415a07"}, + {file = "pyrsistent-0.18.1.tar.gz", hash = "sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96"}, +] +pytest = [ + {file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"}, + {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, +] +pytest-cov = [ + {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, + {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, +] +pytest-mock = [ + {file = "pytest-mock-3.10.0.tar.gz", hash = "sha256:fbbdb085ef7c252a326fd8cdcac0aa3b1333d8811f131bdcc701002e1be7ed4f"}, + {file = "pytest_mock-3.10.0-py3-none-any.whl", hash = "sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b"}, +] +python-dateutil = [ + {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"}, +] +pytz = [ + {file = "pytz-2022.4-py2.py3-none-any.whl", hash = "sha256:2c0784747071402c6e99f0bafdb7da0fa22645f06554c7ae06bf6358897e9c91"}, + {file = "pytz-2022.4.tar.gz", hash = "sha256:48ce799d83b6f8aab2020e369b627446696619e79645419610b9facd909b3174"}, +] +pywin32 = [ + {file = "pywin32-304-cp310-cp310-win32.whl", hash = "sha256:3c7bacf5e24298c86314f03fa20e16558a4e4138fc34615d7de4070c23e65af3"}, + {file = "pywin32-304-cp310-cp310-win_amd64.whl", hash = "sha256:4f32145913a2447736dad62495199a8e280a77a0ca662daa2332acf849f0be48"}, + {file = "pywin32-304-cp310-cp310-win_arm64.whl", hash = "sha256:d3ee45adff48e0551d1aa60d2ec066fec006083b791f5c3527c40cd8aefac71f"}, + {file = "pywin32-304-cp311-cp311-win32.whl", hash = "sha256:30c53d6ce44c12a316a06c153ea74152d3b1342610f1b99d40ba2795e5af0269"}, + {file = "pywin32-304-cp311-cp311-win_amd64.whl", hash = "sha256:7ffa0c0fa4ae4077e8b8aa73800540ef8c24530057768c3ac57c609f99a14fd4"}, + {file = "pywin32-304-cp311-cp311-win_arm64.whl", hash = "sha256:cbbe34dad39bdbaa2889a424d28752f1b4971939b14b1bb48cbf0182a3bcfc43"}, + {file = "pywin32-304-cp36-cp36m-win32.whl", hash = "sha256:be253e7b14bc601718f014d2832e4c18a5b023cbe72db826da63df76b77507a1"}, + {file = "pywin32-304-cp36-cp36m-win_amd64.whl", hash = "sha256:de9827c23321dcf43d2f288f09f3b6d772fee11e809015bdae9e69fe13213988"}, + {file = "pywin32-304-cp37-cp37m-win32.whl", hash = "sha256:f64c0377cf01b61bd5e76c25e1480ca8ab3b73f0c4add50538d332afdf8f69c5"}, + {file = "pywin32-304-cp37-cp37m-win_amd64.whl", hash = "sha256:bb2ea2aa81e96eee6a6b79d87e1d1648d3f8b87f9a64499e0b92b30d141e76df"}, + {file = "pywin32-304-cp38-cp38-win32.whl", hash = "sha256:94037b5259701988954931333aafd39cf897e990852115656b014ce72e052e96"}, + {file = "pywin32-304-cp38-cp38-win_amd64.whl", hash = "sha256:ead865a2e179b30fb717831f73cf4373401fc62fbc3455a0889a7ddac848f83e"}, + {file = "pywin32-304-cp39-cp39-win32.whl", hash = "sha256:25746d841201fd9f96b648a248f731c1dec851c9a08b8e33da8b56148e4c65cc"}, + {file = "pywin32-304-cp39-cp39-win_amd64.whl", hash = "sha256:d24a3382f013b21aa24a5cfbfad5a2cd9926610c0affde3e8ab5b3d7dbcf4ac9"}, +] +pywinpty = [ + {file = "pywinpty-2.0.8-cp310-none-win_amd64.whl", hash = "sha256:9cbf89834abc8d4d4c5f295f11e15dd93889a8069db876f2bc10cc64aa4060ac"}, + {file = "pywinpty-2.0.8-cp37-none-win_amd64.whl", hash = "sha256:a2f9a95f3b74262ef73f1be5257c295c8caab1f79f081aa3400ca61c724f9bc6"}, + {file = "pywinpty-2.0.8-cp38-none-win_amd64.whl", hash = "sha256:23389d56258d6a1fbc4b41257bd65e5bdabaf6fde7f30a13806e557ea9ee6865"}, + {file = "pywinpty-2.0.8-cp39-none-win_amd64.whl", hash = "sha256:ea7c1da94eed5ef93e75026c67c60d4dca33ea9a1c212fa89221079a7b463c68"}, + {file = "pywinpty-2.0.8.tar.gz", hash = "sha256:a89b9021c63ef78b1e7d8e14f0fac4748c88a0c2e4f529c84f37f6e72b914280"}, +] +pyyaml = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] +pyzmq = [ + {file = "pyzmq-24.0.1-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:28b119ba97129d3001673a697b7cce47fe6de1f7255d104c2f01108a5179a066"}, + {file = "pyzmq-24.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bcbebd369493d68162cddb74a9c1fcebd139dfbb7ddb23d8f8e43e6c87bac3a6"}, + {file = "pyzmq-24.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae61446166983c663cee42c852ed63899e43e484abf080089f771df4b9d272ef"}, + {file = "pyzmq-24.0.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87f7ac99b15270db8d53f28c3c7b968612993a90a5cf359da354efe96f5372b4"}, + {file = "pyzmq-24.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9dca7c3956b03b7663fac4d150f5e6d4f6f38b2462c1e9afd83bcf7019f17913"}, + {file = "pyzmq-24.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8c78bfe20d4c890cb5580a3b9290f700c570e167d4cdcc55feec07030297a5e3"}, + {file = "pyzmq-24.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:48f721f070726cd2a6e44f3c33f8ee4b24188e4b816e6dd8ba542c8c3bb5b246"}, + {file = "pyzmq-24.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:afe1f3bc486d0ce40abb0a0c9adb39aed3bbac36ebdc596487b0cceba55c21c1"}, + {file = "pyzmq-24.0.1-cp310-cp310-win32.whl", hash = "sha256:3e6192dbcefaaa52ed81be88525a54a445f4b4fe2fffcae7fe40ebb58bd06bfd"}, + {file = "pyzmq-24.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:86de64468cad9c6d269f32a6390e210ca5ada568c7a55de8e681ca3b897bb340"}, + {file = "pyzmq-24.0.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:838812c65ed5f7c2bd11f7b098d2e5d01685a3f6d1f82849423b570bae698c00"}, + {file = "pyzmq-24.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dfb992dbcd88d8254471760879d48fb20836d91baa90f181c957122f9592b3dc"}, + {file = "pyzmq-24.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7abddb2bd5489d30ffeb4b93a428130886c171b4d355ccd226e83254fcb6b9ef"}, + {file = "pyzmq-24.0.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94010bd61bc168c103a5b3b0f56ed3b616688192db7cd5b1d626e49f28ff51b3"}, + {file = "pyzmq-24.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8242543c522d84d033fe79be04cb559b80d7eb98ad81b137ff7e0a9020f00ace"}, + {file = "pyzmq-24.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ccb94342d13e3bf3ffa6e62f95b5e3f0bc6bfa94558cb37f4b3d09d6feb536ff"}, + {file = "pyzmq-24.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6640f83df0ae4ae1104d4c62b77e9ef39be85ebe53f636388707d532bee2b7b8"}, + {file = "pyzmq-24.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a180dbd5ea5d47c2d3b716d5c19cc3fb162d1c8db93b21a1295d69585bfddac1"}, + {file = "pyzmq-24.0.1-cp311-cp311-win32.whl", hash = "sha256:624321120f7e60336be8ec74a172ae7fba5c3ed5bf787cc85f7e9986c9e0ebc2"}, + {file = "pyzmq-24.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:1724117bae69e091309ffb8255412c4651d3f6355560d9af312d547f6c5bc8b8"}, + {file = "pyzmq-24.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:15975747462ec49fdc863af906bab87c43b2491403ab37a6d88410635786b0f4"}, + {file = "pyzmq-24.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b947e264f0e77d30dcbccbb00f49f900b204b922eb0c3a9f0afd61aaa1cedc3d"}, + {file = "pyzmq-24.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ec91f1bad66f3ee8c6deb65fa1fe418e8ad803efedd69c35f3b5502f43bd1dc"}, + {file = "pyzmq-24.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:db03704b3506455d86ec72c3358a779e9b1d07b61220dfb43702b7b668edcd0d"}, + {file = "pyzmq-24.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:e7e66b4e403c2836ac74f26c4b65d8ac0ca1eef41dfcac2d013b7482befaad83"}, + {file = "pyzmq-24.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:7a23ccc1083c260fa9685c93e3b170baba45aeed4b524deb3f426b0c40c11639"}, + {file = "pyzmq-24.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:fa0ae3275ef706c0309556061185dd0e4c4cd3b7d6f67ae617e4e677c7a41e2e"}, + {file = "pyzmq-24.0.1-cp36-cp36m-win32.whl", hash = "sha256:f01de4ec083daebf210531e2cca3bdb1608dbbbe00a9723e261d92087a1f6ebc"}, + {file = "pyzmq-24.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:de4217b9eb8b541cf2b7fde4401ce9d9a411cc0af85d410f9d6f4333f43640be"}, + {file = "pyzmq-24.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:78068e8678ca023594e4a0ab558905c1033b2d3e806a0ad9e3094e231e115a33"}, + {file = "pyzmq-24.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77c2713faf25a953c69cf0f723d1b7dd83827b0834e6c41e3fb3bbc6765914a1"}, + {file = "pyzmq-24.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8bb4af15f305056e95ca1bd086239b9ebc6ad55e9f49076d27d80027f72752f6"}, + {file = "pyzmq-24.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0f14cffd32e9c4c73da66db97853a6aeceaac34acdc0fae9e5bbc9370281864c"}, + {file = "pyzmq-24.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0108358dab8c6b27ff6b985c2af4b12665c1bc659648284153ee501000f5c107"}, + {file = "pyzmq-24.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d66689e840e75221b0b290b0befa86f059fb35e1ee6443bce51516d4d61b6b99"}, + {file = "pyzmq-24.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ae08ac90aa8fa14caafc7a6251bd218bf6dac518b7bff09caaa5e781119ba3f2"}, + {file = "pyzmq-24.0.1-cp37-cp37m-win32.whl", hash = "sha256:8421aa8c9b45ea608c205db9e1c0c855c7e54d0e9c2c2f337ce024f6843cab3b"}, + {file = "pyzmq-24.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:54d8b9c5e288362ec8595c1d98666d36f2070fd0c2f76e2b3c60fbad9bd76227"}, + {file = "pyzmq-24.0.1-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:acbd0a6d61cc954b9f535daaa9ec26b0a60a0d4353c5f7c1438ebc88a359a47e"}, + {file = "pyzmq-24.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:47b11a729d61a47df56346283a4a800fa379ae6a85870d5a2e1e4956c828eedc"}, + {file = "pyzmq-24.0.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:abe6eb10122f0d746a0d510c2039ae8edb27bc9af29f6d1b05a66cc2401353ff"}, + {file = "pyzmq-24.0.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:07bec1a1b22dacf718f2c0e71b49600bb6a31a88f06527dfd0b5aababe3fa3f7"}, + {file = "pyzmq-24.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0d945a85b70da97ae86113faf9f1b9294efe66bd4a5d6f82f2676d567338b66"}, + {file = "pyzmq-24.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1b7928bb7580736ffac5baf814097be342ba08d3cfdfb48e52773ec959572287"}, + {file = "pyzmq-24.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b946da90dc2799bcafa682692c1d2139b2a96ec3c24fa9fc6f5b0da782675330"}, + {file = "pyzmq-24.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c8840f064b1fb377cffd3efeaad2b190c14d4c8da02316dae07571252d20b31f"}, + {file = "pyzmq-24.0.1-cp38-cp38-win32.whl", hash = "sha256:4854f9edc5208f63f0841c0c667260ae8d6846cfa233c479e29fdc85d42ebd58"}, + {file = "pyzmq-24.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:42d4f97b9795a7aafa152a36fe2ad44549b83a743fd3e77011136def512e6c2a"}, + {file = "pyzmq-24.0.1-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:52afb0ac962963fff30cf1be775bc51ae083ef4c1e354266ab20e5382057dd62"}, + {file = "pyzmq-24.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bad8210ad4df68c44ff3685cca3cda448ee46e20d13edcff8909eba6ec01ca4"}, + {file = "pyzmq-24.0.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:dabf1a05318d95b1537fd61d9330ef4313ea1216eea128a17615038859da3b3b"}, + {file = "pyzmq-24.0.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5bd3d7dfd9cd058eb68d9a905dec854f86649f64d4ddf21f3ec289341386c44b"}, + {file = "pyzmq-24.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8012bce6836d3f20a6c9599f81dfa945f433dab4dbd0c4917a6fb1f998ab33d"}, + {file = "pyzmq-24.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c31805d2c8ade9b11feca4674eee2b9cce1fec3e8ddb7bbdd961a09dc76a80ea"}, + {file = "pyzmq-24.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3104f4b084ad5d9c0cb87445cc8cfd96bba710bef4a66c2674910127044df209"}, + {file = "pyzmq-24.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:df0841f94928f8af9c7a1f0aaaffba1fb74607af023a152f59379c01c53aee58"}, + {file = "pyzmq-24.0.1-cp39-cp39-win32.whl", hash = "sha256:a435ef8a3bd95c8a2d316d6e0ff70d0db524f6037411652803e118871d703333"}, + {file = "pyzmq-24.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:2032d9cb994ce3b4cba2b8dfae08c7e25bc14ba484c770d4d3be33c27de8c45b"}, + {file = "pyzmq-24.0.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bb5635c851eef3a7a54becde6da99485eecf7d068bd885ac8e6d173c4ecd68b0"}, + {file = "pyzmq-24.0.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:83ea1a398f192957cb986d9206ce229efe0ee75e3c6635baff53ddf39bd718d5"}, + {file = "pyzmq-24.0.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:941fab0073f0a54dc33d1a0460cb04e0d85893cb0c5e1476c785000f8b359409"}, + {file = "pyzmq-24.0.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e8f482c44ccb5884bf3f638f29bea0f8dc68c97e38b2061769c4cb697f6140d"}, + {file = "pyzmq-24.0.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:613010b5d17906c4367609e6f52e9a2595e35d5cc27d36ff3f1b6fa6e954d944"}, + {file = "pyzmq-24.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:65c94410b5a8355cfcf12fd600a313efee46ce96a09e911ea92cf2acf6708804"}, + {file = "pyzmq-24.0.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:20e7eeb1166087db636c06cae04a1ef59298627f56fb17da10528ab52a14c87f"}, + {file = "pyzmq-24.0.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a2712aee7b3834ace51738c15d9ee152cc5a98dc7d57dd93300461b792ab7b43"}, + {file = "pyzmq-24.0.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a7c280185c4da99e0cc06c63bdf91f5b0b71deb70d8717f0ab870a43e376db8"}, + {file = "pyzmq-24.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:858375573c9225cc8e5b49bfac846a77b696b8d5e815711b8d4ba3141e6e8879"}, + {file = "pyzmq-24.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:80093b595921eed1a2cead546a683b9e2ae7f4a4592bb2ab22f70d30174f003a"}, + {file = "pyzmq-24.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f3f3154fde2b1ff3aa7b4f9326347ebc89c8ef425ca1db8f665175e6d3bd42f"}, + {file = "pyzmq-24.0.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abb756147314430bee5d10919b8493c0ccb109ddb7f5dfd2fcd7441266a25b75"}, + {file = "pyzmq-24.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44e706bac34e9f50779cb8c39f10b53a4d15aebb97235643d3112ac20bd577b4"}, + {file = "pyzmq-24.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:687700f8371643916a1d2c61f3fdaa630407dd205c38afff936545d7b7466066"}, + {file = "pyzmq-24.0.1.tar.gz", hash = "sha256:216f5d7dbb67166759e59b0479bca82b8acf9bed6015b526b8eb10143fb08e77"}, +] +qtconsole = [ + {file = "qtconsole-5.3.2-py3-none-any.whl", hash = "sha256:c29d24464f57cdbaa17d6f6060be6e6d5e29126e7feb57eebc1747433382b3d1"}, + {file = "qtconsole-5.3.2.tar.gz", hash = "sha256:8eadf012e83ab018295803c247c6ab7eacd3d5ab1e1d88a0f37fdcfdab9295a3"}, +] +qtpy = [ + {file = "QtPy-2.2.1-py3-none-any.whl", hash = "sha256:268cf5328f41353be1b127e04a81bc74ec9a9b54c9ac75dd8fe0ff48d8ad6ead"}, + {file = "QtPy-2.2.1.tar.gz", hash = "sha256:7d5231133b772e40b4ee514b6673aca558331e4b88ca038b26c9e16c5c95524f"}, +] +requests = [] +"ruamel.yaml" = [ + {file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"}, + {file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"}, +] +"ruamel.yaml.clib" = [ + {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6e7be2c5bcb297f5b82fee9c665eb2eb7001d1050deaba8471842979293a80b0"}, + {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:066f886bc90cc2ce44df8b5f7acfc6a7e2b2e672713f027136464492b0c34d7c"}, + {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:221eca6f35076c6ae472a531afa1c223b9c29377e62936f61bc8e6e8bdc5f9e7"}, + {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win32.whl", hash = "sha256:1070ba9dd7f9370d0513d649420c3b362ac2d687fe78c6e888f5b12bf8bc7bee"}, + {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:77df077d32921ad46f34816a9a16e6356d8100374579bc35e15bab5d4e9377de"}, + {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:cfdb9389d888c5b74af297e51ce357b800dd844898af9d4a547ffc143fa56751"}, + {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7b2927e92feb51d830f531de4ccb11b320255ee95e791022555971c466af4527"}, + {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win32.whl", hash = "sha256:ada3f400d9923a190ea8b59c8f60680c4ef8a4b0dfae134d2f2ff68429adfab5"}, + {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win_amd64.whl", hash = "sha256:de9c6b8a1ba52919ae919f3ae96abb72b994dd0350226e28f3686cb4f142165c"}, + {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d67f273097c368265a7b81e152e07fb90ed395df6e552b9fa858c6d2c9f42502"}, + {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:72a2b8b2ff0a627496aad76f37a652bcef400fd861721744201ef1b45199ab78"}, + {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:d3c620a54748a3d4cf0bcfe623e388407c8e85a4b06b8188e126302bcab93ea8"}, + {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win32.whl", hash = "sha256:9efef4aab5353387b07f6b22ace0867032b900d8e91674b5d8ea9150db5cae94"}, + {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:846fc8336443106fe23f9b6d6b8c14a53d38cef9a375149d61f99d78782ea468"}, + {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0847201b767447fc33b9c235780d3aa90357d20dd6108b92be544427bea197dd"}, + {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:78988ed190206672da0f5d50c61afef8f67daa718d614377dcd5e3ed85ab4a99"}, + {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:210c8fcfeff90514b7133010bf14e3bad652c8efde6b20e00c43854bf94fa5a6"}, + {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win32.whl", hash = "sha256:a49e0161897901d1ac9c4a79984b8410f450565bbad64dbfcbf76152743a0cdb"}, + {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:bf75d28fa071645c529b5474a550a44686821decebdd00e21127ef1fd566eabe"}, + {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a32f8d81ea0c6173ab1b3da956869114cae53ba1e9f72374032e33ba3118c233"}, + {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7f7ecb53ae6848f959db6ae93bdff1740e651809780822270eab111500842a84"}, + {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:61bc5e5ca632d95925907c569daa559ea194a4d16084ba86084be98ab1cec1c6"}, + {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win32.whl", hash = "sha256:89221ec6d6026f8ae859c09b9718799fea22c0e8da8b766b0b2c9a9ba2db326b"}, + {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:31ea73e564a7b5fbbe8188ab8b334393e06d997914a4e184975348f204790277"}, + {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dc6a613d6c74eef5a14a214d433d06291526145431c3b964f5e16529b1842bed"}, + {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1866cf2c284a03b9524a5cc00daca56d80057c5ce3cdc86a52020f4c720856f0"}, + {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:1b4139a6ffbca8ef60fdaf9b33dec05143ba746a6f0ae0f9d11d38239211d335"}, + {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win32.whl", hash = "sha256:3fb9575a5acd13031c57a62cc7823e5d2ff8bc3835ba4d94b921b4e6ee664104"}, + {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:825d5fccef6da42f3c8eccd4281af399f21c02b32d98e113dbc631ea6a6ecbc7"}, + {file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"}, +] +safety = [ + {file = "safety-2.3.1-py3-none-any.whl", hash = "sha256:8f098d12b607db2756886280e85c28ece8db1bba4f45fc5f981f4663217bd619"}, + {file = "safety-2.3.1.tar.gz", hash = "sha256:6e6fcb7d4e8321098cf289f59b65051cafd3467f089c6e57c9f894ae32c23b71"}, +] +send2trash = [ + {file = "Send2Trash-1.8.0-py3-none-any.whl", hash = "sha256:f20eaadfdb517eaca5ce077640cb261c7d2698385a6a0f072a4a5447fd49fa08"}, + {file = "Send2Trash-1.8.0.tar.gz", hash = "sha256:d2c24762fd3759860a0aff155e45871447ea58d2be6bdd39b5c8f966a0c99c2d"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +smmap = [ + {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, + {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, +] +snowballstemmer = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] +soupsieve = [ + {file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"}, + {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, +] +stack-data = [ + {file = "stack_data-0.5.1-py3-none-any.whl", hash = "sha256:5120731a18ba4c82cefcf84a945f6f3e62319ef413bfc210e32aca3a69310ba2"}, + {file = "stack_data-0.5.1.tar.gz", hash = "sha256:95eb784942e861a3d80efd549ff9af6cf847d88343a12eb681d7157cfcb6e32b"}, +] +stevedore = [ + {file = "stevedore-4.0.0-py3-none-any.whl", hash = "sha256:87e4d27fe96d0d7e4fc24f0cbe3463baae4ec51e81d95fbe60d2474636e0c7d8"}, + {file = "stevedore-4.0.0.tar.gz", hash = "sha256:f82cc99a1ff552310d19c379827c2c64dd9f85a38bcd5559db2470161867b786"}, +] +tabulate = [ + {file = "tabulate-0.8.10-py3-none-any.whl", hash = "sha256:0ba055423dbaa164b9e456abe7920c5e8ed33fcc16f6d1b2f2d152c8e1e8b4fc"}, + {file = "tabulate-0.8.10-py3.8.egg", hash = "sha256:436f1c768b424654fce8597290d2764def1eea6a77cfa5c33be00b1bc0f4f63d"}, + {file = "tabulate-0.8.10.tar.gz", hash = "sha256:6c57f3f3dd7ac2782770155f3adb2db0b1a269637e42f27599925e64b114f519"}, +] +terminado = [ + {file = "terminado-0.16.0-py3-none-any.whl", hash = "sha256:3e995072a7178a104c41134548ce9b03e4e7f0a538e9c29df4f1fbc81c7cfc75"}, + {file = "terminado-0.16.0.tar.gz", hash = "sha256:fac14374eb5498bdc157ed32e510b1f60d5c3c7981a9f5ba018bb9a64cec0c25"}, +] +tinycss2 = [ + {file = "tinycss2-1.1.1-py3-none-any.whl", hash = "sha256:fe794ceaadfe3cf3e686b22155d0da5780dd0e273471a51846d0a02bc204fec8"}, + {file = "tinycss2-1.1.1.tar.gz", hash = "sha256:b2e44dd8883c360c35dd0d1b5aad0b610e5156c2cb3b33434634e539ead9d8bf"}, +] +toml = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] +tomli = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] +tomlkit = [ + {file = "tomlkit-0.11.5-py3-none-any.whl", hash = "sha256:f2ef9da9cef846ee027947dc99a45d6b68a63b0ebc21944649505bf2e8bc5fe7"}, + {file = "tomlkit-0.11.5.tar.gz", hash = "sha256:571854ebbb5eac89abcb4a2e47d7ea27b89bf29e09c35395da6f03dd4ae23d1c"}, +] +tornado = [] +traitlets = [ + {file = "traitlets-5.4.0-py3-none-any.whl", hash = "sha256:93663cc8236093d48150e2af5e2ed30fc7904a11a6195e21bab0408af4e6d6c8"}, + {file = "traitlets-5.4.0.tar.gz", hash = "sha256:3f2c4e435e271592fe4390f1746ea56836e3a080f84e7833f0f801d9613fec39"}, +] +typing-extensions = [ + {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, + {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, +] +urllib3 = [ + {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, + {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, +] +virtualenv = [ + {file = "virtualenv-20.16.5-py3-none-any.whl", hash = "sha256:d07dfc5df5e4e0dbc92862350ad87a36ed505b978f6c39609dc489eadd5b0d27"}, + {file = "virtualenv-20.16.5.tar.gz", hash = "sha256:227ea1b9994fdc5ea31977ba3383ef296d7472ea85be9d6732e42a91c04e80da"}, +] +wcwidth = [ + {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, + {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, +] +webencodings = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] +widgetsnbextension = [ + {file = "widgetsnbextension-4.0.3-py3-none-any.whl", hash = "sha256:7f3b0de8fda692d31ef03743b598620e31c2668b835edbd3962d080ccecf31eb"}, + {file = "widgetsnbextension-4.0.3.tar.gz", hash = "sha256:34824864c062b0b3030ad78210db5ae6a3960dfb61d5b27562d6631774de0286"}, +] +wrapt = [ + {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, + {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, + {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, + {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, + {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, + {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, + {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, + {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, + {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, + {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, + {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, + {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, + {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, + {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, + {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, + {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, + {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, + {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, + {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, + {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, + {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, + {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, + {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, + {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, + {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, + {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, + {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, + {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, + {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, + {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, + {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, + {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, + {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, + {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, + {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, + {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, + {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, + {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, + {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, + {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, + {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, + {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, + {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, + {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, + {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, + {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, + {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, + {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, + {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, + {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, + {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, + {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, +] +zipp = [ + {file = "zipp-3.9.0-py3-none-any.whl", hash = "sha256:972cfa31bc2fedd3fa838a51e9bc7e64b7fb725a8c00e7431554311f180e9980"}, + {file = "zipp-3.9.0.tar.gz", hash = "sha256:3a7af91c3db40ec72dd9d154ae18e008c69efe8ca88dde4f9a731bb82fe2f9eb"}, +] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..cece210 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,72 @@ +[tool.poetry] +authors = [ + "Ariz Weber ", + "CorrelAid ", + "Daniel Pleus ", + "Felix Schmitz ", + "Frederik Hering ", + "Marco Hübner ", + "Michael Aydinbas ", +] +maintainers = [ + "Michael Aydinbas " +] +description = "Python wrapper for GENESIS web service interface (API) of the Federal Statistical Office." +name = "pystatis" +version = "0.1.0" +readme = "README.md" +repository = "" +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Operating System :: MacOS", + "Operating System :: Microsoft", + "Operating System :: POSIX", + "Operating System :: Unix", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Topic :: Scientific/Engineering", + "Topic :: Scientific/Engineering :: Information Analysis", + "Topic :: Software Development :: Libraries :: Python Modules" +] + +[tool.poetry.dependencies] +python = "^3.9" +requests = "^2.27.1" +pandas = "^1.4.3" +tabulate = "^0.8.10" + +[tool.poetry.dev-dependencies] +bandit = "^1.7.4" +black = "^22.3.0" +flake8-docstrings = "^1.6.0" +isort = "^5.10.1" +mypy = "^0.942" +pre-commit = "^2.18.1" +pylint = "^2.13.4" +pytest = "^7.1.1" +pytest-cov = "^3.0.0" +safety = "^2.0.0" +flake8 = "^4.0.1" +jupyter = "^1.0.0" +pytest-mock = "^3.8.2" + +[tool.black] +line-length = 80 +target-version = ['py39'] + +[build-system] +build-backend = "poetry.core.masonry.api" +requires = ["poetry-core>=1.0.0"] + +[tool.pytest.ini_options] +addopts = "-s -v" +log_cli = false + +[tool.isort] +profile = "black" +line_length = 80 diff --git a/src/pystatis/__init__.py b/src/pystatis/__init__.py new file mode 100644 index 0000000..6e37387 --- /dev/null +++ b/src/pystatis/__init__.py @@ -0,0 +1,30 @@ +"""pystatis is a Python wrapper for the GENESIS web service interface (API). + +Basic usage: + +```python +import pystatis as pstat +print("Version:", pstat.__version__) +``` +""" +from pystatis.cache import clear_cache +from pystatis.config import init_config +from pystatis.cube import Cube +from pystatis.find import Find +from pystatis.helloworld import logincheck, whoami +from pystatis.profile import change_password, remove_result +from pystatis.table import Table + +__version__ = "0.1.0" + +__all__ = [ + "change_password", + "clear_cache", + "Cube", + "Find", + "init_config", + "logincheck", + "remove_result", + "Table", + "whoami", +] diff --git a/src/pystatis/cache.py b/src/pystatis/cache.py new file mode 100644 index 0000000..1c0f0ec --- /dev/null +++ b/src/pystatis/cache.py @@ -0,0 +1,190 @@ +"""Module provides functions/decorators to cache downloaded data as well as remove cached data.""" +import hashlib +import json +import logging +import re +import shutil +import zipfile +from datetime import date +from pathlib import Path +from typing import Optional + +from pystatis.config import load_config + +logger = logging.getLogger(__name__) +JOB_ID_PATTERN = r"\d+" + + +def cache_data( + cache_dir: Path, + name: Optional[str], + params: dict, + data: str, +) -> None: + """Compress and archive data within the configured cache directory. + + Data will be stored in a zip file within the cache directory. + The folder structure will be `///. + This allows to cache different results for different params. + + Args: + cache_dir (Path): The cash directory as configured in the config. + name (str): The unique identifier in GENESIS-Online. + endpoint (str): The endpoint for this data request. + method (str): The method for this data request. + params (dict): The dictionary holding the params for this data request. + data (str): The actual raw text data as returned by GENESIS-Online. + """ + # pylint: disable=too-many-arguments + if name is None: + return + + data_dir = _build_file_path(cache_dir, name, params) + file_name = f"{str(date.today()).replace('-', '')}.txt" + + # create parent dirs, if necessary + file_path = data_dir / file_name + file_path.parent.mkdir(parents=True, exist_ok=True) + + # we have to first save the content to a text file, before we can add it to a + # compressed archive, and finally have to delete the file so only the archive remains + with open(file_path, "w", encoding="utf-8") as file: + file.write(data) + + with zipfile.ZipFile( + str(file_path).replace(".txt", ".zip"), + "w", + compression=zipfile.ZIP_DEFLATED, + compresslevel=9, + ) as myzip: + myzip.write(file_path, arcname=file_name) + + file_path.unlink() + logger.info("Data was successfully cached under %s.", file_path) + + +def read_from_cache( + cache_dir: Path, + name: Optional[str], + params: dict, +) -> str: + """Read and return compressed data from cache. + + Args: + cache_dir (Path): The cash directory as configured in the config. + name (str): The unique identifier in GENESIS-Online. + endpoint (str): The endpoint for this data request. + method (str): The method for this data request. + params (dict): The dictionary holding the params for this data request. + + Returns: + str: The uncompressed raw text data. + """ + if name is None: + return "" + + data_dir = _build_file_path(cache_dir, name, params) + + versions = sorted( + data_dir.glob("*"), + key=lambda path: int(path.stem), + ) + file_name = versions[-1].name + file_path = data_dir / file_name + with zipfile.ZipFile(file_path, "r") as myzip: + with myzip.open(file_name.replace(".zip", ".txt")) as file: + data = file.read().decode() + + return data + + +def _build_file_path(cache_dir: Path, name: str, params: dict) -> Path: + """Builds a unique cache directory name from name and hashed params dictionary. + + The way this method works is that it creates a path under cache dir that is unique + because the name is a unique EVAS identifier number in Destatis and the hash + is (close enough) unique to a given dictionary with query parameter values. + + Args: + cache_dir (Path): The root cache directory as configured in the config.ini. + name (str): The unique identifier for an object in Destatis. + params (dict): The query parameters for a given call to the Destatis API. + + Returns: + Path: The path object to the directory where the data will be downloaded/cached. + """ + params_ = params.copy() + # we have to delete the job key here because otherwise we will not have a cache hit + # we use 10 digits because this is enough security to avoid hash collisions + if "job" in params_: + del params_["job"] + params_hash = hashlib.blake2s(digest_size=10, usedforsecurity=False) + params_hash.update(json.dumps(params_).encode("UTF-8")) + data_dir = cache_dir / name / params_hash.hexdigest() + + return data_dir + + +def normalize_name(name: str) -> str: + """Normalize a Destatis object name by omitting the optional job id. + + Args: + name (str): The unique identifier in GENESIS-Online. + + Returns: + str: The unique identifier without the optional job id. + """ + if len(re.findall(JOB_ID_PATTERN, name)) == 3: + name = name.split("_")[0] + + return name + + +def hit_in_cash( + cache_dir: Path, + name: Optional[str], + params: dict, +) -> bool: + """Check if data is already cached. + + Args: + cache_dir (Path): The cash directory as configured in the config. + name (str): The unique identifier in GENESIS-Online. + endpoint (str): The endpoint for this data request. + method (str): The method for this data request. + params (dict): The dictionary holding the params for this data request. + + Returns: + bool: True, if combination of name, endpoint, method and params is already cached. + """ + if name is None: + return False + + data_dir = _build_file_path(cache_dir, name, params) + return data_dir.exists() + + +def clear_cache(name: Optional[str] = None) -> None: + """Clean the data cache completely or just a specified name. + + Args: + name (str, optional): Unique name to be deleted from cached data. + """ + config = load_config() + cache_dir = Path(config["DATA"]["cache_dir"]) + + # remove specified file (directory) from the data cache + # or clear complete cache (remove childs, preserve base) + file_paths = [cache_dir / name] if name is not None else cache_dir.iterdir() + + for file_path in file_paths: + # delete if file or symlink, otherwise remove complete tree + try: + if file_path.is_file() or file_path.is_symlink(): + file_path.unlink() + elif file_path.is_dir(): + shutil.rmtree(file_path) + except (OSError, ValueError, FileNotFoundError) as e: + logger.warning("Failed to delete %s. Reason: %s", file_path, e) + + logger.info("Removed files: %s", file_paths) diff --git a/src/pystatis/config.py b/src/pystatis/config.py new file mode 100644 index 0000000..415d120 --- /dev/null +++ b/src/pystatis/config.py @@ -0,0 +1,155 @@ +"""Module for handling settings.ini and config.ini files. + +This package stores core information in the settings.ini, which is stored under the user home directory. +The parent directory for the settings.ini is called after the package name. +The settings.ini gets automatically created by importing this package, if it does not exist already. +The config.ini is stored in a directory that is configured in the settings.ini via `config_dir`. +The config.ini holds all revelant information about the usage of GENESIS API like credentials. +If there is no config.ini in the given config_dir, a default config will be created with empty credentials. +""" +import logging +from configparser import ConfigParser +from pathlib import Path + +PKG_NAME = __name__.split(".", maxsplit=1)[0] + +logger = logging.getLogger(__name__) + +DEFAULT_CONFIG_DIR = Path().home() / f".{PKG_NAME}" +DEFAULT_SETTINGS_FILE = DEFAULT_CONFIG_DIR / "settings.ini" + + +def create_settings() -> None: + """Create a settings.ini file within the default config folder in the user home directory.""" + if not DEFAULT_SETTINGS_FILE.exists(): + default_settings = ConfigParser() + default_settings["SETTINGS"] = {"config_dir": str(DEFAULT_CONFIG_DIR)} + + _write_config(default_settings, DEFAULT_SETTINGS_FILE) + logger.info( + "Settings file was created. Path: %s.", DEFAULT_SETTINGS_FILE + ) + + +def load_settings() -> ConfigParser: + """Load the config from settings.ini. + + Returns: + ConfigParser: Sections and key-value pairs from settings.ini. + """ + settings_file = DEFAULT_SETTINGS_FILE + + settings = ConfigParser() + settings.read(settings_file) + + return settings + + +def get_config_path_from_settings() -> Path: + """Return full local path to config.ini. + + Returns: + Path: Path to config_dir / config.ini. + """ + settings = load_settings() + return Path(settings.get("SETTINGS", "config_dir")) / "config.ini" + + +def init_config( + username: str, password: str, config_dir: Path = DEFAULT_CONFIG_DIR +) -> None: + """One-time function to be called for new users to create a new config.ini with default values. + + Stores username and password for the GENESIS API, among other settings. + + Args: + username (str): username used to login to GENESIS-Online. + password (str): password used to login to GENESIS-Online. + config_dir (Path, optional): Path to the root config directory. Defaults to the user home directory. + """ + default_settings = load_settings() + default_settings["SETTINGS"]["config_dir"] = str(config_dir) + + _write_config(default_settings, DEFAULT_SETTINGS_FILE) + logger.info( + "Settings file updated: config_dir set to %s. Path: %s.", + config_dir, + DEFAULT_SETTINGS_FILE, + ) + + config_file = get_config_path_from_settings() + config = _create_default_config() + config["GENESIS API"]["username"] = username + config["GENESIS API"]["password"] = password + _write_config(config, config_file) + + cache_dir = Path(config["DATA"]["cache_dir"]) + if not cache_dir.exists(): + cache_dir.mkdir() + + logger.info("New config was created. Path: %s.", config_file) + + +def load_config() -> ConfigParser: + """Load the config from config.ini. + + Returns: + ConfigParser: Sections and key-value pairs from config.ini. + """ + config_file = get_config_path_from_settings() + config = _load_config(config_file) + + if config.has_section("GENESIS API"): + if not config.get("GENESIS API", "username") or not config.get( + "GENESIS API", "password" + ): + logger.critical( + "Username and/or password are missing! " + "Please make sure to fill in your username and password for GENESIS API. " + "Path: %s.", + config_file, + ) + + return config + + +def _write_config(config: ConfigParser, config_file: Path) -> None: + if not config_file.parent.exists(): + config_file.parent.mkdir(parents=True) + + with open(config_file, "w", encoding="utf-8") as fp: + config.write(fp) + + +def _load_config(config_file: Path) -> ConfigParser: + config = ConfigParser() + successful_reads = config.read(config_file) + + if not successful_reads: + logger.critical( + "Error while loading the config file. Could not find %s. " + "Please make sure to run init_config() first. ", + config_file, + ) + + return config + + +def _create_default_config() -> ConfigParser: + config = ConfigParser() + settings = load_settings() + config["GENESIS API"] = { + "base_url": "https://www-genesis.destatis.de/genesisWS/rest/2020/", + "username": "", + "password": "", + "doku": "https://www-genesis.destatis.de/genesis/misc/GENESIS-Webservices_Einfuehrung.pdf", + } + + config["DATA"] = { + "cache_dir": str(Path(settings["SETTINGS"]["config_dir"]) / "data") + } + + return config + + +create_settings() diff --git a/src/pystatis/cube.py b/src/pystatis/cube.py new file mode 100644 index 0000000..ba52689 --- /dev/null +++ b/src/pystatis/cube.py @@ -0,0 +1,201 @@ +"""Module provides functionality to parse cubefile data provided by GENESIS.""" +import copy +from typing import List + +import pandas as pd + +from pystatis.http_helper import load_data + + +class Cube: + """A wrapper class holding all relevant data and metadata about a given cube. + + Args: + name (str): The unique identifier of this cube. + raw_data (str): The raw cubefile data as returned by the /data/cubfile endpoint. + data (pd.DataFrame): The parsed data as a pandas data frame. + cube (dict): Metadata as returned by the /data/cubefile endpoint. + metadata (dict): Metadata as returned by the /metadata/cube endpoint. + """ + + def __init__(self, name: str): + self.name: str = name + self.raw_data = "" + self.data = pd.DataFrame() + self.cube: dict[str, pd.DataFrame] = {} + self.metadata: dict = {} + + def get_data(self, area: str = "all", **kwargs): + """Downloads raw data and metadata from GENESIS-Online. + + Additional keyword arguments are passed on to the GENESIS-Online GET request for cubefiles. + + Args: + area (str, optional): Area to search for the object in GENESIS-Online. Defaults to "all". + """ + params = {"name": self.name, "area": area} + + params |= kwargs + + raw_data = load_data( + endpoint="data", method="cubefile", params=params, as_json=False + ) + assert isinstance(raw_data, str) # nosec assert_used + self.raw_data = raw_data + self.cube = assign_correct_types(rename_axes(parse_cube(raw_data))) + self.data = self.cube["QEI"] + + metadata = load_data( + endpoint="metadata", method="cube", params=params, as_json=True + ) + assert isinstance(metadata, dict) # nosec assert_used + self.metadata = metadata + + +def parse_cube(data: str) -> dict: + """Main function for parsing a cubefile. + + Args: + data (str): The content of a cubefile as returned by GENESIS. + + Returns: + dict: A dictionary with each header type as key and the corresponding header block as value. + """ + cube = {} + header = None + data_block: List[List[str]] = [] + + for line in data.splitlines(): + # skip all rows until first header + if header is None and not _is_cube_metadata_header(line): + continue + + if _is_cube_metadata_header(line): + if data_block: + cube[header_type] = pd.DataFrame(data_block, columns=header) + + header = _get_cube_metadata_header(line, rename_duplicates=True) + header_type: str = _get_cube_metadata_header_type(line) + data_block = [] + continue + + line_content = _parse_cube_data_line(line) + data_block.append(line_content) + + # the last data block has no header after it so we have to do it here + # for cubes with more than one variable in DQI, we have to repeat the last four columns + if header: + last_four_columns = header[-4:] + header = header[:-4] + for var in cube["DQI"]["NAME"]: + header.extend([f"{var}_{col}" for col in last_four_columns]) + + cube[header_type] = pd.DataFrame(data_block, columns=header) + + return cube + + +def rename_axes( + cube: dict, + rename_classifying_variables: bool = True, + rename_time_variable: bool = True, +) -> dict: + """Rename the generic axes of a cubefile with the names found in the metadata. + + Args: + cube (dict): A dictionary holding the cube data as returned by `parse_cube()`. + rename_classifying_variables (bool, optional): If True, rename classifying variables. + Defaults to True. + rename_time_variable (bool, optional): If True, rename the time variable. + Defaults to True. + + Returns: + dict: Same dict as cube but with renamed axes for QEI. + """ + cube = copy.deepcopy(cube) + + old_cols = [] + new_cols = [] + + if rename_classifying_variables: + old_cols.extend( + [col for col in cube["QEI"].columns if col.startswith("FACH-SCHL")] + ) + new_cols.extend(cube["DQA"].sort_values("RHF-ACHSE")["NAME"].to_list()) + + if rename_time_variable: + old_cols.append("ZI-WERT") + new_cols.extend(cube["DQZ"]["NAME"].to_list()) + + cube["QEI"].rename(columns=dict(zip(old_cols, new_cols)), inplace=True) + + return cube + + +def assign_correct_types(cube: dict) -> dict: + """Assign correct value types to column 'WERT'. + + Args: + cube (dict): A dictionary holding the cube data as returned by `parse_cube()`. + + Returns: + dict: Same dict as cube but with changed column types for QEI. + """ + cube = copy.deepcopy(cube) + + for var, dtype in zip(cube["DQI"]["NAME"], cube["DQI"]["DST"]): + if dtype == "GANZ": + cast_type = int # type: ignore[assignment] + elif dtype == "FEST": + cast_type = float # type: ignore[assignment] + else: + cast_type = None # type: ignore[assignment] + + if cast_type is not None: + cube["QEI"][f"{var}_WERT"] = cube["QEI"][f"{var}_WERT"].astype( + cast_type + ) + + return cube + + +def _is_cube_metadata_header(line: str) -> bool: + """Check if a line is a cube metadata header.""" + return line[0] == "K" + + +def _get_cube_metadata_header_type(line: str) -> str: + """Return the header type.""" + return line.split(";")[1] + + +def _get_cube_metadata_header( + line: str, rename_duplicates: bool = False +) -> List[str]: + """Return the metadata header of a cubefile.""" + raw_header = line.split(";")[2:] + raw_header = [ + name + for name in raw_header + if name not in ['"nur Werte"', '"mit Werten"'] + ] + + if not rename_duplicates: + return raw_header + + # header can have multiple entries with same label, which is problematic for pandas + # so lets just add a counter + header = [""] * len(raw_header) + for name in set(raw_header): + if raw_header.count(name) == 1: + header[raw_header.index(name)] = name + else: + for counter in range(raw_header.count(name)): + header[raw_header.index(name) + counter] = f"{name}-{counter+1}" + + return header + + +def _parse_cube_data_line(line: str) -> List[str]: + """Return the content of a cube data line.""" + return line.split(";")[1:] diff --git a/src/pystatis/custom_exceptions.py b/src/pystatis/custom_exceptions.py new file mode 100644 index 0000000..2b09525 --- /dev/null +++ b/src/pystatis/custom_exceptions.py @@ -0,0 +1,7 @@ +"""Define custom "speaking" Exception and Error classes.""" + + +class DestatisStatusError(ValueError): + """Raised when Destatis status code indicates an error ("Fehler")""" + + pass diff --git a/src/pystatis/data/evas.csv b/src/pystatis/data/evas.csv new file mode 100644 index 0000000..4733815 --- /dev/null +++ b/src/pystatis/data/evas.csv @@ -0,0 +1,306 @@ +EVAS ;Beschreibung +1;Gebiet, Bevölkerung, Erwerbstätigkeit, Wahlen +2;Bildung, Sozialleistungen, Gesundheit, Rechtspflege +3;Wohnen, Umwelt +4;Wirtschaftsbereiche +5;Außenhandel, Unternehmen, Handwerk +6;Preise, Verdienste, Einkommen und Verbrauch +7;Öffentliche Finanzen, Steuern und Personal im öffentlichen Dienst +8;Gesamtrechnungen +9;Sonderbereich - interne Zwecke +9;Sonderbereiche +10;Sonderbereich - Leitmaterialien +11;Gebiet +12;Bevölkerung +13;Erwerbstätigkeit +14;Wahlen +19;Andere (für Länder- oder Bundeszwecke) - Gebiet, Bevölkerung, Erwerbstätigkeit, Wahlen +21;Bildung und Kultur, Forschung und Entwicklung +22;Öffentliche Sozialleistungen +23;Gesundheitswesen +24;Rechtspflege +29;Andere (für Länder- oder Bundeszwecke) - Bildung, Sozialleistungen, Gesundheit, Rechtspflege +31;Gebäude und Wohnen +32;Umwelt +33;Flächennutzung +39;Andere (für Länder- oder Bundeszwecke) - Wohnen, Umwelt +41;Land- und Forstwirtschaft, Fischerei +42;Produzierendes Gewerbe: Bereich Verarbeitendes Gewerbe, Bergbau und Gewinnung von Steinen und Erden +43;Produzierendes Gewerbe: Bereich Energieversorgung, Wasserversorgung, Abwasser- und Abfallentsorgung, Beseitigung von Umweltverschmutzungen +44;Produzierendes Gewerbe: Bereich Baugewerbe +45;Handel (einschl. Instandhaltung und Reparatur von Kfz), Gastgewerbe, Tourismus +46;Transport und Verkehr +47;Finanz- und andere Dienstleistungen +48;Wirtschaftsbereichsübergreifende Ergebnisse +49;Andere (für Länder- oder Bundeszwecke) - Wirtschaftsbereiche +51;Außenhandel +52;Unternehmen und Arbeitsstätten +53;Handwerk und handwerksähnliches Gewerbe +59;Andere (für Länder- oder Bundeszwecke) - Außenhandel, Unternehmen, Handwerk +61;Preise +62;Verdienste, Arbeitskosten +63;Freiwillige Erhebungen zu Einkommen, Ausgaben und Lebensbedingungen privater Haushalte +69;Andere (für Länder- oder Bundeszwecke) - Preise, Verdienste, Einkommen und Verbrauch +71;Öffentliche Finanzen +72;Öffentliche Fonds, Einrichtungen und Unternehmen mit eigenem Rechnungswesen - (Stillgelegt am 01.05.2015) +73;Steuern +74;Personal im öffentlichen Dienst +75;Berichtskreismanagement (BKM) +79;Andere (für Länder- oder Bundeszwecke) - Öffentliche Finanzen, Steuern und Personal im öffentlichen Dienst +81;VGR des Bundes +82;VGR der Länder +83;Zahlungsbilanz, Auslandsvermögen +84;Geld, Zinsen, Währungen +85;UGR +86;UGR der Länder +87;Sozioökonomisches Berichtssystem +88;Gesundheitsökonomische Gesamtrechnung (GGR) der Länder +89;Andere (für Länder- oder Bundeszwecke) - Gesamtrechnungen +90;Sonderbereich - interne Zwecke +91;Auslandsstatistische Informationen +92;Forschung und Entwicklung +93;Weiterentwicklung der Haushaltsstatistiken +94;EVAS-Nummern für die Altdateninventur +95;Bereichsübergreifende Statistiken, Register o.ä. +99;Andere (für Länder- oder Bundeszwecke) - Sonderbereiche +111;Gebietsstand +119;Sonstiges im Bereich Gebiet +121;Volkszählungen +122;Mikrozensus +123;Haushaltspanel +124;Bevölkerungsstand, -vorausberechnung +125;Einbürgerungen, Ausländer +126;Natürliche Bevölkerungsbewegungen +127;Wanderungen +129;Sonstiges im Bereich Bevölkerung +131;Beschäftigte +132;Arbeitsmarkt +133;Erwerbstätige +139;Sonstiges im Bereich Erwerbstätigkeit +141;Bundestagswahlen +142;Europawahlen +143;Landtagswahlen +144;Kommunalwahlen +145;Volksentscheide +149;Sonstiges im Bereich Wahlen +191;Länderstatistiken im Bereich Gebiet +192;Länderstatistiken im Bereich Bevölkerung +193;Länderstatistiken im Bereich Erwerbstätigkeiten +194;Länderstatistiken im Bereich Wahlen +199;Geschäftsstatistiken des Statistischen Bundesamtes im Bereich - Gebiet, Bevölkerung, Erwerbstätigkeit, Wahlen +211;Allgemeinbildende und berufliche Schulen +212;Berufsbildung +213;Hochschulen +214;Ausbildungsförderung +215;Weiterbildung +216;Kultur +217;Bildungsberichterstattung +218;Forschung und Entwicklung +219;Sonstiges im Bereich Bildung und Kultur, Forschung und Entwicklung +221;Sozialhilfe +222;Asylbewerberleistungen +223;Wohngeld +224;Pflege +225;Kinder- und Jugendhilfe +226;Sozialversicherungen +227;Behinderte, Kriegsopfer +228;Sozialberichterstattung und Statistiken nach dem Prostituiertenschutzgesetz +229;Sonstiges im Bereich öffentliche Sozialleistungen +231;Krankenhausstatistik +232;Todesursachen +233;Schwangerschaftsabbrüche +234;Meldepflichtige Krankheiten +235;Berufe des Gesundheitswesens +236;Gesundheitsbezogene Rechensysteme +237;Ambulante Diagnosestatistik +239;Sonstiges im Bereich Gesundheitswesen +241;Gerichte und Personal der Rechtspflege +242;Justizgeschäftsstatistiken +243;Strafverfolgung und -vollzug +244;Bewährungshilfe +249;Sonstiges im Bereich Rechtspflege +291;Länderstatistiken im Bereich Bildung und Kultur, Forschung und Entwicklung +292;Länderstatistiken im Bereich öffentliche Sozialleistungen +293;Länderstatistiken im Bereich Gesundheitswesen +294;Länderstatistiken im Bereich Rechtspflege +299;Geschäftsstatistiken des Statistischen Bundesamtes im Bereich Bildung, Sozialleistungen, Gesundheit und Rechtspflege +311;Bautätigkeit +312;Gebäude und Wohnungen +313;Finanzierung des Wohnungsbaus +319;Sonstiges im Bereich Gebäude und Wohnen +321;Abfallwirtschaft +322;Wasserversorgung und Abwasserentsorgung +323;Wassergefährdende Stoffe +324;Klimawirksame Stoffe +325;Umweltschutzausgaben und -produkte +329;Sonstiges im Bereich Umwelt +331;Flächenerhebungen +339;Sonstiges im Bereich Flächennutzung +391;Länderstatistiken im Bereich Gebäude und Wohnen +392;Länderstatistiken im Bereich Umwelt +393;Länderstatistiken im Bereich Flächennutzung +399;Geschäftsstatistiken des Statistischen Bundesamtes im Bereich Wohnen, Umwelt +411;Struktur der land- und forstwirtschaftlichen Betriebe +412;Bodennutzung und Ernte +413;Viehbestand und tierische Erzeugung +414;Ernährungswirtschaft +419;Sonstiges im Bereich Land- und Forstwirtschaft, Fischerei +421;Konjunkturerhebungen im Bereich Verarbeitendes Gewerbe, Bergbau und Gewinnung von Steinen und Erden +422;Strukturerhebungen im Bereich Verarbeitendes Gewerbe, Bergbau und Gewinnung von Steinen und Erden +423;Fachstatistiken einzelner Zweige im Bereich Verarbeitendes Gewerbe, Bergbau und Gewinnung von Steinen und Erden +429;Sonstiges im Bereich Verarbeitendes Gewerbe, Bergbau und Gewinnung von Steinen und Erden +431;Konjunkturerhebungen im Bereich Energie- und Wasserversorgung +432;Strukturerhebungen im Bereich Energieversorgung, Wasserversorgung, Abwasser- und Abfallentsorgung, Beseitigung von Umweltverschmutzungen +433;Fachstatistiken im Bereich Energie- und Wasserversorgung: Elektrizität- und Gasversorgung +434;Fachstatistiken im Bereich Energie- und Wasserversorgung: Wärmeversorgung +435;Übrige Fachstatistiken im Bereich Energie- und Wasserversorgung +439;Sonstiges im Bereich Energie- und Wasserversorgung +441;Konjunkturerhebungen im Bereich Baugewerbe +442;Strukturerhebungen im Bereich Baugewerbe +449;Sonstiges im Bereich Baugewerbe +451;Handels- und Gaststättenzählung +452;Konjunkturstatistiken im Bereich Handel (einschl. Instandhaltung und Reparatur von Kfz), Gastgewerbe +453;Strukturstatistiken im Bereich Handel (einschl. Instandhaltung und Reparatur von Kfz), Gastgewerbe +454;Fachstatistiken in einzelnen Zweigen des Bereichs Handel (einschl. Instandhaltung und Reparatur von Kfz), Gastgewerbe, Tourismus +456;Kfz-Handel, Instandhaltung +459;Sonstiges im Bereich Handel (einschl. Instandhaltung und Reparatur von Kfz), Gastgewerbe, Tourismus +461;Eisenbahnverkehr und Straßenpersonenverkehr +462;Straßenverkehr (ohne Personenbeförderung) +463;Binnen- und Seeschifffahrt +464;Luftverkehr +465;Nachrichtenübermittlung +469;Sonstiges im Bereich Transport und Verkehr +471;Wertpapiermärkte +472;Kreditinstitute +473;Versicherungen +474;Dienstleistungen +479;Sonstiges im Bereich Finanz- und andere Dienstleistungen +481;Strukturstatistiken der Unternehmen +482;Flexibles Modul der strukturellen Unternehmensstatistik +491;Länderstatistiken im Bereich Land- und Forstwirtschaft, Fischerei +492;Länderstatistiken im Bereich Produzierendes Gewerbe: Bereich Verarbeitendes Gewerbe, Bergbau und Gewinnung von Steinen und Erden +493;Länderstatistiken im Bereich Produzierendes Gewerbe: Bereich Energie- und Wasserversorgung +494;Länderstatistiken im Bereich Produzierendes Gewerbe: Bereich Baugewerbe +495;Länderstatistiken im Bereich Handel sowie Instandhaltung und Reparatur von Kfz und Gebrauchsgütern, Gastgewerbe, Tourismus +496;Länderstatistiken im Bereich Verkehr und Nachrichtenübermittlung +497;Länderstatistiken im Bereich Finanz- und andere Dienstleistungen +499;Geschäftsstatistiken des Statistischen Bundesamtes im Bereich Wirtschaftsbereiche +511;Intrahandel +512;Extrahandel +519;Sonstiges im Bereich Außenhandel +521;Unternehmensregister +522;Arbeitsstätten +523;Gewerbeanzeigen, -aufsicht +524;Insolvenzen +525;Kostenstrukturen +529;Sonstiges im Bereich Unternehmen und Arbeitsstätten +531;Handwerkszählungen +532;Handwerksberichterstattungen +539;Sonstiges im Bereich Handwerk und handwerksähnliches Gewerbe +591;Länderstatistiken im Bereich Außenhandel +592;Länderstatistiken im Bereich Unternehmen und Arbeitsstätten +593;Länderstatistiken im Bereich Handwerk und handwerksähnliches Gewerbe +599;Geschäftsstatistiken des Bundes im Bereich Außenhandel, Unternehmen, Handwerk +611;Verbraucherpreise +612;Agrarpreise, Erzeugerpreise gewerblicher Produkte, Großhandelspreise, Baupreise +613;Preise für Dienstleistungen +614;Außenhandelspreise +615;Bodenmarkt +616;Preisvergleiche mit dem Ausland +619;Sonstiges im Bereich Preise +621;Verdienststrukturen +622;Tarifverdienste +623;Laufende Verdiensterhebungen +624;Arbeitskosten +629;Sonstiges im Bereich Verdienste, Arbeitskosten +631;Laufende Wirtschaftsrechnungen +632;Einkommens- und Verbrauchsstichproben +633;Dauerstichprobe befragungsbereiter Haushalte +634;Gemeinschaftsstatistik über Einkommen und Lebensbedingungen (EU-SILC) +635;Überschuldungsstatistik +639;Sonstiges im Bereich Wirtschaftsrechnungen privater Haushalte +691;Länderstatistiken im Bereich Preise +692;Länderstatistiken im Bereich Löhne und Gehälter, Arbeitskosten +693;Länderstatistiken im Bereich Freiwillige Erhebungen zu Einkommen, Ausgaben und Lebensbedingungen privater Haushalte +699;Geschäftsstatistiken des Bundes im Bereich Preise, Verdienste, Einkommen und Verbrauch +711;Haushaltsansätze +712;Steuerhaushalt +713;Schulden +714;Finanzvermögen +715;Vierteljährliche Kassenergebnisse +716;Vierteljahresdaten der kaufmännisch buchenden öffentlichen Fonds, Einrichtungen und Unternehmen +717;Rechnungsergebnisse +718;Jahresabschlüsse der kaufmännisch buchenden öffentlichen Fonds, Einrichtungen und Unternehmen +719;Sonstiges im Bereich Öffentliche Finanzen +721;Jahres- und Vierteljahresabschlüsse - (Stillgelegt am 01.05.2015) +722;Schulden - (Stillgelegt am 01.05.2015) +723;Vermögen - (Stillgelegt am 01.05.2015) +729;Sonstiges im Bereich Öffentliche Fonds, Einrichtungen und Unternehmen mit eigenem Rechnungswesen - (Stillgelegt am 01.05.2015) +731;Lohn- und Einkommensteuer +732;Körperschaftsteuer +733;Umsatzsteuer +734;Verbrauchsteuern - (Stillgelegt am 01.01.2015) +735;Gewerbesteuern +736;Steuern vom Vermögen +737;Steuerverteilung +739;Sonstiges im Bereich Steuern +741;Personalstand +742;Versorgungsempfänger +749;Sonstiges im Bereich Personal im öffentlichen Dienst +751;Berichtskreismanagement Finanz- und Personalstatistiken +791;Länderstatistiken im Bereich Öffentliche Finanzen +792;Länderstatistiken im Bereich Öffentliche Fonds, Einrichtungen und Unternehmen mit eigenem Rechnungswesen - (Stillgelegt am 01.01.2015) +793;Länderstatistiken im Bereich Steuern +794;Länderstatistiken im Bereich Personal im öffentlichen Dienst +799;Geschäftsstatistiken des Bundes im Bereich Öffentliche Finanzen, Steuern und Personal im öffentlichen Dienst +811;Entstehung und Verwendung des Inlandsprodukts +812;Verteilung und Umverteilung des Nationaleinkommens +813;Einnahmen und Ausgaben des Staats +814;Außenwirtschaft +815;Input-Output-Rechnung +816;Vermögensrechnung +817;Satellitensysteme +819;Sonstiges im Bereich VGR des Bundes +821;Entstehungsrechnung +822;Verteilungsrechnung Inländerkonzept +823;Verteilungsrechnung Inlandskonzept +824;Umverteilungsrechnung +825;Verwendungsrechnung +826;VGR-Bezugszahlen +827;Kreisberechnungen +829;Sonstiges im Bereich VGR der Länder +831;Zahlungsbilanz +832;Auslandsvermögen +839;Sonstiges im Bereich Zahlungsbilanz, Auslandsvermögen +841;Bankstatistische Gesamtrechnungen +842;Statistiken der Deutschen Bundesbank +843;Zinsen und Währungen +849;Sonstiges im Bereich Geld, Zinsen, Währungen +851;Material- und Energieflussrechnungen +852;Nutzung von Fläche und Raum +853;Umweltzustand +854;Maßnahmen des Umweltschutzes +855;Vermeidungskosten +859;Sonstiges im Bereich UGR +861;Material- und Energieflussrechungen +862;Nutzung von Fläche und Raum +863;Umweltzustand +864;Maßnahmen des Umweltschutzes +865;Vermeidungskosten +869;Sonstiges im Bereich UGR der Länder +871;Sozioökonomisches Berichtssystem +892;Länderstatistiken im Bereich VGR der Länder +893;Länderstatistiken im Bereich Zahlungsbilanz, Auslandsvermögen +894;Länderstatistiken im Bereich Geld, Zinsen, Währungen +895;Länderstatistiken im Bereich UGR +899;Geschäftsstatistiken des Bundes im Bereich Gesamtrechnungen +921;Ausgaben und Einnahmen für Wissenschaft und Forschung +922;Nationale und internationale Berichterstattung über Forschung und Entwicklung +929;Sonstiges im Bereich Forschung und Entwicklung +931;Test der Teilnahmebereitschaft +941;EVAS-Nummern für die Altdateninventur +951;Register +991;Länderstatistiken im Bereich Auslandsstatistische Informationen +992;Länderstatistiken im Bereich Forschung und Entwicklung +993;Indikatoren zur nachhaltigen Entwicklung +999;Geschäftsstatistiken des Bundes in Sonderbereichen diff --git a/src/pystatis/find.py b/src/pystatis/find.py new file mode 100644 index 0000000..5715998 --- /dev/null +++ b/src/pystatis/find.py @@ -0,0 +1,280 @@ +"""Implements find endpoint to retrieve results based on query""" +import pandas as pd + +from pystatis.http_helper import load_data + +pd.set_option("max_colwidth", None) +pd.set_option("expand_frame_repr", False) + + +class Results: + """ + A class representing the result object of variables, statistics, cubes and tables. + + Attributes: + df (pd.DataFrame): The DataFrame that contains the data. + category (str): Category (plural) of the result. E.g. "tables", "cubes". + + Methods: + get_code(): Gets code based on the index of the object. + get_metadata(): Gets metadata based on the index of the object. + """ + + def __init__(self, result: pd.DataFrame, category: str) -> None: + """ + Class that contains the results of a find query. + + Args: + result (pd.DataFrame): Result of a search query. + category (str): Category of the result. E.g. "tables", "cubes" + """ + self.df = result + self.category = category + + def __repr__(self) -> str: + return self.__str__() + + def __str__(self) -> str: + return str(self.df.to_markdown()) + + def __len__(self) -> int: + if len(self.df) > 0: + return len(self.df) + else: + return 0 + + def get_code(self, row_numbers: list) -> list: + """ + Returns the code for a given list of tables. + + Args: + row_numbers (list): A list that contains the row numbers from the results objects. This is not the object + code." + Returns: + table codes (list): Contains the corresponding tables codes. + """ + + codes = self.df.iloc[row_numbers]["Code"] + return list(codes) + + def get_metadata(self, row_numbers: list) -> None: + """ + Prints meta data for a given list of tables. + + Args: + row_numbers (list): A list that contains the row_numbers from the results objects. This is not the object + code." + """ + codes = self.df.iloc[row_numbers]["Code"] + + for code, ix in zip(codes, row_numbers): + response = self._get_metadata_results( + self.category[0:-1], code + ) # Category is truncated, because + # metadata endpoints works with singulars + + if self.category == "tables": + structure_dict = response["Object"]["Structure"] + + output = "\n".join( + [ + f"{self.category.upper()} {code} - {ix}", + "Name:", + structure_dict["Head"]["Content"], + f"{'-' * 20}", + "Columns:", + "\n".join( + [ + col["Content"] + for col in structure_dict["Columns"] + ] + ), + f"{'-' * 20}", + "Rows:", + "\n".join( + [row["Content"] for row in structure_dict["Rows"]] + ), + f"{'-' * 40}", + ] + ) + + elif self.category == "cubes": + axis_dict = response["Object"]["Structure"]["Axis"] + + output = "\n".join( + [ + f"{self.category.upper()} {code} - {ix}", + "Name:", + response["Object"]["Content"], + f"{'-' * 20}", + "Content:", + "\n".join( + [content["Content"] for content in axis_dict] + ), + f"{'-' * 40}", + ] + ) + + elif self.category == "statistics": + structure_dict = response["Object"] + + output = "\n".join( + [ + f"{self.category.upper()} {code} - {ix}", + "Name:", + response["Object"]["Content"], + f"{'-' * 20}", + "Content:", + "\n".join( + [ + f"{structure_dict[content]} {content}" + for content in ["Cubes", "Variables", "Updated"] + ] + ), + f"{'-' * 40}", + ] + ) + + elif self.category == "variables": + object_dict = response["Object"] + + output = "\n".join( + [ + f"{self.category.upper()} {code} - {ix}", + "Name:", + object_dict["Content"], + f"{'-' * 20}", + "Information:", + str(object_dict["Information"]), + f"{'-' * 40}", + ] + ) + + print(output) + + @staticmethod + def _get_metadata_results(category: str, code: str) -> dict: + """ + Based on the category and code query parameters the metadata will be generated. + + Args: + category (str): Category of the result. E.g. "tables", "cubes" + code (str): The code (identifier) of the relevant category object. + Returns: + response (json): The response as a json. + """ + params = { + "name": code, + } + + response = load_data( + endpoint="metadata", method=category, params=params, as_json=True + ) + assert isinstance(response, dict) # nosec assert_used + + return response + + +class Find: + """ + A class representing the find object that includes Result objects for variables, statistics, cubes and tables. + + Attributes: + query (str): The query that is provided to find endpoint. + statistics (Results): Statistics that match with the query. + tables (Results): Tables that match with the query. + variables (Results): Variables that match with the query. + cubes (Results): Cubes that match with the query. + + Methods: + run(): Queries the API and prints summary. + summary(): Prints summary of all results. + """ + + def __init__(self, query: str, top_n_preview: int = 5) -> None: + """Method for retrieving data from find endpoint. + + Args: + query (str): The query that is provided to find endpoint. + top_n_preview (int): Number of previews in print summary. + """ + self.query = query + + self.top_n_preview = top_n_preview + self.statistics = Results(pd.DataFrame(), "statistics") + self.variables = Results(pd.DataFrame(), "variables") + self.tables = Results(pd.DataFrame(), "tables") + self.cubes = Results(pd.DataFrame(), "cubes") + + self.is_run = False + + def run(self): + self.statistics = self._get_find_results("statistics") + self.variables = self._get_find_results("variables") + self.tables = self._get_find_results("tables") + self.cubes = self._get_find_results("cubes") + + self.is_run = True + + print(self.summary()) + + def summary(self): + """ + Returns: + summary_string: String that contains summary statistics. + """ + + if self.is_run: + return "\n".join( + [ + "##### Results #####", + f"{'-' * 40}", + f"# Number of tables: {len(self.tables.df)}", + "# Preview:", + self.tables.df.iloc[: self.top_n_preview].to_markdown(), + f"{'-' * 40}" + f"# Number of statistics: {len(self.statistics.df)}", + "# Preview:", + self.statistics.df.iloc[: self.top_n_preview].to_markdown(), + f"{'-' * 40}", + f"# Number of variables: {len(self.variables.df)}", + "# Preview:", + self.variables.df.iloc[: self.top_n_preview].to_markdown(), + f"{'-' * 40}", + f"# Number of cubes: {len(self.cubes.df)}", + "# Preview:", + self.cubes.df.iloc[: self.top_n_preview].to_markdown(), + f"{'-' * 40}", + "# Use object.tables, object.statistics, object.variables or object.cubes to get all results.", + f"{'-' * 40}", + ] + ) + else: + return "No data found. Please use .run() to retrieve data." + + def _get_find_results(self, category: str, **kwargs) -> Results: + """ + Based on the query (term), category and additional query parameters a Result object will be created. + + Args: + category (str): Category of the result. E.g. "tables", "cubes" + query_params (dict, optional): Additional query parameters (Default: None) + Returns: + pd.DataFrame + """ + + params = { + "term": self.query, + "category": category, + } + + params |= kwargs + + response = load_data( + endpoint="find", method="find", params=params, as_json=True + ) + assert isinstance(response, dict) # nosec assert_used + response_dict = response[category.capitalize()] + response_df = pd.DataFrame(response_dict).replace("\n", " ", regex=True) + + return Results(response_df, category) diff --git a/src/pystatis/helloworld.py b/src/pystatis/helloworld.py new file mode 100644 index 0000000..865c853 --- /dev/null +++ b/src/pystatis/helloworld.py @@ -0,0 +1,49 @@ +"""Module provides wrapper for HelloWorld GENESIS REST-API functions.""" + +import requests + +from pystatis.config import load_config +from pystatis.http_helper import _check_invalid_status_code + + +def whoami() -> str: + """ + Wrapper method which constructs an URL for testing the Destatis API + whoami method, which returns host name and IP address. + + Returns: + str: text test response from Destatis + """ + config = load_config() + url = f"{config['GENESIS API']['base_url']}" + "helloworld/whoami" + + response = requests.get(url, timeout=(1, 15)) + + _check_invalid_status_code(response) + + return str(response.text) + + +def logincheck() -> str: + """ + Wrapper method which constructs an URL for testing the Destatis API + logincheck method, which tests the login credentials (from the config.ini). + + Returns: + str: text logincheck response from Destatis + """ + config = load_config() + url = f"{config['GENESIS API']['base_url']}" + "helloworld/logincheck" + + params = { + "username": config["GENESIS API"]["username"], + "password": config["GENESIS API"]["password"], + } + + response = requests.get(url, params=params, timeout=(1, 15)) + + # NOTE: Cannot use get_data_from_endpoint due to colliding + # and misleading usage of "Status" key in API response + _check_invalid_status_code(response) + + return str(response.text) diff --git a/src/pystatis/http_helper.py b/src/pystatis/http_helper.py new file mode 100644 index 0000000..689eea2 --- /dev/null +++ b/src/pystatis/http_helper.py @@ -0,0 +1,301 @@ +"""Wrapper module for the data endpoint.""" +import json +import logging +import re +import time +from pathlib import Path +from typing import Union + +import requests + +from pystatis.cache import ( + cache_data, + hit_in_cash, + normalize_name, + read_from_cache, +) +from pystatis.config import load_config +from pystatis.custom_exceptions import DestatisStatusError + +logger = logging.getLogger(__name__) + +JOB_ID_PATTERN = re.compile(r"\d+-\d+_\d+") +JOB_TIMEOUT = 60 + + +def load_data( + endpoint: str, method: str, params: dict, as_json: bool = False +) -> Union[str, dict]: + """Load data identified by endpoint, method and params. + + Either load data from cache (previous download) or from Destatis. + + Args: + endpoint (str): The endpoint for this data request. + method (str): The method for this data request. + params (dict): The dictionary holding the params for this data request. + as_json (bool, optional): If True, result will be parsed as JSON. Defaults to False. + + Returns: + Union[str, dict]: The data as raw text or JSON dict. + """ + config = load_config() + cache_dir = Path(config["DATA"]["cache_dir"]) + name = params.get("name") + + if name is not None: + name = normalize_name(name) + + if endpoint == "data": + if hit_in_cash(cache_dir, name, params): + data = read_from_cache(cache_dir, name, params) + else: + response = get_data_from_endpoint(endpoint, method, params) + data = response.text + + # status code 98 means that the table is too big + # we have to start a job and wait for it to be ready + response_status_code = 200 + try: + # test for job-relevant status code + response_status_code = response.json().get("Status").get("Code") + except json.decoder.JSONDecodeError: + pass + + if response_status_code == 98: + job_response = start_job(endpoint, method, params) + job_id = get_job_id_from_response(job_response) + data = get_data_from_resultfile(job_id) + + cache_data(cache_dir, name, params, data) + else: + response = get_data_from_endpoint(endpoint, method, params) + data = response.text + + if as_json: + parsed_data: dict = json.loads(data) + return parsed_data + else: + return data + + +def get_data_from_endpoint( + endpoint: str, method: str, params: dict +) -> requests.Response: + """ + Wrapper method which constructs an url for querying data from Destatis and + sends a GET request. + + Args: + endpoint (str): Destatis endpoint (eg. data, catalogue, ..) + method (str): Destatis method (eg. cube, tablefile, ...) + params (dict): dictionary of query parameters + + Returns: + requests.Response: the response object holding the response from calling the Destatis endpoint. + """ + config = load_config() + url = f"{config['GENESIS API']['base_url']}{endpoint}/{method}" + + # params is used to calculate hash for caching so don't alter params dict here! + params_ = params.copy() + params_.update( + { + "username": config["GENESIS API"]["username"], + "password": config["GENESIS API"]["password"], + } + ) + + response = requests.get(url, params=params_, timeout=(5, 15)) + + response.encoding = "UTF-8" + _check_invalid_status_code(response) + _check_invalid_destatis_status_code(response) + + return response + + +def start_job(endpoint: str, method: str, params: dict) -> requests.Response: + """Small helper function to start a job in the background. + + Args: + endpoint (str): Destatis endpoint (eg. data, catalogue, ..) + method (str): Destatis method (eg. cube, tablefile, ...) + params (dict): dictionary of query parameters + + Returns: + requests.Response: the response object holding the response from calling the Destatis endpoint. + """ + logger.warning( + "Die Tabelle ist zu groß, um direkt abgerufen zu werden. Es wird eine Verarbeitung im Hintergrund gestartet." + ) + params["job"] = "true" + + # starting a job + response = get_data_from_endpoint( + endpoint=endpoint, method=method, params=params + ) + + return response + + +def get_job_id_from_response(response: requests.Response) -> str: + """Get the job ID of a successful started job. + + Args: + response (requests.Response): Response from endpoint request with job set equal to true. + + Returns: + str: the job id. + """ + # check out job_id & inform user + content = "" + try: + content = response.json().get("Status").get("Content") + except json.JSONDecodeError: + pass + + match_result = JOB_ID_PATTERN.search(content) + job_id = match_result.group() if match_result is not None else "" + + return job_id + + +def get_data_from_resultfile(job_id: str) -> str: + """Get data from a job once it is finished or when the timeout is reached. + + Args: + job_id (str): Job ID generated by Destatis API. + + Returns: + str: The raw data of the table file as returned by Destatis. + """ + params = { + "selection": "*" + job_id, + "searchcriterion": "code", + "sortcriterion": "code", + "type": "all", + } + + time_ = time.perf_counter() + + while (time.perf_counter() - time_) < JOB_TIMEOUT: + response = get_data_from_endpoint( + endpoint="catalogue", method="jobs", params=params + ) + + jobs = response.json().get("List") + if len(jobs) > 0 and jobs[0].get("State") == "Fertig": + break + + time.sleep(5) + else: + return "" + + params = { + "name": job_id, + "area": "all", + "compress": "false", + "format": "ffcsv", + } + response = get_data_from_endpoint( + endpoint="data", method="resultfile", params=params + ) + return str(response.text) + + +def _check_invalid_status_code(response: requests.Response) -> None: + """ + Helper method which handles the status code from the response + + Args: + response (requests.Response): The response object from the request + + Raises: + AssertionError: Assert that status is not 4xx or 5xx + """ + if response.status_code // 100 in [4, 5]: + try: + body: dict = response.json() + except json.JSONDecodeError: + body = {} + + content = body.get("Content") + code = body.get("Code") + logger.error("Error Code: %s. Content: %s.", code, content) + raise requests.exceptions.HTTPError( + f"The server returned a {response.status_code} status code." + ) + + +def _check_invalid_destatis_status_code(response: requests.Response) -> None: + """ + Helper method which handles the status code returned from Destatis + (if exists) + + Args: + response (requests.Response): The response object from the request + + """ + try: + response_dict = response.json() + # catch possible errors raised by .json() (and only .json()) + except ( + UnicodeDecodeError, + json.decoder.JSONDecodeError, + requests.exceptions.JSONDecodeError, + ): + response_dict = None + + if response_dict is not None: + _check_destatis_status(response_dict.get("Status", {})) + + +def _check_destatis_status(destatis_status: dict) -> None: + """ + Helper method which checks the status message from Destatis. + If the status message is erroneous an error will be raised. + + Possible Codes (2.1.2 Grundstruktur der Responses): + # TODO: Ask Destatis for full list of error codes + - 0: "erfolgreich" (Type: "Information") + - 22: "erfolgreich mit Parameteranpassung" (Type: "Warnung") + - 104: "Kein passendes Objekt zu Suche" (Type: "Information") + + Args: + destatis_status (dict): Status response dict from Destatis + + Raises: + DestatisStatusError: If the status code or type displays an error (caused by the user inputs) + """ + # -1 status code for unexpected errors and if no status code is given (faulty response) + destatis_status_code = destatis_status.get("Code", -1) + destatis_status_type = destatis_status.get("Type", "Information") + destatis_status_content = destatis_status.get("Content") + + # define status types + error_en_de = ["Error", "Fehler"] + warning_en_de = ["Warning", "Warnung"] + + # check for generic/ system error + if destatis_status_code == -1: + raise DestatisStatusError(destatis_status_content) + + # check for destatis/ query errors + elif (destatis_status_code == 104) or (destatis_status_type in error_en_de): + if destatis_status_code == 98: + pass + else: + raise DestatisStatusError(destatis_status_content) + + # output warnings to user + elif (destatis_status_code == 22) or ( + destatis_status_type in warning_en_de + ): + logger.warning(destatis_status_content) + + # output information to user + elif destatis_status_type.lower() == "information": + logger.info( + "Code %d: %s", destatis_status_code, destatis_status_content + ) diff --git a/src/pystatis/profile.py b/src/pystatis/profile.py new file mode 100644 index 0000000..94bba5c --- /dev/null +++ b/src/pystatis/profile.py @@ -0,0 +1,73 @@ +"""Module provides wrapper for Profile GENESIS REST-API functions.""" + +import logging +from typing import cast + +from pystatis.config import ( + _write_config, + get_config_path_from_settings, + load_config, +) +from pystatis.http_helper import load_data + +logger = logging.getLogger(__name__) + + +def change_password(new_password: str) -> str: + """ + Changes Genesis REST-API password and updates local config. + + Args: + new_password (str): New password for the Genesis REST-API + + Returns: + str: text response from Destatis + """ + params = { + "new": new_password, + "repeat": new_password, + } + + # load config.ini beforehand, to ensure passwords are changed at the same time + config = load_config() + try: + config["GENESIS API"]["password"] + except KeyError as e: + raise KeyError( + "Password not found in config! Please make sure \ + init_config() was run properly & your user data is set correctly!", + ) from e + + # change remote password + response_text = load_data( + endpoint="profile", method="password", params=params + ) + # change local password + config["GENESIS API"]["password"] = new_password + _write_config(config, get_config_path_from_settings()) + + logger.info("Password changed successfully!") + + return cast(str, response_text) + + +def remove_result(name: str, area: str = "all") -> str: + """ + Remove 'Ergebnistabellen' from the the permission space 'area'. + Should only apply for manually saved data, visible in 'Meine Tabellen' in the Web Interface. + + Args: + name (str): 'Ergebnistabelle' to be removed + area (str): permission area in which the 'Ergebnistabelle' resides + + Returns: + str: text response from Destatis + """ + params = {"name": name, "area": area, "language": "de"} + + # remove 'Ergebnistabelle' with previously defined parameters + response_text = load_data( + endpoint="profile", method="removeresult", params=params + ) + + return cast(str, response_text) diff --git a/src/pystatis/table.py b/src/pystatis/table.py new file mode 100644 index 0000000..071fc93 --- /dev/null +++ b/src/pystatis/table.py @@ -0,0 +1,49 @@ +"""Module contains business logic related to destatis tables.""" +from io import StringIO + +import pandas as pd + +from pystatis.http_helper import load_data + + +class Table: + """A wrapper class holding all relevant data and metadata about a given table. + + Args: + name (str): The unique identifier of this table. + raw_data (str): The raw tablefile data as returned by the /data/table endpoint. + data (pd.DataFrame): The parsed data as a pandas data frame. + metadata (dict): Metadata as returned by the /metadata/table endpoint. + """ + + def __init__(self, name: str): + self.name: str = name + self.raw_data = "" + self.data = pd.DataFrame() + self.metadata: dict = {} + + def get_data(self, area: str = "all", **kwargs): + """Downloads raw data and metadata from GENESIS-Online. + + Additional keyword arguments are passed on to the GENESIS-Online GET request for tablefile. + + Args: + area (str, optional): Area to search for the object in GENESIS-Online. Defaults to "all". + """ + params = {"name": self.name, "area": area, "format": "ffcsv"} + + params |= kwargs + + raw_data = load_data( + endpoint="data", method="tablefile", params=params, as_json=False + ) + assert isinstance(raw_data, str) # nosec assert_used + self.raw_data = raw_data + data_str = StringIO(raw_data) + self.data = pd.read_csv(data_str, sep=";") + + metadata = load_data( + endpoint="metadata", method="table", params=params, as_json=True + ) + assert isinstance(metadata, dict) # nosec assert_used + self.metadata = metadata diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/rsc/data.zip b/tests/rsc/data.zip new file mode 100644 index 0000000..c036a7c Binary files /dev/null and b/tests/rsc/data.zip differ diff --git a/tests/test_cache.py b/tests/test_cache.py new file mode 100644 index 0000000..25196bf --- /dev/null +++ b/tests/test_cache.py @@ -0,0 +1,128 @@ +import re +from pathlib import Path + +import pytest + +from pystatis.cache import ( + _build_file_path, + cache_data, + clear_cache, + hit_in_cash, + normalize_name, + read_from_cache, +) +from pystatis.config import ( + DEFAULT_SETTINGS_FILE, + _write_config, + init_config, + load_config, + load_settings, +) + + +@pytest.fixture() +def cache_dir(tmp_path_factory): + # remove white-space and non-latin characters (issue fo some user names) + temp_dir = str(tmp_path_factory.mktemp(".pystatis")) + temp_dir = re.sub(r"[^\x00-\x7f]", r"", temp_dir.replace(" ", "")) + + init_config("myuser", "mypw", temp_dir) + + config = load_config() + cache_dir = Path(config["DATA"]["cache_dir"]) + + return cache_dir + + +@pytest.fixture(autouse=True) +def restore_settings(): + old_settings = load_settings() + yield + _write_config(old_settings, DEFAULT_SETTINGS_FILE) + + +@pytest.fixture(scope="module") +def params(): + return {"name": "test-cache", "area": "all"} + + +def test_build_file_path(cache_dir, params): + data_dir = _build_file_path(cache_dir, "test-build-file-path", params) + + assert isinstance(data_dir, Path) + assert data_dir.parent == Path(cache_dir) / "test-build-file-path" + assert data_dir.name.isalnum() + + +def test_cache_data(cache_dir, params): + assert len(list((cache_dir / "data").glob("*"))) == 0 + + test_data = "test" + cache_data(cache_dir, "test-cache-data", params, test_data) + + data_dir = _build_file_path(cache_dir, "test-cache-data", params) + + assert data_dir.exists() and len(list(data_dir.glob("*.zip"))) == 1 + + +def test_read_from_cache(cache_dir, params): + test_data = "test read from cache" + cache_data( + cache_dir, + "test-read-cache", + params, + test_data, + ) + data = read_from_cache(cache_dir, "test-read-cache", params) + + assert data == test_data + + +def test_hit_cache(cache_dir, params): + assert not hit_in_cash(cache_dir, "test-hit-cache", params) + cache_data(cache_dir, "test-hit-cache", params, "test") + assert hit_in_cash(cache_dir, "test-hit-cache", params) + + +def test_normalize_name(): + full_name = "42153-0001_878150652" + assert normalize_name(full_name) == "42153-0001" + + +def test_change_in_params(cache_dir, params): + params_ = params.copy() + + name = "test-change-in-params" + assert not hit_in_cash(cache_dir, name, params_) + cache_data(cache_dir, name, params_, "test") + assert hit_in_cash(cache_dir, name, params_) + + params_.update({"new-param": 2}) + assert not hit_in_cash(cache_dir, name, params_) + + +def test_ignore_jobs_in_params(cache_dir, params): + params_ = params.copy() + + name = "test-ignore-jobs" + cache_data(cache_dir, name, params_, "test") + + params_.update({"job": True}) + assert hit_in_cash(cache_dir, name, params_) + + params_.update({"job": False}) + assert hit_in_cash(cache_dir, name, params_) + + +def test_clean_cache(cache_dir, params): + name = "test-clean-cache" + cache_data(cache_dir, name, params, "test") + + data_dir = _build_file_path(cache_dir, name, params) + cached_data_file = list(data_dir.glob("*.zip"))[0] + + assert cached_data_file.exists() and cached_data_file.is_file() + + clear_cache(name=name) + + assert not cached_data_file.exists() and not cached_data_file.is_file() diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 0000000..45ffc87 --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,128 @@ +import logging +import re +from configparser import ConfigParser +from pathlib import Path + +import pytest + +import pystatis.config +from pystatis.config import ( + DEFAULT_SETTINGS_FILE, + _write_config, + create_settings, + get_config_path_from_settings, + init_config, + load_config, + load_settings, +) + + +@pytest.fixture() +def config_dir(tmp_path_factory): + # remove white-space and non-latin characters (issue fo some user names) + temp_dir = str(tmp_path_factory.mktemp(".pystatis")) + temp_dir = re.sub(r"[^\x00-\x7f]", r"", temp_dir.replace(" ", "")) + + return Path(temp_dir) + + +@pytest.fixture(autouse=True) +def restore_settings(): + old_settings = load_settings() + yield + _write_config(old_settings, DEFAULT_SETTINGS_FILE) + + +def test_create_settings_is_run_on_import(): + assert DEFAULT_SETTINGS_FILE.exists() and DEFAULT_SETTINGS_FILE.is_file() + + +def test_create_settings(config_dir, mocker): + mocker.patch.object(pystatis.config, "DEFAULT_CONFIG_DIR", config_dir) + mocker.patch.object( + pystatis.config, "DEFAULT_SETTINGS_FILE", config_dir / "settings.ini" + ) + create_settings() + + assert (config_dir / "settings.ini").is_file() + + +def test_load_settings(): + settings = load_settings() + + assert isinstance(settings, ConfigParser) + assert settings.has_option("SETTINGS", "config_dir") + + +def test_get_config_path_from_settings(): + config_path = get_config_path_from_settings() + + assert isinstance(config_path, Path) + + +def test_init_config_with_config_dir(config_dir, caplog): + caplog.clear() + caplog.set_level(logging.INFO) + + init_config("myuser", "mypw", config_dir) + + assert len(caplog.records) == 2 + assert caplog.records[0].levelname == "INFO" + assert caplog.records[1].levelname == "INFO" + assert "Settings file updated" in caplog.text + assert "New config was created" in caplog.text + assert (config_dir / "data").exists() + + config = load_config() + + assert isinstance(config, ConfigParser) + assert len(config.sections()) > 0 + assert config["DATA"]["cache_dir"] == str(config_dir / "data") + assert len(list((config_dir / "data").glob("*"))) == 0 + + config_file = get_config_path_from_settings() + + assert config_file.exists() and config_file.is_file() + + +def test_load_config(config_dir): + init_config("myuser", "mypw123!", config_dir) + config: ConfigParser = load_config() + + for section in ["GENESIS API", "DATA"]: + assert config.has_section(section) + + assert config.options("GENESIS API") == [ + "base_url", + "username", + "password", + "doku", + ] + assert config.options("DATA") == ["cache_dir"] + + assert config["GENESIS API"]["username"] == "myuser" + assert config["GENESIS API"]["password"] == "mypw123!" + + +def test_missing_username(config_dir, caplog): + init_config("", "", config_dir) + + caplog.clear() + + _ = load_config() + + assert caplog.records[0].levelname == "CRITICAL" + assert "Username and/or password are missing!" in caplog.text + + +def test_missing_file(config_dir, caplog): + init_config("", "", config_dir) + (config_dir / "config.ini").unlink() + + caplog.clear() + + config = load_config() + assert not config.sections() + + for record in caplog.records: + assert record.levelname == "CRITICAL" diff --git a/tests/test_cube.py b/tests/test_cube.py new file mode 100644 index 0000000..ce4aa01 --- /dev/null +++ b/tests/test_cube.py @@ -0,0 +1,166 @@ +import zipfile +from pathlib import Path + +import numpy as np +import pytest + +from pystatis.cube import assign_correct_types, parse_cube, rename_axes + + +@pytest.fixture +def easy_raw_data(): + with zipfile.ZipFile(Path(__file__).parent / "rsc" / "data.zip") as myzip: + with myzip.open("12411BJ001.txt", "r") as file: + return file.read().decode() + + +@pytest.fixture +def hard_raw_data(): + with zipfile.ZipFile(Path(__file__).parent / "rsc" / "data.zip") as myzip: + with myzip.open("22922KJ1141.txt", "r") as file: + return file.read().decode() + + +@pytest.fixture +def easy_cube(easy_raw_data): + return parse_cube(easy_raw_data) + + +@pytest.fixture +def hard_cube(hard_raw_data): + return parse_cube(hard_raw_data) + + +@pytest.fixture +def raw_data(request, easy_raw_data, hard_raw_data): + if request.param == "easy_cube": + return easy_raw_data + elif request.param == "hard_cube": + return hard_raw_data + + +@pytest.fixture +def cube(request, easy_cube, hard_cube): + if request.param == "easy_cube": + return easy_cube + elif request.param == "hard_cube": + return hard_cube + + +@pytest.mark.parametrize( + "raw_data, expected_shape, expected_DQ, expected_DQ_ERH, expected_DQA, expected_DQZ, expected_DQI,", + [ + ( + "hard_cube", + (19185, 13), + "22922KJ114", + "22922", + ["KREISE", "GES", "ERW122", "ELGAT2"], + "JAHR", + ["ELG002", "ELG003"], + ), + ( + "easy_cube", + (42403, 10), + "12411BJ001", + "12411", + ["DINSG", "NAT", "GES", "FAMST8", "ALT013"], + "STAG", + ["BEVSTD"], + ), + ], + indirect=["raw_data"], +) +def test_parse_cube( + raw_data, + expected_shape, + expected_DQ, + expected_DQ_ERH, + expected_DQA, + expected_DQZ, + expected_DQI, +): + cube = parse_cube(raw_data) + + assert isinstance(cube, dict) + assert len(cube) == raw_data.count("K;") + + assert cube["QEI"].shape == expected_shape + assert cube["DQ"]["FACH-SCHL"].values[0] == expected_DQ + assert cube["DQ-ERH"]["FACH-SCHL"].values[0] == expected_DQ_ERH + assert cube["DQA"]["NAME"].to_list() == expected_DQA + assert cube["DQZ"]["NAME"].values[0] == expected_DQZ + assert cube["DQI"]["NAME"].to_list() == expected_DQI + + +@pytest.mark.parametrize( + "cube, expected_names", + [ + ( + "easy_cube", + [ + "DINSG", + "NAT", + "GES", + "FAMST8", + "ALT013", + "STAG", + "BEVSTD_WERT", + "BEVSTD_QUALITAET", + "BEVSTD_GESPERRT", + "BEVSTD_WERT-VERFAELSCHT", + ], + ), + ( + "hard_cube", + [ + "KREISE", + "GES", + "ERW122", + "ELGAT2", + "JAHR", + "ELG002_WERT", + "ELG002_QUALITAET", + "ELG002_GESPERRT", + "ELG002_WERT-VERFAELSCHT", + "ELG003_WERT", + "ELG003_QUALITAET", + "ELG003_GESPERRT", + "ELG003_WERT-VERFAELSCHT", + ], + ), + ], + indirect=["cube"], +) +def test_rename_axes(cube, expected_names): + cube = rename_axes(cube) + + assert list(cube["QEI"].columns) == expected_names + + +@pytest.mark.parametrize( + "cube, test_cols, test_types", + [ + ( + "easy_cube", + [ + "BEVSTD_WERT", + ], + [np.integer], + ), + ( + "hard_cube", + [ + "ELG002_WERT", + "ELG003_WERT", + ], + [np.integer, np.integer], + ), + ], + indirect=["cube"], +) +def test_rename_axes(cube, test_cols, test_types): + cube = assign_correct_types(rename_axes(cube)) + + for col, expected_type in zip(test_cols, test_types): + assert issubclass(cube["QEI"][col].dtype.type, expected_type) diff --git a/tests/test_helloworld.py b/tests/test_helloworld.py new file mode 100644 index 0000000..0106394 --- /dev/null +++ b/tests/test_helloworld.py @@ -0,0 +1,45 @@ +from pystatis import logincheck, whoami +from tests.test_http_helper import _generic_request_status + + +def test_whoami(mocker): + mocker.patch( + "pystatis.helloworld.load_config", + return_value={ + "GENESIS API": { + "base_url": "mocked_url", + "username": "JaneDoe", + "password": "password", + } + }, + ) + + mocker.patch( + "pystatis.helloworld.requests.get", + return_value=_generic_request_status(), + ) + + response = whoami() + + assert response == str(_generic_request_status().text) + + +def test_logincheck(mocker): + mocker.patch( + "pystatis.helloworld.load_config", + return_value={ + "GENESIS API": { + "base_url": "mocked_url", + "username": "JaneDoe", + "password": "password", + } + }, + ) + mocker.patch( + "pystatis.helloworld.requests.get", + return_value=_generic_request_status(), + ) + + response = logincheck() + + assert response == str(_generic_request_status().text) diff --git a/tests/test_http_helper.py b/tests/test_http_helper.py new file mode 100644 index 0000000..1c8823f --- /dev/null +++ b/tests/test_http_helper.py @@ -0,0 +1,194 @@ +import json +import logging + +import pytest +import requests + +from pystatis.custom_exceptions import DestatisStatusError +from pystatis.http_helper import ( + _check_invalid_destatis_status_code, + _check_invalid_status_code, + get_data_from_endpoint, + get_job_id_from_response, +) + + +def _generic_request_status( + status_response: bool = True, + status_code: int = 200, + code: int = 0, + status_type: str = "Information", + status_content: str = "Erfolg/ Success/ Some Issue", +) -> requests.Response: + """ + Helper method which allows to create a generic request.Response that covers all Destatis answers + + Returns: + requests.Response: the response from Destatis + """ + # define possible status dict and texts + status_dict = { + "Ident": { + "Service": "A DESTATIS service", + "Method": "A DESTATIS method", + }, + "Status": { + "Code": code, + "Content": status_content, + "Type": status_type, + }, + } + + response_text = "Some text for a successful response without status..." + + # set up generic requests.Response + request_status = requests.Response() + request_status.status_code = status_code # success + + # Define UTF-8 encoding as requests guesses otherwise + if status_response: + request_status._content = json.dumps(status_dict).encode("UTF-8") + else: + request_status._content = response_text.encode("UTF-8") + + return request_status + + +def test_get_response_from_endpoint(mocker): + """ + Test once with generic API response, more detailed tests + of subfunctions and specific cases below. + """ + mocker.patch( + "pystatis.http_helper.requests", return_value=_generic_request_status() + ) + mocker.patch( + "pystatis.http_helper.load_config", + return_value={ + "GENESIS API": { + "base_url": "mocked_url", + "username": "JaneDoe", + "password": "password", + } + }, + ) + + get_data_from_endpoint(endpoint="endpoint", method="method", params={}) + + +def test_check_invalid_status_code_with_error(): + """ + Basic tests to check an error status code (4xx, 5xx) + for _handle_status_code method. + """ + for status_code in [400, 500]: + with pytest.raises(requests.exceptions.HTTPError) as e: + _check_invalid_status_code( + _generic_request_status(status_code=status_code) + ) + assert ( + str(e.value) == f"The server returned a {status_code} status code." + ) + + +def test_check_invalid_status_code_without_error(): + """ + Basic test to check a valid status code (2xx) + for the _handle_status_code method. + """ + try: + _check_invalid_status_code(_generic_request_status()) + except Exception: + assert False + + +def test_check_invalid_destatis_status_code_with_error(): + """ + Basic tests to check an error status code as defined in the + documentation via code (e.g. -1, 104) or type ('Error', 'Fehler'). + """ + for status in [ + _generic_request_status(code=104), + _generic_request_status(status_type="Error"), + _generic_request_status(status_type="Fehler"), + ]: + # extract status content which is raised + status_content = status.json().get("Status").get("Content") + + with pytest.raises(DestatisStatusError) as e: + _check_invalid_destatis_status_code(status) + assert str(e.value) == status_content + + # also test generic -1 error code + generic_error_status = _generic_request_status( + code=-1, + status_content="Error: There is a system error. Please check your query parameters.", + ) + + with pytest.raises(DestatisStatusError) as e: + _check_invalid_destatis_status_code(generic_error_status) + assert ( + str(e.value) + == "Error: There is a system error. Please check your query parameters." + ) + + +def test_check_invalid_destatis_status_code_with_warning(caplog): + """ + Basic tests to check a warning status code as defined in the + documentation via code (e.g. 22) or type ('Warning', 'Warnung'). + """ + caplog.set_level(logging.WARNING) + + for status in [ + _generic_request_status(code=22), + _generic_request_status(status_type="Warnung"), + _generic_request_status(status_type="Warning"), + ]: + # extract status content which is contained in warning + status_content = status.json().get("Status").get("Content") + + _check_invalid_destatis_status_code(status) + + assert status_content in caplog.text + + +def test_check_invalid_destatis_status_code_without_error(caplog): + """ + Basic tests to check the successful status code 0 or only text response as defined in the documentation. + """ + # JSON response with status code + caplog.set_level(logging.INFO) + status = _generic_request_status() + status_content = status.json().get("Status").get("Content") + _check_invalid_destatis_status_code(status) + + assert status_content in caplog.text + + # text only response + status_text = _generic_request_status(status_response=False) + try: + _check_invalid_destatis_status_code(status_text) + except Exception: + assert False + + +def test_get_job_id_from_response(): + response = requests.Response() + response._content = """{"Status": {"Content": "Der Bearbeitungsauftrag wurde erstellt. Die Tabelle kann in Kürze als Ergebnis mit folgendem Namen abgerufen werden: 42153-0001_001597503 (Mindestens ein Parameter enthält ungültige Werte. Er wurde angepasst, um den Service starten zu können.: stand"}}""".encode() + job_id = get_job_id_from_response(response) + assert job_id == "42153-0001_001597503" + + +def test_get_job_id_from_response_with_no_id(): + response = requests.Response() + response._content = """{"Status": {"Content": "Der Bearbeitungsauftrag wurde erstellt."}}""".encode() + job_id = get_job_id_from_response(response) + assert job_id == "" + + +def test_get_job_id_from_response_with_no_json(): + response = requests.Response() + response._content = "Der Bearbeitungsauftrag wurde erstellt. Die Tabelle kann in Kürze als Ergebnis mit folgendem Namen abgerufen werden: 42153-0001_001597503 (Mindestens ein Parameter enthält ungültige Werte. Er wurde angepasst, um den Service starten zu können.: stand".encode() + job_id = get_job_id_from_response(response) + assert job_id == "" diff --git a/tests/test_profile.py b/tests/test_profile.py new file mode 100644 index 0000000..a3f6571 --- /dev/null +++ b/tests/test_profile.py @@ -0,0 +1,74 @@ +import re +from configparser import ConfigParser +from pathlib import Path + +import pytest + +from pystatis.profile import change_password, remove_result +from tests.test_http_helper import _generic_request_status + + +@pytest.fixture() +def cache_dir(tmp_path_factory): + # remove white-space and non-latin characters (issue fo some user names) + temp_dir = str(tmp_path_factory.mktemp(".pystatis")) + temp_dir = re.sub(r"[^\x00-\x7f]", r"", temp_dir.replace(" ", "")) + + return Path(temp_dir) + + +def test_change_password(mocker, cache_dir): + # mock configparser to be able to test writing of new password + config = ConfigParser() + config["GENESIS API"] = { + "base_url": "mocked_url", + "username": "JaneDoe", + "password": "password", + } + mocker.patch("pystatis.profile.load_config", return_value=config) + mocker.patch( + "pystatis.profile.load_data", + return_value=str(_generic_request_status().text), + ) + mocker.patch( + "pystatis.profile.get_config_path_from_settings", + return_value=cache_dir / "config.ini", + ) + + response = change_password("new_password") + + assert response == str(_generic_request_status().text) + + +def test_change_password_keyerror(mocker, cache_dir): + # define empty config (no password) + mocker.patch( + "pystatis.profile.load_config", return_value={"GENESIS API": {}} + ) + mocker.patch( + "pystatis.profile.load_data", + return_value=str(_generic_request_status().text), + ) + mocker.patch( + "pystatis.profile.get_config_path_from_settings", + return_value=cache_dir / "config.ini", + ) + + with pytest.raises(KeyError) as e: + change_password("new_password") + assert ( + "Password not found in config! Please make sure \ + init_config() was run properly & your user data is set correctly!" + in str(e.value) + ) + + +def test_remove_result(mocker): + mocker.patch( + "pystatis.profile.load_data", + return_value=str(_generic_request_status().text), + ) + + response = remove_result("11111-0001") + + assert response == str(_generic_request_status().text) diff --git a/tests/test_version.py b/tests/test_version.py new file mode 100644 index 0000000..8f057ce --- /dev/null +++ b/tests/test_version.py @@ -0,0 +1,5 @@ +from pystatis import __version__ + + +def test_version(): + assert __version__ == "0.1.0"