├── tests ├── __init__.py ├── conftest.py └── test_econci.py ├── _config.yml ├── docs ├── authors.rst ├── history.rst ├── readme.rst ├── contributing.rst ├── usage.rst ├── index.rst ├── Makefile ├── make.bat ├── installation.rst └── conf.py ├── .flake8 ├── HISTORY.rst ├── econci ├── __init__.py ├── utils.py └── complexity.py ├── AUTHORS.rst ├── MANIFEST.in ├── pyproject.toml ├── LICENSE ├── .gitignore ├── Makefile ├── README.rst ├── CONTRIBUTING.rst └── poetry.lock /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /docs/authors.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../AUTHORS.rst 2 | -------------------------------------------------------------------------------- /docs/history.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../HISTORY.rst 2 | -------------------------------------------------------------------------------- /docs/readme.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.rst 2 | -------------------------------------------------------------------------------- /docs/contributing.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../CONTRIBUTING.rst 2 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | exclude = docs 4 | -------------------------------------------------------------------------------- /docs/usage.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | Usage 3 | ===== 4 | 5 | To use econci in a project:: 6 | 7 | import econci 8 | -------------------------------------------------------------------------------- /HISTORY.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | History 3 | ======= 4 | 5 | 0.1.0 (2020-06-06) 6 | ------------------ 7 | 8 | * First release on PyPI. 9 | -------------------------------------------------------------------------------- /econci/__init__.py: -------------------------------------------------------------------------------- 1 | from .complexity import Complexity 2 | from .utils import edges_nodes_to_csv 3 | 4 | __all__ = ['Complexity', 'edges_nodes_to_csv'] 5 | -------------------------------------------------------------------------------- /AUTHORS.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Credits 3 | ======= 4 | 5 | Development Lead 6 | ---------------- 7 | 8 | * Pedro Henrique Castro Soares 9 | 10 | Contributors 11 | ------------ 12 | 13 | None yet. Why not be the first? 14 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include AUTHORS.rst 2 | include CONTRIBUTING.rst 3 | include HISTORY.rst 4 | include LICENSE 5 | include README.rst 6 | 7 | recursive-include tests * 8 | recursive-exclude * __pycache__ 9 | recursive-exclude * *.py[co] 10 | 11 | recursive-include docs *.rst conf.py Makefile make.bat *.jpg *.png *.gif 12 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to econci's documentation! 2 | ====================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Contents: 7 | 8 | readme 9 | installation 10 | usage 11 | modules 12 | contributing 13 | authors 14 | history 15 | 16 | Indices and tables 17 | ================== 18 | * :ref:`genindex` 19 | * :ref:`modindex` 20 | * :ref:`search` 21 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "econci" 3 | version = "0.1.3" 4 | description = "" 5 | authors = ["phcsoares "] 6 | license = "MIT" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.8" 10 | pandas = ">=0.25.0" 11 | networkx = ">=2.4" 12 | 13 | [tool.poetry.dev-dependencies] 14 | flake8 = "^4.0.1" 15 | pytest = "^6.2.5" 16 | twine = "^3.4.2" 17 | pytest-cov = "^3.0.0" 18 | towncrier = "^21.3.0" 19 | 20 | [build-system] 21 | requires = ["poetry-core>=1.0.0"] 22 | build-backend = "poetry.core.masonry.api" 23 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = python -msphinx 7 | SPHINXPROJ = econci 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=python -msphinx 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=econci 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The Sphinx module was not found. Make sure you have Sphinx installed, 20 | echo.then set the SPHINXBUILD environment variable to point to the full 21 | echo.path of the 'sphinx-build' executable. Alternatively you may add the 22 | echo.Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | import pandas as pd 4 | import numpy as np 5 | 6 | 7 | @pytest.fixture 8 | def data_stub(): 9 | return pd.DataFrame({ 10 | 'country': ['A', 'A', 'A', 'B', 'B', 'C'], 11 | 'product': ['P1', 'P2', 'P3', 'P1', 'P2', 'P1'], 12 | 'export': [10, 20, 30, 40, 50, 60], 13 | }) 14 | 15 | 16 | @pytest.fixture 17 | def correct_m_stub(): 18 | return pd.DataFrame( 19 | np.array([[10., 20., 30.], 20 | [40., 50., 0.], 21 | [60., 0., 0.]]), 22 | index=pd.Index(['A', 'B', 'C'], name='country'), 23 | columns=pd.Index(['P1', 'P2', 'P3'], name='product') 24 | ) 25 | 26 | 27 | @pytest.fixture 28 | def correct_rca_stub(): 29 | return pd.DataFrame( 30 | np.array([[0.3182, 1., 3.5], 31 | [0.8485, 1.6667, 0.], 32 | [1.9091, 0., 0.]]), 33 | index=pd.Index(['A', 'B', 'C'], name='country'), 34 | columns=pd.Index(['P1', 'P2', 'P3'], name='product') 35 | ) 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020, Pedro Henrique Castro Soares 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | .. highlight:: shell 2 | 3 | ============ 4 | Installation 5 | ============ 6 | 7 | 8 | Stable release 9 | -------------- 10 | 11 | To install econci, run this command in your terminal: 12 | 13 | .. code-block:: console 14 | 15 | $ pip install econci 16 | 17 | This is the preferred method to install econci, as it will always install the most recent stable release. 18 | 19 | If you don't have `pip`_ installed, this `Python installation guide`_ can guide 20 | you through the process. 21 | 22 | .. _pip: https://pip.pypa.io 23 | .. _Python installation guide: http://docs.python-guide.org/en/latest/starting/installation/ 24 | 25 | 26 | From sources 27 | ------------ 28 | 29 | The sources for econci can be downloaded from the `Github repo`_. 30 | 31 | You can either clone the public repository: 32 | 33 | .. code-block:: console 34 | 35 | $ git clone git://github.com/phcsoares/econci 36 | 37 | Or download the `tarball`_: 38 | 39 | .. code-block:: console 40 | 41 | $ curl -OJL https://github.com/phcsoares/econci/tarball/master 42 | 43 | Once you have a copy of the source, you can install it with: 44 | 45 | .. code-block:: console 46 | 47 | $ python setup.py install 48 | 49 | 50 | .. _Github repo: https://github.com/phcsoares/econci 51 | .. _tarball: https://github.com/phcsoares/econci/tarball/master 52 | -------------------------------------------------------------------------------- /econci/utils.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import networkx as nx 3 | import functools 4 | 5 | 6 | def edges_nodes_to_csv(graph: nx.Graph, graph_name: str, dir_path: str) -> None: 7 | ''' 8 | Saves two csv files, one with the edges and another with the nodes information. 9 | 10 | Parameters 11 | ---------- 12 | graph : networkx.Graph 13 | Graph to be saved. 14 | graph_name : str 15 | Name of the graph. 16 | dir_path : str 17 | Path to directory where graph will be saved. 18 | ''' 19 | nodes = [(ind, node) for ind, node in zip(range(len(list(graph.nodes))), list(graph.nodes))] 20 | dic_nodes = {node: ind for ind, node in zip(range(len(list(graph.nodes))), list(graph.nodes))} 21 | nodes = pd.DataFrame(nodes, columns=['id', 'name']) 22 | 23 | edges = nx.to_pandas_edgelist(graph) 24 | edges[['source', 'target']] = edges[['source', 'target']].replace(dic_nodes) 25 | 26 | if not dir_path.endswith('/'): 27 | dir_path += '/' 28 | edges_path = dir_path + graph_name + '_edges.csv' 29 | nodes_path = dir_path + graph_name + '_nodes.csv' 30 | 31 | edges.to_csv(edges_path, index=False) 32 | nodes.to_csv(nodes_path, index=False) 33 | 34 | 35 | def check_if_indexes(func): 36 | @functools.wraps(func) 37 | def decor_check(self, *args, **kwargs): 38 | if hasattr(self, '_m'): 39 | return func(self, *args, **kwargs) 40 | else: 41 | raise Exception('First, calculate indexes!') 42 | return decor_check 43 | 44 | 45 | def check_if_graph(func): 46 | @functools.wraps(func) 47 | def decor_check(self, *args, **kwargs): 48 | if hasattr(self, '_complete_graph'): 49 | return func(self, *args, **kwargs) 50 | else: 51 | raise Exception('First, create the Product Space!') 52 | return decor_check 53 | -------------------------------------------------------------------------------- /tests/test_econci.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | import pandas as pd 4 | import networkx as nx 5 | 6 | from econci import Complexity 7 | 8 | 9 | class TestComplexity(): 10 | 11 | def _get_instance(self, df: pd.DataFrame) -> Complexity: 12 | return Complexity(df=df, c='country', p='product', values='export', m_cp_thresh=1) 13 | 14 | def test_initialization(self): 15 | df = pd.DataFrame() 16 | c = 'country' 17 | p = 'product' 18 | values = 'export' 19 | m_cp_thresh = 0.5 20 | 21 | comp = Complexity(df, c, p, values, m_cp_thresh) 22 | 23 | assert comp._df.equals(df) 24 | assert comp.c == c 25 | assert comp.p == p 26 | assert comp.values == values 27 | assert comp.m_cp_thresh == m_cp_thresh 28 | 29 | # test check_df 30 | with pytest.raises(TypeError): 31 | comp = Complexity(None, c, p, values, m_cp_thresh) 32 | 33 | def test_calculate_correct_indexes( 34 | self, 35 | data_stub: pd.DataFrame, 36 | correct_rca_stub: pd.DataFrame, 37 | correct_m_stub: pd.DataFrame, 38 | ): 39 | comp = self._get_instance(data_stub) 40 | comp.calculate_indexes() 41 | 42 | assert comp.m.equals(correct_m_stub) 43 | assert comp.rca.round(4).equals(correct_rca_stub) 44 | assert list(comp.eci['eci'].round(3).values) == [0.707, 0.707, -1.414] 45 | assert list(comp.pci['pci'].round(3).values) == [1.414, -0.707, -0.707] 46 | 47 | def test_create_product_space( 48 | self, 49 | data_stub: pd.DataFrame 50 | ): 51 | comp = self._get_instance(data_stub) 52 | comp.calculate_indexes() 53 | comp.create_product_space() 54 | 55 | assert isinstance(comp.complete_graph, nx.Graph) 56 | assert isinstance(comp.maxst, nx.Graph) 57 | assert isinstance(comp.product_space, nx.Graph) 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | 132 | # vscode 133 | **.vscode/* 134 | .vscode/* 135 | .vscode 136 | 137 | # jupyter notebooks 138 | **.ipynb_checkpoints/* 139 | **.ipynb -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: clean clean-test clean-pyc clean-build docs help 2 | .DEFAULT_GOAL := help 3 | 4 | define BROWSER_PYSCRIPT 5 | import os, webbrowser, sys 6 | 7 | from urllib.request import pathname2url 8 | 9 | webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) 10 | endef 11 | export BROWSER_PYSCRIPT 12 | 13 | define PRINT_HELP_PYSCRIPT 14 | import re, sys 15 | 16 | for line in sys.stdin: 17 | match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) 18 | if match: 19 | target, help = match.groups() 20 | print("%-20s %s" % (target, help)) 21 | endef 22 | export PRINT_HELP_PYSCRIPT 23 | 24 | BROWSER := python -c "$$BROWSER_PYSCRIPT" 25 | 26 | help: 27 | @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) 28 | 29 | clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts 30 | 31 | clean-build: ## remove build artifacts 32 | rm -fr build/ 33 | rm -fr dist/ 34 | rm -fr .eggs/ 35 | find . -name '*.egg-info' -exec rm -fr {} + 36 | find . -name '*.egg' -exec rm -f {} + 37 | 38 | clean-pyc: ## remove Python file artifacts 39 | find . -name '*.pyc' -exec rm -f {} + 40 | find . -name '*.pyo' -exec rm -f {} + 41 | find . -name '*~' -exec rm -f {} + 42 | find . -name '__pycache__' -exec rm -fr {} + 43 | 44 | clean-test: ## remove test and coverage artifacts 45 | rm -fr .tox/ 46 | rm -f .coverage 47 | rm -fr htmlcov/ 48 | rm -fr .pytest_cache 49 | 50 | lint: ## check style with flake8 51 | @poetry run flake8 econci tests --statistics 52 | 53 | test: ## run tests quickly with the default Python 54 | @poetry run pytest -vv 55 | 56 | coverage: ## check code coverage quickly with the default Python 57 | @poetry run pytest -vv --cov=econci --cov-report=term-missing tests 58 | 59 | docs: ## generate Sphinx HTML documentation, including API docs 60 | rm -f docs/econci.rst 61 | rm -f docs/modules.rst 62 | sphinx-apidoc -o docs/ econci 63 | $(MAKE) -C docs clean 64 | $(MAKE) -C docs html 65 | $(BROWSER) docs/_build/html/index.html 66 | 67 | servedocs: docs ## compile the docs watching for changes 68 | watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D . 69 | 70 | build: clean ## builds source and wheel package 71 | @poetry build 72 | ls -l dist 73 | 74 | bump-patch: ## Bump version to next patch 75 | @poetry version patch 76 | 77 | bump-minor: ## Bump version to next minor 78 | @poetry version minor 79 | 80 | bump-major: ## Bump version to next major 81 | @poetry version major 82 | 83 | prerelease: ## Create prerelase version 84 | @poetry version prerelease 85 | 86 | publish: build ## Publish new version to internal pypi (nexus) 87 | @poetry publish 88 | 89 | dependencies: 90 | @poetry install --no-dev 91 | 92 | dev-dependencies: dependencies 93 | @poetry install 94 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ====== 2 | econci 3 | ====== 4 | 5 | 6 | .. image:: https://img.shields.io/pypi/v/econci.svg 7 | :target: https://pypi.python.org/pypi/econci 8 | .. image:: https://img.shields.io/pypi/pyversions/econci?style=flat 9 | :target: https://pypi.python.org/pypi/econci 10 | .. image:: https://img.shields.io/github/license/phcsoares/econci 11 | :target: LICENSE 12 | 13 | Calculates Economic Complexity Indexes 14 | 15 | 16 | * Free software: MIT license 17 | 18 | This package implements the indexes found in the Atlas of Economic Complexity [HaRH2014]_, [HiCH2009]_ and [HiCK2007]_. 19 | It also creates the Product Space. 20 | 21 | Installation 22 | ------------ 23 | 24 | :code:`econci` can be installed from PyPI:: 25 | 26 | pip install econci 27 | 28 | or from Anaconda:: 29 | 30 | conda install -c conda-forge econci 31 | 32 | Usage 33 | ----- 34 | 35 | .. code-block:: python 36 | 37 | import econci 38 | 39 | comp = econci.Complexity(df, c='country', p='product', values='export') 40 | comp.calculate_indexes() 41 | eci = comp.eci 42 | pci = comp.pci 43 | 44 | # creating the product space 45 | comp.create_product_space() 46 | 47 | # the graphs are networkx.Graph objects 48 | complete_graph = comp.complete_graph # complete product space 49 | max_spanning_tree = comp.maxst # maximum spanning tree 50 | prod_space = comp.product_space # product space 51 | 52 | # edges_nodes_to_csv saves one csv file with edges and weights 53 | # and another file with nodes information 54 | econci.edges_nodes_to_csv(prod_space, graph_name='prod_space', dir_path='./data/') 55 | 56 | Complete list of calculated indexes: 57 | 58 | * Economic Complexity Index: :code:`comp.eci` 59 | * Product Complexity Index: :code:`comp.pci` 60 | * Country Diversity: :code:`comp.diversity` 61 | * Product Ubiquity: :code:`comp.ubiquity` 62 | * Balassa's RCA [BaBN1989]_: :code:`comp.rca` 63 | * Proximity: :code:`comp.proximity` 64 | * Density: :code:`comp.density` 65 | * Distance: :code:`comp.distance` 66 | 67 | You can also vary the threshold of RCA value when creating the Mcp matrix. 68 | The :code:`Complexity` class accepts the parameter :code:`m_cp_thresh`, which by default is :code:`1.0`. 69 | 70 | :code:`comp.create_product_space()` also accepts the argument :code:`edge_weight_thresh`, by default :code:`0.65`. 71 | This argument filters edges to be added to the maximum spanning tree by weight. 72 | 73 | References 74 | ---------- 75 | 76 | .. [HaRH2014] Hausmann, R., Hidalgo, C. A., Bustos, S., Coscia, M., Chung, S., Jimenez, J., … Yildirim, M. A. (2014). The Atlas of Economic Complexity: Mapping Paths to Prosperity. MIT Press. 77 | .. [HiCH2009] Hidalgo, C. A., & Hausmann, R. (2009). The building blocks of economic complexity. Proceedings of the national academy of sciences, 106(26), 10570-10575. 78 | .. [HiCK2007] Hidalgo, C. A., Klinger, B., Barabási, A. L., & Hausmann, R. (2007). The product space conditions the development of nations. Science, 317(5837), 482-487. 79 | .. [BaBN1989] Balassa, B., & Noland, M. (1989). ``Revealed''Comparative Advantage in Japan and the United States. Journal of International Economic Integration, 8-22. 80 | 81 | 82 | Credits 83 | ------- 84 | 85 | This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template. 86 | 87 | .. _Cookiecutter: https://github.com/audreyr/cookiecutter 88 | .. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage 89 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | .. highlight:: shell 2 | 3 | ============ 4 | Contributing 5 | ============ 6 | 7 | Contributions are welcome, and they are greatly appreciated! Every little bit 8 | helps, and credit will always be given. 9 | 10 | You can contribute in many ways: 11 | 12 | Types of Contributions 13 | ---------------------- 14 | 15 | Report Bugs 16 | ~~~~~~~~~~~ 17 | 18 | Report bugs at https://github.com/phcsoares/econci/issues. 19 | 20 | If you are reporting a bug, please include: 21 | 22 | * Your operating system name and version. 23 | * Any details about your local setup that might be helpful in troubleshooting. 24 | * Detailed steps to reproduce the bug. 25 | 26 | Fix Bugs 27 | ~~~~~~~~ 28 | 29 | Look through the GitHub issues for bugs. Anything tagged with "bug" and "help 30 | wanted" is open to whoever wants to implement it. 31 | 32 | Implement Features 33 | ~~~~~~~~~~~~~~~~~~ 34 | 35 | Look through the GitHub issues for features. Anything tagged with "enhancement" 36 | and "help wanted" is open to whoever wants to implement it. 37 | 38 | Write Documentation 39 | ~~~~~~~~~~~~~~~~~~~ 40 | 41 | econci could always use more documentation, whether as part of the 42 | official econci docs, in docstrings, or even on the web in blog posts, 43 | articles, and such. 44 | 45 | Submit Feedback 46 | ~~~~~~~~~~~~~~~ 47 | 48 | The best way to send feedback is to file an issue at https://github.com/phcsoares/econci/issues. 49 | 50 | If you are proposing a feature: 51 | 52 | * Explain in detail how it would work. 53 | * Keep the scope as narrow as possible, to make it easier to implement. 54 | * Remember that this is a volunteer-driven project, and that contributions 55 | are welcome :) 56 | 57 | Get Started! 58 | ------------ 59 | 60 | Ready to contribute? Here's how to set up `econci` for local development. 61 | 62 | 1. Fork the `econci` repo on GitHub. 63 | 2. Clone your fork locally:: 64 | 65 | $ git clone git@github.com:your_name_here/econci.git 66 | 67 | 3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: 68 | 69 | $ mkvirtualenv econci 70 | $ cd econci/ 71 | $ python setup.py develop 72 | 73 | 4. Create a branch for local development:: 74 | 75 | $ git checkout -b name-of-your-bugfix-or-feature 76 | 77 | Now you can make your changes locally. 78 | 79 | 5. When you're done making changes, check that your changes pass flake8 and the 80 | tests, including testing other Python versions with tox:: 81 | 82 | $ flake8 econci tests 83 | $ python setup.py test or pytest 84 | $ tox 85 | 86 | To get flake8 and tox, just pip install them into your virtualenv. 87 | 88 | 6. Commit your changes and push your branch to GitHub:: 89 | 90 | $ git add . 91 | $ git commit -m "Your detailed description of your changes." 92 | $ git push origin name-of-your-bugfix-or-feature 93 | 94 | 7. Submit a pull request through the GitHub website. 95 | 96 | Pull Request Guidelines 97 | ----------------------- 98 | 99 | Before you submit a pull request, check that it meets these guidelines: 100 | 101 | 1. The pull request should include tests. 102 | 2. If the pull request adds functionality, the docs should be updated. Put 103 | your new functionality into a function with a docstring, and add the 104 | feature to the list in README.rst. 105 | 3. The pull request should work for Python 3.5, 3.6, 3.7 and 3.8, and for PyPy. Check 106 | https://travis-ci.com/phcsoares/econci/pull_requests 107 | and make sure that the tests pass for all supported Python versions. 108 | 109 | Tips 110 | ---- 111 | 112 | To run a subset of tests:: 113 | 114 | 115 | $ python -m unittest tests.test_econci 116 | 117 | Deploying 118 | --------- 119 | 120 | A reminder for the maintainers on how to deploy. 121 | Make sure all your changes are committed (including an entry in HISTORY.rst). 122 | Then run:: 123 | 124 | $ bump2version patch # possible: major / minor / patch 125 | $ git push 126 | $ git push --tags 127 | 128 | Travis will then deploy to PyPI if tests pass. 129 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # econci documentation build configuration file, created by 4 | # sphinx-quickstart on Fri Jun 9 13:47:02 2017. 5 | # 6 | # This file is execfile()d with the current directory set to its 7 | # containing dir. 8 | # 9 | # Note that not all possible configuration values are present in this 10 | # autogenerated file. 11 | # 12 | # All configuration values have a default; values that are commented out 13 | # serve to show the default. 14 | 15 | # If extensions (or modules to document with autodoc) are in another 16 | # directory, add these directories to sys.path here. If the directory is 17 | # relative to the documentation root, use os.path.abspath to make it 18 | # absolute, like shown here. 19 | # 20 | import os 21 | import sys 22 | sys.path.insert(0, os.path.abspath('..')) 23 | 24 | import econci 25 | 26 | # -- General configuration --------------------------------------------- 27 | 28 | # If your documentation needs a minimal Sphinx version, state it here. 29 | # 30 | # needs_sphinx = '1.0' 31 | 32 | # Add any Sphinx extension module names here, as strings. They can be 33 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 34 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] 35 | 36 | # Add any paths that contain templates here, relative to this directory. 37 | templates_path = ['_templates'] 38 | 39 | # The suffix(es) of source filenames. 40 | # You can specify multiple suffix as a list of string: 41 | # 42 | # source_suffix = ['.rst', '.md'] 43 | source_suffix = '.rst' 44 | 45 | # The master toctree document. 46 | master_doc = 'index' 47 | 48 | # General information about the project. 49 | project = 'econci' 50 | copyright = "2020, Pedro Henrique Castro Soares" 51 | author = "Pedro Henrique Castro Soares" 52 | 53 | # The version info for the project you're documenting, acts as replacement 54 | # for |version| and |release|, also used in various other places throughout 55 | # the built documents. 56 | # 57 | # The short X.Y version. 58 | version = econci.__version__ 59 | # The full version, including alpha/beta/rc tags. 60 | release = econci.__version__ 61 | 62 | # The language for content autogenerated by Sphinx. Refer to documentation 63 | # for a list of supported languages. 64 | # 65 | # This is also used if you do content translation via gettext catalogs. 66 | # Usually you set "language" from the command line for these cases. 67 | language = None 68 | 69 | # List of patterns, relative to source directory, that match files and 70 | # directories to ignore when looking for source files. 71 | # This patterns also effect to html_static_path and html_extra_path 72 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 73 | 74 | # The name of the Pygments (syntax highlighting) style to use. 75 | pygments_style = 'sphinx' 76 | 77 | # If true, `todo` and `todoList` produce output, else they produce nothing. 78 | todo_include_todos = False 79 | 80 | 81 | # -- Options for HTML output ------------------------------------------- 82 | 83 | # The theme to use for HTML and HTML Help pages. See the documentation for 84 | # a list of builtin themes. 85 | # 86 | html_theme = 'alabaster' 87 | 88 | # Theme options are theme-specific and customize the look and feel of a 89 | # theme further. For a list of options available for each theme, see the 90 | # documentation. 91 | # 92 | # html_theme_options = {} 93 | 94 | # Add any paths that contain custom static files (such as style sheets) here, 95 | # relative to this directory. They are copied after the builtin static files, 96 | # so a file named "default.css" will overwrite the builtin "default.css". 97 | html_static_path = ['_static'] 98 | 99 | 100 | # -- Options for HTMLHelp output --------------------------------------- 101 | 102 | # Output file base name for HTML help builder. 103 | htmlhelp_basename = 'econcidoc' 104 | 105 | 106 | # -- Options for LaTeX output ------------------------------------------ 107 | 108 | latex_elements = { 109 | # The paper size ('letterpaper' or 'a4paper'). 110 | # 111 | # 'papersize': 'letterpaper', 112 | 113 | # The font size ('10pt', '11pt' or '12pt'). 114 | # 115 | # 'pointsize': '10pt', 116 | 117 | # Additional stuff for the LaTeX preamble. 118 | # 119 | # 'preamble': '', 120 | 121 | # Latex figure (float) alignment 122 | # 123 | # 'figure_align': 'htbp', 124 | } 125 | 126 | # Grouping the document tree into LaTeX files. List of tuples 127 | # (source start file, target name, title, author, documentclass 128 | # [howto, manual, or own class]). 129 | latex_documents = [ 130 | (master_doc, 'econci.tex', 131 | 'econci Documentation', 132 | 'Pedro Henrique Castro Soares', 'manual'), 133 | ] 134 | 135 | 136 | # -- Options for manual page output ------------------------------------ 137 | 138 | # One entry per manual page. List of tuples 139 | # (source start file, name, description, authors, manual section). 140 | man_pages = [ 141 | (master_doc, 'econci', 142 | 'econci Documentation', 143 | [author], 1) 144 | ] 145 | 146 | 147 | # -- Options for Texinfo output ---------------------------------------- 148 | 149 | # Grouping the document tree into Texinfo files. List of tuples 150 | # (source start file, target name, title, author, 151 | # dir menu entry, description, category) 152 | texinfo_documents = [ 153 | (master_doc, 'econci', 154 | 'econci Documentation', 155 | author, 156 | 'econci', 157 | 'One line description of project.', 158 | 'Miscellaneous'), 159 | ] 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /econci/complexity.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import networkx as nx 4 | from .utils import check_if_indexes, check_if_graph 5 | 6 | 7 | class Complexity(): 8 | """ 9 | Calculates complexity indexes. 10 | """ 11 | 12 | def __init__(self, df: pd.DataFrame, c: str, p: str, values: str, m_cp_thresh: float = 1.0): 13 | """ 14 | Parameters 15 | ---------- 16 | df : pandas.DataFrame 17 | Data used in calculations. 18 | c : str 19 | Column equivalent to country. 20 | p : str 21 | Column equivalent to product. 22 | values : str 23 | Column with the values on which to calculate the indexes. 24 | m_cp_thresh : float, optional 25 | Threshold applied to RCA values when creating M_cp. Larger or equal values of RCA become 1 in M_cp, 26 | by default 1.0 27 | """ 28 | self._check_df(df) 29 | self._df = df.copy() 30 | self._c = c 31 | self._p = p 32 | self._values = values 33 | self._m_cp_thresh = m_cp_thresh 34 | 35 | def _check_df(self, df: pd.DataFrame): 36 | """ 37 | Checks if df is a pandas.DataFrame. 38 | 39 | Parameters 40 | ---------- 41 | df : 42 | Data used in calculations. 43 | 44 | Raises 45 | ------ 46 | Exception 47 | `df` is not pandas.DataFrame. 48 | """ 49 | if not isinstance(df, pd.DataFrame): 50 | raise TypeError('df must be a pandas.DataFrame.') 51 | 52 | def _get_m(self): 53 | """ 54 | Pivots the initial `df` so that rows are `c`, columns are `p` and cells are the sum of `values`. 55 | """ 56 | self._m = self._df.groupby([self._c, self._p])[self._values].sum().unstack().fillna(0) 57 | 58 | def _calc_rca(self): 59 | """ 60 | Calculates Balassa's RCA. 61 | """ 62 | sum_p = self._m.sum(axis=0) 63 | sum_c = self._m.sum(axis=1) 64 | sum_tt = sum_c.sum() 65 | 66 | self._rca = self._m.apply(lambda x: (x / sum_c.loc[x.index]) / (sum_p.loc[x.name] / sum_tt)) 67 | 68 | def _get_m_cp(self): 69 | """ 70 | Creates the M_cp binary matrix. 71 | """ 72 | m_cp = self._rca.copy() 73 | thresh = self._m_cp_thresh 74 | m_cp[m_cp >= thresh] = 1 75 | m_cp[m_cp < thresh] = 0 76 | m_cp = m_cp[(m_cp != 0).all(axis=0).index] 77 | m_cp = m_cp.loc[(m_cp != 0).all(axis=1).index] 78 | self._m_cp = m_cp 79 | 80 | def _fix_sign(self, k: pd.Series, ci: pd.DataFrame) -> pd.DataFrame: 81 | """ 82 | Fixes the sign of a complexity index. 83 | The Eigenvalues and Eigenvectors may switch sign, hence the need for the correction. 84 | 85 | Parameters 86 | ---------- 87 | k : pandas.Series 88 | Either diversity or ubiquity. 89 | ci : pandas.DataFrame 90 | Calculated complexity index. 91 | 92 | Returns 93 | ------- 94 | pandas.DataFrame 95 | Corrected sign of complexity index 96 | """ 97 | corr = np.corrcoef(k, ci.iloc[:, 0])[0, 1] 98 | corr_sign = np.sign(corr) 99 | ci *= corr_sign 100 | return ci 101 | 102 | def _get_diversity(self): 103 | """ 104 | Calculates the diversity of countries. 105 | """ 106 | self._diversity = self._m_cp.sum(axis=1) 107 | 108 | def _get_ubiquity(self): 109 | """ 110 | Calculates the ubiquity of proudcts. 111 | """ 112 | self._ubiquity = self._m_cp.sum(axis=0) 113 | 114 | def _calc_eci(self): 115 | """ 116 | Calculates the Ecomomic Complexity Index. 117 | """ 118 | kc0 = self._diversity 119 | kp0 = self._ubiquity 120 | 121 | m_tilda_cc = ((self._m_cp).dot((self._m_cp / kp0).T) / kc0).T 122 | 123 | vals_c, vecs_c = np.linalg.eig(m_tilda_cc) 124 | ind = vals_c.argsort()[-2] 125 | eci = np.real(vecs_c[:, ind]) 126 | eci = (eci - eci.mean()) / eci.std() 127 | eci = pd.DataFrame(eci, index=self._m_cp.index, columns=["eci"]) 128 | 129 | self._eci = self._fix_sign(kc0, eci) 130 | 131 | def _calc_pci(self): 132 | """ 133 | Calculates the Product Complexity Index. 134 | """ 135 | kc0 = self._diversity 136 | kp0 = self._ubiquity 137 | 138 | m_tilda_pp = ((self._m_cp.T).dot((self._m_cp.T / kc0).T) / kp0).T 139 | 140 | vals_p, vecs_p = np.linalg.eig(m_tilda_pp) 141 | ind = vals_p.argsort()[-2] 142 | pci = np.real(vecs_p[:, ind]) 143 | pci = (pci - pci.mean()) / pci.std() 144 | pci = pd.DataFrame(pci, index=self._m_cp.columns, columns=["pci"]) 145 | 146 | self._pci = self._fix_sign(kp0, pci) * (-1) # PCI is negatively correlated with ubiquity 147 | 148 | def _calc_proximity(self): 149 | """ 150 | Calculates the proximity matrix between products. 151 | """ 152 | kp0 = self._ubiquity 153 | phi = self._m_cp.T.dot(self._m_cp) 154 | phi_pp = phi.apply(lambda x: x / np.maximum(kp0.loc[x.name], kp0.loc[x.index])) 155 | np.fill_diagonal(phi_pp.values, 0) 156 | self._proximity = phi_pp 157 | 158 | def _calc_density(self): 159 | """ 160 | Calculates the density of a product in a country. 161 | """ 162 | self._density = self._m_cp.dot(self._proximity) / self._proximity.sum(axis=1) 163 | 164 | def _calc_distance(self): 165 | """ 166 | Calculates the distance of a product to a country. 167 | """ 168 | self._distance = 1 - self._density 169 | 170 | def calculate_indexes(self): 171 | """ 172 | Calculates all indexes. 173 | """ 174 | self._get_m() 175 | self._calc_rca() 176 | self._get_m_cp() 177 | self._get_diversity() 178 | self._get_ubiquity() 179 | self._calc_eci() 180 | self._calc_pci() 181 | self._calc_proximity() 182 | self._calc_density() 183 | self._calc_distance() 184 | 185 | def _generate_graphs(self): 186 | """ 187 | Creates the complete graph from the proximity matrix and finds its 188 | maximum spanning tree. 189 | """ 190 | self._complete_graph = nx.from_pandas_adjacency(self._proximity) 191 | self._maxst = nx.maximum_spanning_tree(self._complete_graph) 192 | 193 | @check_if_indexes 194 | def create_product_space(self, edge_weight_thresh: float = 0.65): 195 | """ 196 | Creates the product space 197 | 198 | Parameters 199 | ---------- 200 | edge_weight_thresh : float, optional 201 | Wheight threshold for extra edges to be added to the maximum 202 | spanning tree, by default 0.65 203 | """ 204 | if not hasattr(self, '_complete_graph'): 205 | self._generate_graphs() 206 | 207 | self._product_space = self._maxst.copy() 208 | for e in self._complete_graph.edges(data=True): 209 | if (e not in self._product_space.edges()) and (e[2]['weight'] > edge_weight_thresh): 210 | self._product_space.add_edges_from([e]) 211 | 212 | @property 213 | def c(self): 214 | return self._c 215 | 216 | @property 217 | def p(self): 218 | return self._p 219 | 220 | @property 221 | def values(self): 222 | return self._values 223 | 224 | @property 225 | def m_cp_thresh(self): 226 | return self._m_cp_thresh 227 | 228 | @property 229 | @check_if_indexes 230 | def m(self): 231 | return self._m.copy() 232 | 233 | @property 234 | @check_if_indexes 235 | def rca(self): 236 | return self._rca.copy() 237 | 238 | @property 239 | @check_if_indexes 240 | def m_cp(self): 241 | return self._m_cp.copy() 242 | 243 | @property 244 | @check_if_indexes 245 | def diversity(self): 246 | return self._diversity.to_frame('diversity').reset_index().copy() 247 | 248 | @property 249 | @check_if_indexes 250 | def ubiquity(self): 251 | return self._ubiquity.to_frame('ubiquity').reset_index().copy() 252 | 253 | @property 254 | @check_if_indexes 255 | def eci(self): 256 | return self._eci.reset_index().copy() 257 | 258 | @property 259 | @check_if_indexes 260 | def pci(self): 261 | return self._pci.reset_index().copy() 262 | 263 | @property 264 | @check_if_indexes 265 | def proximity(self): 266 | return self._proximity.copy() 267 | 268 | @property 269 | @check_if_indexes 270 | def density(self): 271 | return self._density.copy() 272 | 273 | @property 274 | @check_if_indexes 275 | def distance(self): 276 | return self._distance.copy() 277 | 278 | @property 279 | @check_if_graph 280 | def complete_graph(self): 281 | return self._complete_graph 282 | 283 | @property 284 | @check_if_graph 285 | def maxst(self): 286 | return self._maxst 287 | 288 | @property 289 | @check_if_graph 290 | def product_space(self): 291 | return self._product_space 292 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "atomicwrites" 3 | version = "1.4.0" 4 | description = "Atomic file writes." 5 | category = "dev" 6 | optional = false 7 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 8 | 9 | [[package]] 10 | name = "attrs" 11 | version = "21.2.0" 12 | description = "Classes Without Boilerplate" 13 | category = "dev" 14 | optional = false 15 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 16 | 17 | [package.extras] 18 | dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] 19 | docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] 20 | tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] 21 | tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] 22 | 23 | [[package]] 24 | name = "bleach" 25 | version = "4.1.0" 26 | description = "An easy safelist-based HTML-sanitizing tool." 27 | category = "dev" 28 | optional = false 29 | python-versions = ">=3.6" 30 | 31 | [package.dependencies] 32 | packaging = "*" 33 | six = ">=1.9.0" 34 | webencodings = "*" 35 | 36 | [[package]] 37 | name = "certifi" 38 | version = "2021.10.8" 39 | description = "Python package for providing Mozilla's CA Bundle." 40 | category = "dev" 41 | optional = false 42 | python-versions = "*" 43 | 44 | [[package]] 45 | name = "cffi" 46 | version = "1.15.0" 47 | description = "Foreign Function Interface for Python calling C code." 48 | category = "dev" 49 | optional = false 50 | python-versions = "*" 51 | 52 | [package.dependencies] 53 | pycparser = "*" 54 | 55 | [[package]] 56 | name = "charset-normalizer" 57 | version = "2.0.7" 58 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 59 | category = "dev" 60 | optional = false 61 | python-versions = ">=3.5.0" 62 | 63 | [package.extras] 64 | unicode_backport = ["unicodedata2"] 65 | 66 | [[package]] 67 | name = "click" 68 | version = "8.0.3" 69 | description = "Composable command line interface toolkit" 70 | category = "dev" 71 | optional = false 72 | python-versions = ">=3.6" 73 | 74 | [package.dependencies] 75 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 76 | 77 | [[package]] 78 | name = "click-default-group" 79 | version = "1.2.2" 80 | description = "Extends click.Group to invoke a command without explicit subcommand name" 81 | category = "dev" 82 | optional = false 83 | python-versions = "*" 84 | 85 | [package.dependencies] 86 | click = "*" 87 | 88 | [[package]] 89 | name = "colorama" 90 | version = "0.4.4" 91 | description = "Cross-platform colored terminal text." 92 | category = "dev" 93 | optional = false 94 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 95 | 96 | [[package]] 97 | name = "coverage" 98 | version = "6.0.2" 99 | description = "Code coverage measurement for Python" 100 | category = "dev" 101 | optional = false 102 | python-versions = ">=3.6" 103 | 104 | [package.dependencies] 105 | tomli = {version = "*", optional = true, markers = "extra == \"toml\""} 106 | 107 | [package.extras] 108 | toml = ["tomli"] 109 | 110 | [[package]] 111 | name = "cryptography" 112 | version = "35.0.0" 113 | description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." 114 | category = "dev" 115 | optional = false 116 | python-versions = ">=3.6" 117 | 118 | [package.dependencies] 119 | cffi = ">=1.12" 120 | 121 | [package.extras] 122 | docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"] 123 | docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] 124 | pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] 125 | sdist = ["setuptools_rust (>=0.11.4)"] 126 | ssh = ["bcrypt (>=3.1.5)"] 127 | test = ["pytest (>=6.2.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] 128 | 129 | [[package]] 130 | name = "docutils" 131 | version = "0.18" 132 | description = "Docutils -- Python Documentation Utilities" 133 | category = "dev" 134 | optional = false 135 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 136 | 137 | [[package]] 138 | name = "flake8" 139 | version = "4.0.1" 140 | description = "the modular source code checker: pep8 pyflakes and co" 141 | category = "dev" 142 | optional = false 143 | python-versions = ">=3.6" 144 | 145 | [package.dependencies] 146 | mccabe = ">=0.6.0,<0.7.0" 147 | pycodestyle = ">=2.8.0,<2.9.0" 148 | pyflakes = ">=2.4.0,<2.5.0" 149 | 150 | [[package]] 151 | name = "idna" 152 | version = "3.3" 153 | description = "Internationalized Domain Names in Applications (IDNA)" 154 | category = "dev" 155 | optional = false 156 | python-versions = ">=3.5" 157 | 158 | [[package]] 159 | name = "importlib-metadata" 160 | version = "4.8.1" 161 | description = "Read metadata from Python packages" 162 | category = "dev" 163 | optional = false 164 | python-versions = ">=3.6" 165 | 166 | [package.dependencies] 167 | zipp = ">=0.5" 168 | 169 | [package.extras] 170 | docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] 171 | perf = ["ipython"] 172 | testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] 173 | 174 | [[package]] 175 | name = "incremental" 176 | version = "21.3.0" 177 | description = "A small library that versions your Python projects." 178 | category = "dev" 179 | optional = false 180 | python-versions = "*" 181 | 182 | [package.extras] 183 | scripts = ["click (>=6.0)", "twisted (>=16.4.0)"] 184 | 185 | [[package]] 186 | name = "iniconfig" 187 | version = "1.1.1" 188 | description = "iniconfig: brain-dead simple config-ini parsing" 189 | category = "dev" 190 | optional = false 191 | python-versions = "*" 192 | 193 | [[package]] 194 | name = "jeepney" 195 | version = "0.7.1" 196 | description = "Low-level, pure Python DBus protocol wrapper." 197 | category = "dev" 198 | optional = false 199 | python-versions = ">=3.6" 200 | 201 | [package.extras] 202 | test = ["pytest", "pytest-trio", "pytest-asyncio", "testpath", "trio", "async-timeout"] 203 | trio = ["trio", "async-generator"] 204 | 205 | [[package]] 206 | name = "jinja2" 207 | version = "3.0.2" 208 | description = "A very fast and expressive template engine." 209 | category = "dev" 210 | optional = false 211 | python-versions = ">=3.6" 212 | 213 | [package.dependencies] 214 | MarkupSafe = ">=2.0" 215 | 216 | [package.extras] 217 | i18n = ["Babel (>=2.7)"] 218 | 219 | [[package]] 220 | name = "keyring" 221 | version = "23.2.1" 222 | description = "Store and access your passwords safely." 223 | category = "dev" 224 | optional = false 225 | python-versions = ">=3.6" 226 | 227 | [package.dependencies] 228 | importlib-metadata = ">=3.6" 229 | jeepney = {version = ">=0.4.2", markers = "sys_platform == \"linux\""} 230 | pywin32-ctypes = {version = "<0.1.0 || >0.1.0,<0.1.1 || >0.1.1", markers = "sys_platform == \"win32\""} 231 | SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} 232 | 233 | [package.extras] 234 | docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] 235 | testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"] 236 | 237 | [[package]] 238 | name = "markupsafe" 239 | version = "2.0.1" 240 | description = "Safely add untrusted strings to HTML/XML markup." 241 | category = "dev" 242 | optional = false 243 | python-versions = ">=3.6" 244 | 245 | [[package]] 246 | name = "mccabe" 247 | version = "0.6.1" 248 | description = "McCabe checker, plugin for flake8" 249 | category = "dev" 250 | optional = false 251 | python-versions = "*" 252 | 253 | [[package]] 254 | name = "networkx" 255 | version = "2.6.3" 256 | description = "Python package for creating and manipulating graphs and networks" 257 | category = "main" 258 | optional = false 259 | python-versions = ">=3.7" 260 | 261 | [package.extras] 262 | default = ["numpy (>=1.19)", "scipy (>=1.5,!=1.6.1)", "matplotlib (>=3.3)", "pandas (>=1.1)"] 263 | developer = ["black (==21.5b1)", "pre-commit (>=2.12)"] 264 | doc = ["sphinx (>=4.0,<5.0)", "pydata-sphinx-theme (>=0.6,<1.0)", "sphinx-gallery (>=0.9,<1.0)", "numpydoc (>=1.1)", "pillow (>=8.2)", "nb2plots (>=0.6)", "texext (>=0.6.6)"] 265 | extra = ["lxml (>=4.5)", "pygraphviz (>=1.7)", "pydot (>=1.4.1)"] 266 | test = ["pytest (>=6.2)", "pytest-cov (>=2.12)", "codecov (>=2.1)"] 267 | 268 | [[package]] 269 | name = "numpy" 270 | version = "1.21.1" 271 | description = "NumPy is the fundamental package for array computing with Python." 272 | category = "main" 273 | optional = false 274 | python-versions = ">=3.7" 275 | 276 | [[package]] 277 | name = "numpy" 278 | version = "1.21.3" 279 | description = "NumPy is the fundamental package for array computing with Python." 280 | category = "main" 281 | optional = false 282 | python-versions = ">=3.7,<3.11" 283 | 284 | [[package]] 285 | name = "packaging" 286 | version = "21.0" 287 | description = "Core utilities for Python packages" 288 | category = "dev" 289 | optional = false 290 | python-versions = ">=3.6" 291 | 292 | [package.dependencies] 293 | pyparsing = ">=2.0.2" 294 | 295 | [[package]] 296 | name = "pandas" 297 | version = "1.3.4" 298 | description = "Powerful data structures for data analysis, time series, and statistics" 299 | category = "main" 300 | optional = false 301 | python-versions = ">=3.7.1" 302 | 303 | [package.dependencies] 304 | numpy = [ 305 | {version = ">=1.17.3", markers = "platform_machine != \"aarch64\" and platform_machine != \"arm64\" and python_version < \"3.10\""}, 306 | {version = ">=1.19.2", markers = "platform_machine == \"aarch64\" and python_version < \"3.10\""}, 307 | {version = ">=1.20.0", markers = "platform_machine == \"arm64\" and python_version < \"3.10\""}, 308 | {version = ">=1.21.0", markers = "python_version >= \"3.10\""}, 309 | ] 310 | python-dateutil = ">=2.7.3" 311 | pytz = ">=2017.3" 312 | 313 | [package.extras] 314 | test = ["hypothesis (>=3.58)", "pytest (>=6.0)", "pytest-xdist"] 315 | 316 | [[package]] 317 | name = "pkginfo" 318 | version = "1.7.1" 319 | description = "Query metadatdata from sdists / bdists / installed packages." 320 | category = "dev" 321 | optional = false 322 | python-versions = "*" 323 | 324 | [package.extras] 325 | testing = ["nose", "coverage"] 326 | 327 | [[package]] 328 | name = "pluggy" 329 | version = "1.0.0" 330 | description = "plugin and hook calling mechanisms for python" 331 | category = "dev" 332 | optional = false 333 | python-versions = ">=3.6" 334 | 335 | [package.extras] 336 | dev = ["pre-commit", "tox"] 337 | testing = ["pytest", "pytest-benchmark"] 338 | 339 | [[package]] 340 | name = "py" 341 | version = "1.10.0" 342 | description = "library with cross-python path, ini-parsing, io, code, log facilities" 343 | category = "dev" 344 | optional = false 345 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 346 | 347 | [[package]] 348 | name = "pycodestyle" 349 | version = "2.8.0" 350 | description = "Python style guide checker" 351 | category = "dev" 352 | optional = false 353 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 354 | 355 | [[package]] 356 | name = "pycparser" 357 | version = "2.20" 358 | description = "C parser in Python" 359 | category = "dev" 360 | optional = false 361 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 362 | 363 | [[package]] 364 | name = "pyflakes" 365 | version = "2.4.0" 366 | description = "passive checker of Python programs" 367 | category = "dev" 368 | optional = false 369 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 370 | 371 | [[package]] 372 | name = "pygments" 373 | version = "2.10.0" 374 | description = "Pygments is a syntax highlighting package written in Python." 375 | category = "dev" 376 | optional = false 377 | python-versions = ">=3.5" 378 | 379 | [[package]] 380 | name = "pyparsing" 381 | version = "3.0.1" 382 | description = "Python parsing module" 383 | category = "dev" 384 | optional = false 385 | python-versions = ">=3.6" 386 | 387 | [package.extras] 388 | diagrams = ["jinja2", "railroad-diagrams"] 389 | 390 | [[package]] 391 | name = "pytest" 392 | version = "6.2.5" 393 | description = "pytest: simple powerful testing with Python" 394 | category = "dev" 395 | optional = false 396 | python-versions = ">=3.6" 397 | 398 | [package.dependencies] 399 | atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} 400 | attrs = ">=19.2.0" 401 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 402 | iniconfig = "*" 403 | packaging = "*" 404 | pluggy = ">=0.12,<2.0" 405 | py = ">=1.8.2" 406 | toml = "*" 407 | 408 | [package.extras] 409 | testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] 410 | 411 | [[package]] 412 | name = "pytest-cov" 413 | version = "3.0.0" 414 | description = "Pytest plugin for measuring coverage." 415 | category = "dev" 416 | optional = false 417 | python-versions = ">=3.6" 418 | 419 | [package.dependencies] 420 | coverage = {version = ">=5.2.1", extras = ["toml"]} 421 | pytest = ">=4.6" 422 | 423 | [package.extras] 424 | testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] 425 | 426 | [[package]] 427 | name = "python-dateutil" 428 | version = "2.8.2" 429 | description = "Extensions to the standard Python datetime module" 430 | category = "main" 431 | optional = false 432 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 433 | 434 | [package.dependencies] 435 | six = ">=1.5" 436 | 437 | [[package]] 438 | name = "pytz" 439 | version = "2021.3" 440 | description = "World timezone definitions, modern and historical" 441 | category = "main" 442 | optional = false 443 | python-versions = "*" 444 | 445 | [[package]] 446 | name = "pywin32-ctypes" 447 | version = "0.2.0" 448 | description = "" 449 | category = "dev" 450 | optional = false 451 | python-versions = "*" 452 | 453 | [[package]] 454 | name = "readme-renderer" 455 | version = "30.0" 456 | description = "readme_renderer is a library for rendering \"readme\" descriptions for Warehouse" 457 | category = "dev" 458 | optional = false 459 | python-versions = "*" 460 | 461 | [package.dependencies] 462 | bleach = ">=2.1.0" 463 | docutils = ">=0.13.1" 464 | Pygments = ">=2.5.1" 465 | 466 | [package.extras] 467 | md = ["cmarkgfm (>=0.5.0,<0.7.0)"] 468 | 469 | [[package]] 470 | name = "requests" 471 | version = "2.26.0" 472 | description = "Python HTTP for Humans." 473 | category = "dev" 474 | optional = false 475 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 476 | 477 | [package.dependencies] 478 | certifi = ">=2017.4.17" 479 | charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} 480 | idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} 481 | urllib3 = ">=1.21.1,<1.27" 482 | 483 | [package.extras] 484 | socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] 485 | use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] 486 | 487 | [[package]] 488 | name = "requests-toolbelt" 489 | version = "0.9.1" 490 | description = "A utility belt for advanced users of python-requests" 491 | category = "dev" 492 | optional = false 493 | python-versions = "*" 494 | 495 | [package.dependencies] 496 | requests = ">=2.0.1,<3.0.0" 497 | 498 | [[package]] 499 | name = "rfc3986" 500 | version = "1.5.0" 501 | description = "Validating URI References per RFC 3986" 502 | category = "dev" 503 | optional = false 504 | python-versions = "*" 505 | 506 | [package.extras] 507 | idna2008 = ["idna"] 508 | 509 | [[package]] 510 | name = "secretstorage" 511 | version = "3.3.1" 512 | description = "Python bindings to FreeDesktop.org Secret Service API" 513 | category = "dev" 514 | optional = false 515 | python-versions = ">=3.6" 516 | 517 | [package.dependencies] 518 | cryptography = ">=2.0" 519 | jeepney = ">=0.6" 520 | 521 | [[package]] 522 | name = "six" 523 | version = "1.16.0" 524 | description = "Python 2 and 3 compatibility utilities" 525 | category = "main" 526 | optional = false 527 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 528 | 529 | [[package]] 530 | name = "toml" 531 | version = "0.10.2" 532 | description = "Python Library for Tom's Obvious, Minimal Language" 533 | category = "dev" 534 | optional = false 535 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 536 | 537 | [[package]] 538 | name = "tomli" 539 | version = "1.2.2" 540 | description = "A lil' TOML parser" 541 | category = "dev" 542 | optional = false 543 | python-versions = ">=3.6" 544 | 545 | [[package]] 546 | name = "towncrier" 547 | version = "21.3.0" 548 | description = "Building newsfiles for your project." 549 | category = "dev" 550 | optional = false 551 | python-versions = "*" 552 | 553 | [package.dependencies] 554 | click = "*" 555 | click-default-group = "*" 556 | incremental = "*" 557 | jinja2 = "*" 558 | toml = "*" 559 | 560 | [package.extras] 561 | dev = ["packaging"] 562 | 563 | [[package]] 564 | name = "tqdm" 565 | version = "4.62.3" 566 | description = "Fast, Extensible Progress Meter" 567 | category = "dev" 568 | optional = false 569 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" 570 | 571 | [package.dependencies] 572 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 573 | 574 | [package.extras] 575 | dev = ["py-make (>=0.1.0)", "twine", "wheel"] 576 | notebook = ["ipywidgets (>=6)"] 577 | telegram = ["requests"] 578 | 579 | [[package]] 580 | name = "twine" 581 | version = "3.4.2" 582 | description = "Collection of utilities for publishing packages on PyPI" 583 | category = "dev" 584 | optional = false 585 | python-versions = ">=3.6" 586 | 587 | [package.dependencies] 588 | colorama = ">=0.4.3" 589 | importlib-metadata = ">=3.6" 590 | keyring = ">=15.1" 591 | pkginfo = ">=1.4.2" 592 | readme-renderer = ">=21.0" 593 | requests = ">=2.20" 594 | requests-toolbelt = ">=0.8.0,<0.9.0 || >0.9.0" 595 | rfc3986 = ">=1.4.0" 596 | tqdm = ">=4.14" 597 | 598 | [[package]] 599 | name = "urllib3" 600 | version = "1.26.7" 601 | description = "HTTP library with thread-safe connection pooling, file post, and more." 602 | category = "dev" 603 | optional = false 604 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 605 | 606 | [package.extras] 607 | brotli = ["brotlipy (>=0.6.0)"] 608 | secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] 609 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 610 | 611 | [[package]] 612 | name = "webencodings" 613 | version = "0.5.1" 614 | description = "Character encoding aliases for legacy web content" 615 | category = "dev" 616 | optional = false 617 | python-versions = "*" 618 | 619 | [[package]] 620 | name = "zipp" 621 | version = "3.6.0" 622 | description = "Backport of pathlib-compatible object wrapper for zip files" 623 | category = "dev" 624 | optional = false 625 | python-versions = ">=3.6" 626 | 627 | [package.extras] 628 | docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] 629 | testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] 630 | 631 | [metadata] 632 | lock-version = "1.1" 633 | python-versions = "^3.8" 634 | content-hash = "b0c88b1a5fb657325517ce5ef72824ee0c8d55e30702b14ca4c6b5490b518f58" 635 | 636 | [metadata.files] 637 | atomicwrites = [ 638 | {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, 639 | {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, 640 | ] 641 | attrs = [ 642 | {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, 643 | {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, 644 | ] 645 | bleach = [ 646 | {file = "bleach-4.1.0-py2.py3-none-any.whl", hash = "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"}, 647 | {file = "bleach-4.1.0.tar.gz", hash = "sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da"}, 648 | ] 649 | certifi = [ 650 | {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, 651 | {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, 652 | ] 653 | cffi = [ 654 | {file = "cffi-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962"}, 655 | {file = "cffi-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0"}, 656 | {file = "cffi-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14"}, 657 | {file = "cffi-1.15.0-cp27-cp27m-win32.whl", hash = "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474"}, 658 | {file = "cffi-1.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6"}, 659 | {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27"}, 660 | {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023"}, 661 | {file = "cffi-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2"}, 662 | {file = "cffi-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e"}, 663 | {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7"}, 664 | {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3"}, 665 | {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c"}, 666 | {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962"}, 667 | {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382"}, 668 | {file = "cffi-1.15.0-cp310-cp310-win32.whl", hash = "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55"}, 669 | {file = "cffi-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0"}, 670 | {file = "cffi-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e"}, 671 | {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39"}, 672 | {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc"}, 673 | {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032"}, 674 | {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8"}, 675 | {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605"}, 676 | {file = "cffi-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e"}, 677 | {file = "cffi-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc"}, 678 | {file = "cffi-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636"}, 679 | {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4"}, 680 | {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997"}, 681 | {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b"}, 682 | {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2"}, 683 | {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7"}, 684 | {file = "cffi-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66"}, 685 | {file = "cffi-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029"}, 686 | {file = "cffi-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880"}, 687 | {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20"}, 688 | {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024"}, 689 | {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e"}, 690 | {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728"}, 691 | {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6"}, 692 | {file = "cffi-1.15.0-cp38-cp38-win32.whl", hash = "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c"}, 693 | {file = "cffi-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443"}, 694 | {file = "cffi-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a"}, 695 | {file = "cffi-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37"}, 696 | {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a"}, 697 | {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e"}, 698 | {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796"}, 699 | {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df"}, 700 | {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8"}, 701 | {file = "cffi-1.15.0-cp39-cp39-win32.whl", hash = "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a"}, 702 | {file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"}, 703 | {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"}, 704 | ] 705 | charset-normalizer = [ 706 | {file = "charset-normalizer-2.0.7.tar.gz", hash = "sha256:e019de665e2bcf9c2b64e2e5aa025fa991da8720daa3c1138cadd2fd1856aed0"}, 707 | {file = "charset_normalizer-2.0.7-py3-none-any.whl", hash = "sha256:f7af805c321bfa1ce6714c51f254e0d5bb5e5834039bc17db7ebe3a4cec9492b"}, 708 | ] 709 | click = [ 710 | {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, 711 | {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, 712 | ] 713 | click-default-group = [ 714 | {file = "click-default-group-1.2.2.tar.gz", hash = "sha256:d9560e8e8dfa44b3562fbc9425042a0fd6d21956fcc2db0077f63f34253ab904"}, 715 | ] 716 | colorama = [ 717 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 718 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 719 | ] 720 | coverage = [ 721 | {file = "coverage-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1549e1d08ce38259de2bc3e9a0d5f3642ff4a8f500ffc1b2df73fd621a6cdfc0"}, 722 | {file = "coverage-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcae10fccb27ca2a5f456bf64d84110a5a74144be3136a5e598f9d9fb48c0caa"}, 723 | {file = "coverage-6.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:53a294dc53cfb39c74758edaa6305193fb4258a30b1f6af24b360a6c8bd0ffa7"}, 724 | {file = "coverage-6.0.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8251b37be1f2cd9c0e5ccd9ae0380909c24d2a5ed2162a41fcdbafaf59a85ebd"}, 725 | {file = "coverage-6.0.2-cp310-cp310-win32.whl", hash = "sha256:db42baa892cba723326284490283a68d4de516bfb5aaba369b4e3b2787a778b7"}, 726 | {file = "coverage-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:bbffde2a68398682623d9dd8c0ca3f46fda074709b26fcf08ae7a4c431a6ab2d"}, 727 | {file = "coverage-6.0.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:60e51a3dd55540bec686d7fff61b05048ca31e804c1f32cbb44533e6372d9cc3"}, 728 | {file = "coverage-6.0.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a6a9409223a27d5ef3cca57dd7cd4dfcb64aadf2fad5c3b787830ac9223e01a"}, 729 | {file = "coverage-6.0.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4b34ae4f51bbfa5f96b758b55a163d502be3dcb24f505d0227858c2b3f94f5b9"}, 730 | {file = "coverage-6.0.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3bbda1b550e70fa6ac40533d3f23acd4f4e9cb4e6e77251ce77fdf41b3309fb2"}, 731 | {file = "coverage-6.0.2-cp36-cp36m-win32.whl", hash = "sha256:4e28d2a195c533b58fc94a12826f4431726d8eb029ac21d874345f943530c122"}, 732 | {file = "coverage-6.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a82d79586a0a4f5fd1cf153e647464ced402938fbccb3ffc358c7babd4da1dd9"}, 733 | {file = "coverage-6.0.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3be1206dc09fb6298de3fce70593e27436862331a85daee36270b6d0e1c251c4"}, 734 | {file = "coverage-6.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9cd3828bbe1a40070c11fe16a51df733fd2f0cb0d745fb83b7b5c1f05967df7"}, 735 | {file = "coverage-6.0.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d036dc1ed8e1388e995833c62325df3f996675779541f682677efc6af71e96cc"}, 736 | {file = "coverage-6.0.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04560539c19ec26995ecfb3d9307ff154fbb9a172cb57e3b3cfc4ced673103d1"}, 737 | {file = "coverage-6.0.2-cp37-cp37m-win32.whl", hash = "sha256:e4fb7ced4d9dec77d6cf533acfbf8e1415fe799430366affb18d69ee8a3c6330"}, 738 | {file = "coverage-6.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:77b1da5767ed2f44611bc9bc019bc93c03fa495728ec389759b6e9e5039ac6b1"}, 739 | {file = "coverage-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:61b598cbdbaae22d9e34e3f675997194342f866bb1d781da5d0be54783dce1ff"}, 740 | {file = "coverage-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36e9040a43d2017f2787b28d365a4bb33fcd792c7ff46a047a04094dc0e2a30d"}, 741 | {file = "coverage-6.0.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9f1627e162e3864a596486774876415a7410021f4b67fd2d9efdf93ade681afc"}, 742 | {file = "coverage-6.0.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e7a0b42db2a47ecb488cde14e0f6c7679a2c5a9f44814393b162ff6397fcdfbb"}, 743 | {file = "coverage-6.0.2-cp38-cp38-win32.whl", hash = "sha256:a1b73c7c4d2a42b9d37dd43199c5711d91424ff3c6c22681bc132db4a4afec6f"}, 744 | {file = "coverage-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:1db67c497688fd4ba85b373b37cc52c50d437fd7267520ecd77bddbd89ea22c9"}, 745 | {file = "coverage-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f2f184bf38e74f152eed7f87e345b51f3ab0b703842f447c22efe35e59942c24"}, 746 | {file = "coverage-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd1cf1deb3d5544bd942356364a2fdc8959bad2b6cf6eb17f47d301ea34ae822"}, 747 | {file = "coverage-6.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ad9b8c1206ae41d46ec7380b78ba735ebb77758a650643e841dd3894966c31d0"}, 748 | {file = "coverage-6.0.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:381d773d896cc7f8ba4ff3b92dee4ed740fb88dfe33b6e42efc5e8ab6dfa1cfe"}, 749 | {file = "coverage-6.0.2-cp39-cp39-win32.whl", hash = "sha256:424c44f65e8be58b54e2b0bd1515e434b940679624b1b72726147cfc6a9fc7ce"}, 750 | {file = "coverage-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:abbff240f77347d17306d3201e14431519bf64495648ca5a49571f988f88dee9"}, 751 | {file = "coverage-6.0.2-pp36-none-any.whl", hash = "sha256:7092eab374346121805fb637572483270324407bf150c30a3b161fc0c4ca5164"}, 752 | {file = "coverage-6.0.2-pp37-none-any.whl", hash = "sha256:30922626ce6f7a5a30bdba984ad21021529d3d05a68b4f71ea3b16bda35b8895"}, 753 | {file = "coverage-6.0.2.tar.gz", hash = "sha256:6807947a09510dc31fa86f43595bf3a14017cd60bf633cc746d52141bfa6b149"}, 754 | ] 755 | cryptography = [ 756 | {file = "cryptography-35.0.0-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:d57e0cdc1b44b6cdf8af1d01807db06886f10177469312fbde8f44ccbb284bc9"}, 757 | {file = "cryptography-35.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:ced40344e811d6abba00295ced98c01aecf0c2de39481792d87af4fa58b7b4d6"}, 758 | {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:54b2605e5475944e2213258e0ab8696f4f357a31371e538ef21e8d61c843c28d"}, 759 | {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7b7ceeff114c31f285528ba8b390d3e9cfa2da17b56f11d366769a807f17cbaa"}, 760 | {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d69645f535f4b2c722cfb07a8eab916265545b3475fdb34e0be2f4ee8b0b15e"}, 761 | {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2d0e0acc20ede0f06ef7aa58546eee96d2592c00f450c9acb89c5879b61992"}, 762 | {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:07bb7fbfb5de0980590ddfc7f13081520def06dc9ed214000ad4372fb4e3c7f6"}, 763 | {file = "cryptography-35.0.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7eba2cebca600a7806b893cb1d541a6e910afa87e97acf2021a22b32da1df52d"}, 764 | {file = "cryptography-35.0.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:18d90f4711bf63e2fb21e8c8e51ed8189438e6b35a6d996201ebd98a26abbbe6"}, 765 | {file = "cryptography-35.0.0-cp36-abi3-win32.whl", hash = "sha256:c10c797ac89c746e488d2ee92bd4abd593615694ee17b2500578b63cad6b93a8"}, 766 | {file = "cryptography-35.0.0-cp36-abi3-win_amd64.whl", hash = "sha256:7075b304cd567694dc692ffc9747f3e9cb393cc4aa4fb7b9f3abd6f5c4e43588"}, 767 | {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a688ebcd08250eab5bb5bca318cc05a8c66de5e4171a65ca51db6bd753ff8953"}, 768 | {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d99915d6ab265c22873f1b4d6ea5ef462ef797b4140be4c9d8b179915e0985c6"}, 769 | {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:928185a6d1ccdb816e883f56ebe92e975a262d31cc536429041921f8cb5a62fd"}, 770 | {file = "cryptography-35.0.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ebeddd119f526bcf323a89f853afb12e225902a24d29b55fe18dd6fcb2838a76"}, 771 | {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:22a38e96118a4ce3b97509443feace1d1011d0571fae81fc3ad35f25ba3ea999"}, 772 | {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb80e8a1f91e4b7ef8b33041591e6d89b2b8e122d787e87eeb2b08da71bb16ad"}, 773 | {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:abb5a361d2585bb95012a19ed9b2c8f412c5d723a9836418fab7aaa0243e67d2"}, 774 | {file = "cryptography-35.0.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:1ed82abf16df40a60942a8c211251ae72858b25b7421ce2497c2eb7a1cee817c"}, 775 | {file = "cryptography-35.0.0.tar.gz", hash = "sha256:9933f28f70d0517686bd7de36166dda42094eac49415459d9bdf5e7df3e0086d"}, 776 | ] 777 | docutils = [ 778 | {file = "docutils-0.18-py2.py3-none-any.whl", hash = "sha256:a31688b2ea858517fa54293e5d5df06fbb875fb1f7e4c64529271b77781ca8fc"}, 779 | {file = "docutils-0.18.tar.gz", hash = "sha256:c1d5dab2b11d16397406a282e53953fe495a46d69ae329f55aa98a5c4e3c5fbb"}, 780 | ] 781 | flake8 = [ 782 | {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, 783 | {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, 784 | ] 785 | idna = [ 786 | {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, 787 | {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, 788 | ] 789 | importlib-metadata = [ 790 | {file = "importlib_metadata-4.8.1-py3-none-any.whl", hash = "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15"}, 791 | {file = "importlib_metadata-4.8.1.tar.gz", hash = "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1"}, 792 | ] 793 | incremental = [ 794 | {file = "incremental-21.3.0-py2.py3-none-any.whl", hash = "sha256:92014aebc6a20b78a8084cdd5645eeaa7f74b8933f70fa3ada2cfbd1e3b54321"}, 795 | {file = "incremental-21.3.0.tar.gz", hash = "sha256:02f5de5aff48f6b9f665d99d48bfc7ec03b6e3943210de7cfc88856d755d6f57"}, 796 | ] 797 | iniconfig = [ 798 | {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, 799 | {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, 800 | ] 801 | jeepney = [ 802 | {file = "jeepney-0.7.1-py3-none-any.whl", hash = "sha256:1b5a0ea5c0e7b166b2f5895b91a08c14de8915afda4407fb5022a195224958ac"}, 803 | {file = "jeepney-0.7.1.tar.gz", hash = "sha256:fa9e232dfa0c498bd0b8a3a73b8d8a31978304dcef0515adc859d4e096f96f4f"}, 804 | ] 805 | jinja2 = [ 806 | {file = "Jinja2-3.0.2-py3-none-any.whl", hash = "sha256:8569982d3f0889eed11dd620c706d39b60c36d6d25843961f33f77fb6bc6b20c"}, 807 | {file = "Jinja2-3.0.2.tar.gz", hash = "sha256:827a0e32839ab1600d4eb1c4c33ec5a8edfbc5cb42dafa13b81f182f97784b45"}, 808 | ] 809 | keyring = [ 810 | {file = "keyring-23.2.1-py3-none-any.whl", hash = "sha256:bd2145a237ed70c8ce72978b497619ddfcae640b6dcf494402d5143e37755c6e"}, 811 | {file = "keyring-23.2.1.tar.gz", hash = "sha256:6334aee6073db2fb1f30892697b1730105b5e9a77ce7e61fca6b435225493efe"}, 812 | ] 813 | markupsafe = [ 814 | {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, 815 | {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, 816 | {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, 817 | {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, 818 | {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, 819 | {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, 820 | {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, 821 | {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, 822 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, 823 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, 824 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, 825 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, 826 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, 827 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, 828 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, 829 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, 830 | {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, 831 | {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, 832 | {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, 833 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"}, 834 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"}, 835 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, 836 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, 837 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, 838 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, 839 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, 840 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, 841 | {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, 842 | {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, 843 | {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, 844 | {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, 845 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, 846 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, 847 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, 848 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, 849 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, 850 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, 851 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, 852 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, 853 | {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, 854 | {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, 855 | {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, 856 | {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"}, 857 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"}, 858 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"}, 859 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, 860 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, 861 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, 862 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, 863 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, 864 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, 865 | {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, 866 | {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, 867 | {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, 868 | ] 869 | mccabe = [ 870 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 871 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, 872 | ] 873 | networkx = [ 874 | {file = "networkx-2.6.3-py3-none-any.whl", hash = "sha256:80b6b89c77d1dfb64a4c7854981b60aeea6360ac02c6d4e4913319e0a313abef"}, 875 | {file = "networkx-2.6.3.tar.gz", hash = "sha256:c0946ed31d71f1b732b5aaa6da5a0388a345019af232ce2f49c766e2d6795c51"}, 876 | ] 877 | numpy = [ 878 | {file = "numpy-1.21.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38e8648f9449a549a7dfe8d8755a5979b45b3538520d1e735637ef28e8c2dc50"}, 879 | {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fd7d7409fa643a91d0a05c7554dd68aa9c9bb16e186f6ccfe40d6e003156e33a"}, 880 | {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a75b4498b1e93d8b700282dc8e655b8bd559c0904b3910b144646dbbbc03e062"}, 881 | {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1412aa0aec3e00bc23fbb8664d76552b4efde98fb71f60737c83efbac24112f1"}, 882 | {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e46ceaff65609b5399163de5893d8f2a82d3c77d5e56d976c8b5fb01faa6b671"}, 883 | {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c6a2324085dd52f96498419ba95b5777e40b6bcbc20088fddb9e8cbb58885e8e"}, 884 | {file = "numpy-1.21.1-cp37-cp37m-win32.whl", hash = "sha256:73101b2a1fef16602696d133db402a7e7586654682244344b8329cdcbbb82172"}, 885 | {file = "numpy-1.21.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7a708a79c9a9d26904d1cca8d383bf869edf6f8e7650d85dbc77b041e8c5a0f8"}, 886 | {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95b995d0c413f5d0428b3f880e8fe1660ff9396dcd1f9eedbc311f37b5652e16"}, 887 | {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:635e6bd31c9fb3d475c8f44a089569070d10a9ef18ed13738b03049280281267"}, 888 | {file = "numpy-1.21.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a3d5fb89bfe21be2ef47c0614b9c9c707b7362386c9a3ff1feae63e0267ccb6"}, 889 | {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a326af80e86d0e9ce92bcc1e65c8ff88297de4fa14ee936cb2293d414c9ec63"}, 890 | {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:791492091744b0fe390a6ce85cc1bf5149968ac7d5f0477288f78c89b385d9af"}, 891 | {file = "numpy-1.21.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0318c465786c1f63ac05d7c4dbcecd4d2d7e13f0959b01b534ea1e92202235c5"}, 892 | {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a513bd9c1551894ee3d31369f9b07460ef223694098cf27d399513415855b68"}, 893 | {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:91c6f5fc58df1e0a3cc0c3a717bb3308ff850abdaa6d2d802573ee2b11f674a8"}, 894 | {file = "numpy-1.21.1-cp38-cp38-win32.whl", hash = "sha256:978010b68e17150db8765355d1ccdd450f9fc916824e8c4e35ee620590e234cd"}, 895 | {file = "numpy-1.21.1-cp38-cp38-win_amd64.whl", hash = "sha256:9749a40a5b22333467f02fe11edc98f022133ee1bfa8ab99bda5e5437b831214"}, 896 | {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d7a4aeac3b94af92a9373d6e77b37691b86411f9745190d2c351f410ab3a791f"}, 897 | {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d9e7912a56108aba9b31df688a4c4f5cb0d9d3787386b87d504762b6754fbb1b"}, 898 | {file = "numpy-1.21.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:25b40b98ebdd272bc3020935427a4530b7d60dfbe1ab9381a39147834e985eac"}, 899 | {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a92c5aea763d14ba9d6475803fc7904bda7decc2a0a68153f587ad82941fec1"}, 900 | {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05a0f648eb28bae4bcb204e6fd14603de2908de982e761a2fc78efe0f19e96e1"}, 901 | {file = "numpy-1.21.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f01f28075a92eede918b965e86e8f0ba7b7797a95aa8d35e1cc8821f5fc3ad6a"}, 902 | {file = "numpy-1.21.1-cp39-cp39-win32.whl", hash = "sha256:88c0b89ad1cc24a5efbb99ff9ab5db0f9a86e9cc50240177a571fbe9c2860ac2"}, 903 | {file = "numpy-1.21.1-cp39-cp39-win_amd64.whl", hash = "sha256:01721eefe70544d548425a07c80be8377096a54118070b8a62476866d5208e33"}, 904 | {file = "numpy-1.21.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2d4d1de6e6fb3d28781c73fbde702ac97f03d79e4ffd6598b880b2d95d62ead4"}, 905 | {file = "numpy-1.21.1.zip", hash = "sha256:dff4af63638afcc57a3dfb9e4b26d434a7a602d225b42d746ea7fe2edf1342fd"}, 906 | {file = "numpy-1.21.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:508b0b513fa1266875524ba8a9ecc27b02ad771fe1704a16314dc1a816a68737"}, 907 | {file = "numpy-1.21.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5dfe9d6a4c39b8b6edd7990091fea4f852888e41919d0e6722fe78dd421db0eb"}, 908 | {file = "numpy-1.21.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a10968963640e75cc0193e1847616ab4c718e83b6938ae74dea44953950f6b7"}, 909 | {file = "numpy-1.21.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c6249260890e05b8111ebfc391ed58b3cb4b33e63197b2ec7f776e45330721"}, 910 | {file = "numpy-1.21.3-cp310-cp310-win_amd64.whl", hash = "sha256:f8f4625536926a155b80ad2bbff44f8cc59e9f2ad14cdda7acf4c135b4dc8ff2"}, 911 | {file = "numpy-1.21.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e54af82d68ef8255535a6cdb353f55d6b8cf418a83e2be3569243787a4f4866f"}, 912 | {file = "numpy-1.21.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f41b018f126aac18583956c54544db437f25c7ee4794bcb23eb38bef8e5e192a"}, 913 | {file = "numpy-1.21.3-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:50cd26b0cf6664cb3b3dd161ba0a09c9c1343db064e7c69f9f8b551f5104d654"}, 914 | {file = "numpy-1.21.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cc9b512e9fb590797474f58b7f6d1f1b654b3a94f4fa8558b48ca8b3cfc97cf"}, 915 | {file = "numpy-1.21.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:88a5d6b268e9ad18f3533e184744acdaa2e913b13148160b1152300c949bbb5f"}, 916 | {file = "numpy-1.21.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3c09418a14471c7ae69ba682e2428cae5b4420a766659605566c0fa6987f6b7e"}, 917 | {file = "numpy-1.21.3-cp37-cp37m-win32.whl", hash = "sha256:90bec6a86b348b4559b6482e2b684db4a9a7eed1fa054b86115a48d58fbbf62a"}, 918 | {file = "numpy-1.21.3-cp37-cp37m-win_amd64.whl", hash = "sha256:043e83bfc274649c82a6f09836943e4a4aebe5e33656271c7dbf9621dd58b8ec"}, 919 | {file = "numpy-1.21.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:75621882d2230ab77fb6a03d4cbccd2038511491076e7964ef87306623aa5272"}, 920 | {file = "numpy-1.21.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:188031f833bbb623637e66006cf75e933e00e7231f67e2b45cf8189612bb5dc3"}, 921 | {file = "numpy-1.21.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:160ccc1bed3a8371bf0d760971f09bfe80a3e18646620e9ded0ad159d9749baa"}, 922 | {file = "numpy-1.21.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:29fb3dcd0468b7715f8ce2c0c2d9bbbaf5ae686334951343a41bd8d155c6ea27"}, 923 | {file = "numpy-1.21.3-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:32437f0b275c1d09d9c3add782516413e98cd7c09e6baf4715cbce781fc29912"}, 924 | {file = "numpy-1.21.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e606e6316911471c8d9b4618e082635cfe98876007556e89ce03d52ff5e8fcf0"}, 925 | {file = "numpy-1.21.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a99a6b067e5190ac6d12005a4d85aa6227c5606fa93211f86b1dafb16233e57d"}, 926 | {file = "numpy-1.21.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:dde972a1e11bb7b702ed0e447953e7617723760f420decb97305e66fb4afc54f"}, 927 | {file = "numpy-1.21.3-cp38-cp38-win32.whl", hash = "sha256:fe52dbe47d9deb69b05084abd4b0df7abb39a3c51957c09f635520abd49b29dd"}, 928 | {file = "numpy-1.21.3-cp38-cp38-win_amd64.whl", hash = "sha256:75eb7cadc8da49302f5b659d40ba4f6d94d5045fbd9569c9d058e77b0514c9e4"}, 929 | {file = "numpy-1.21.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2a6ee9620061b2a722749b391c0d80a0e2ae97290f1b32e28d5a362e21941ee4"}, 930 | {file = "numpy-1.21.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c4193f70f8069550a1788bd0cd3268ab7d3a2b70583dfe3b2e7f421e9aace06"}, 931 | {file = "numpy-1.21.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28f15209fb535dd4c504a7762d3bc440779b0e37d50ed810ced209e5cea60d96"}, 932 | {file = "numpy-1.21.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c6c2d535a7beb1f8790aaa98fd089ceab2e3dd7ca48aca0af7dc60e6ef93ffe1"}, 933 | {file = "numpy-1.21.3-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bffa2eee3b87376cc6b31eee36d05349571c236d1de1175b804b348dc0941e3f"}, 934 | {file = "numpy-1.21.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc14e7519fab2a4ed87d31f99c31a3796e4e1fe63a86ebdd1c5a1ea78ebd5896"}, 935 | {file = "numpy-1.21.3-cp39-cp39-win32.whl", hash = "sha256:dd0482f3fc547f1b1b5d6a8b8e08f63fdc250c58ce688dedd8851e6e26cff0f3"}, 936 | {file = "numpy-1.21.3-cp39-cp39-win_amd64.whl", hash = "sha256:300321e3985c968e3ae7fbda187237b225f3ffe6528395a5b7a5407f73cf093e"}, 937 | {file = "numpy-1.21.3-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98339aa9911853f131de11010f6dd94c8cec254d3d1f7261528c3b3e3219f139"}, 938 | {file = "numpy-1.21.3.zip", hash = "sha256:63571bb7897a584ca3249c86dd01c10bcb5fe4296e3568b2e9c1a55356b6410e"}, 939 | ] 940 | packaging = [ 941 | {file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"}, 942 | {file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"}, 943 | ] 944 | pandas = [ 945 | {file = "pandas-1.3.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:372d72a3d8a5f2dbaf566a5fa5fa7f230842ac80f29a931fb4b071502cf86b9a"}, 946 | {file = "pandas-1.3.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d99d2350adb7b6c3f7f8f0e5dfb7d34ff8dd4bc0a53e62c445b7e43e163fce63"}, 947 | {file = "pandas-1.3.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c2646458e1dce44df9f71a01dc65f7e8fa4307f29e5c0f2f92c97f47a5bf22f5"}, 948 | {file = "pandas-1.3.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5298a733e5bfbb761181fd4672c36d0c627320eb999c59c65156c6a90c7e1b4f"}, 949 | {file = "pandas-1.3.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22808afb8f96e2269dcc5b846decacb2f526dd0b47baebc63d913bf847317c8f"}, 950 | {file = "pandas-1.3.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b528e126c13816a4374e56b7b18bfe91f7a7f6576d1aadba5dee6a87a7f479ae"}, 951 | {file = "pandas-1.3.4-cp37-cp37m-win32.whl", hash = "sha256:fe48e4925455c964db914b958f6e7032d285848b7538a5e1b19aeb26ffaea3ec"}, 952 | {file = "pandas-1.3.4-cp37-cp37m-win_amd64.whl", hash = "sha256:eaca36a80acaacb8183930e2e5ad7f71539a66805d6204ea88736570b2876a7b"}, 953 | {file = "pandas-1.3.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:42493f8ae67918bf129869abea8204df899902287a7f5eaf596c8e54e0ac7ff4"}, 954 | {file = "pandas-1.3.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a388960f979665b447f0847626e40f99af8cf191bce9dc571d716433130cb3a7"}, 955 | {file = "pandas-1.3.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba0aac1397e1d7b654fccf263a4798a9e84ef749866060d19e577e927d66e1b"}, 956 | {file = "pandas-1.3.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f567e972dce3bbc3a8076e0b675273b4a9e8576ac629149cf8286ee13c259ae5"}, 957 | {file = "pandas-1.3.4-cp38-cp38-win32.whl", hash = "sha256:c1aa4de4919358c5ef119f6377bc5964b3a7023c23e845d9db7d9016fa0c5b1c"}, 958 | {file = "pandas-1.3.4-cp38-cp38-win_amd64.whl", hash = "sha256:dd324f8ee05925ee85de0ea3f0d66e1362e8c80799eb4eb04927d32335a3e44a"}, 959 | {file = "pandas-1.3.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d47750cf07dee6b55d8423471be70d627314277976ff2edd1381f02d52dbadf9"}, 960 | {file = "pandas-1.3.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d1dc09c0013d8faa7474574d61b575f9af6257ab95c93dcf33a14fd8d2c1bab"}, 961 | {file = "pandas-1.3.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10e10a2527db79af6e830c3d5842a4d60383b162885270f8cffc15abca4ba4a9"}, 962 | {file = "pandas-1.3.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35c77609acd2e4d517da41bae0c11c70d31c87aae8dd1aabd2670906c6d2c143"}, 963 | {file = "pandas-1.3.4-cp39-cp39-win32.whl", hash = "sha256:003ba92db58b71a5f8add604a17a059f3068ef4e8c0c365b088468d0d64935fd"}, 964 | {file = "pandas-1.3.4-cp39-cp39-win_amd64.whl", hash = "sha256:a51528192755f7429c5bcc9e80832c517340317c861318fea9cea081b57c9afd"}, 965 | {file = "pandas-1.3.4.tar.gz", hash = "sha256:a2aa18d3f0b7d538e21932f637fbfe8518d085238b429e4790a35e1e44a96ffc"}, 966 | ] 967 | pkginfo = [ 968 | {file = "pkginfo-1.7.1-py2.py3-none-any.whl", hash = "sha256:37ecd857b47e5f55949c41ed061eb51a0bee97a87c969219d144c0e023982779"}, 969 | {file = "pkginfo-1.7.1.tar.gz", hash = "sha256:e7432f81d08adec7297633191bbf0bd47faf13cd8724c3a13250e51d542635bd"}, 970 | ] 971 | pluggy = [ 972 | {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, 973 | {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, 974 | ] 975 | py = [ 976 | {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, 977 | {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, 978 | ] 979 | pycodestyle = [ 980 | {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, 981 | {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, 982 | ] 983 | pycparser = [ 984 | {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, 985 | {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, 986 | ] 987 | pyflakes = [ 988 | {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, 989 | {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, 990 | ] 991 | pygments = [ 992 | {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, 993 | {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, 994 | ] 995 | pyparsing = [ 996 | {file = "pyparsing-3.0.1-py3-none-any.whl", hash = "sha256:fd93fc45c47893c300bd98f5dd1b41c0e783eaeb727e7cea210dcc09d64ce7c3"}, 997 | {file = "pyparsing-3.0.1.tar.gz", hash = "sha256:84196357aa3566d64ad123d7a3c67b0e597a115c4934b097580e5ce220b91531"}, 998 | ] 999 | pytest = [ 1000 | {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, 1001 | {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, 1002 | ] 1003 | pytest-cov = [ 1004 | {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, 1005 | {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, 1006 | ] 1007 | python-dateutil = [ 1008 | {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, 1009 | {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, 1010 | ] 1011 | pytz = [ 1012 | {file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"}, 1013 | {file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"}, 1014 | ] 1015 | pywin32-ctypes = [ 1016 | {file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"}, 1017 | {file = "pywin32_ctypes-0.2.0-py2.py3-none-any.whl", hash = "sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"}, 1018 | ] 1019 | readme-renderer = [ 1020 | {file = "readme_renderer-30.0-py2.py3-none-any.whl", hash = "sha256:3286806450d9961d6e3b5f8a59f77e61503799aca5155c8d8d40359b4e1e1adc"}, 1021 | {file = "readme_renderer-30.0.tar.gz", hash = "sha256:8299700d7a910c304072a7601eafada6712a5b011a20139417e1b1e9f04645d8"}, 1022 | ] 1023 | requests = [ 1024 | {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"}, 1025 | {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"}, 1026 | ] 1027 | requests-toolbelt = [ 1028 | {file = "requests-toolbelt-0.9.1.tar.gz", hash = "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"}, 1029 | {file = "requests_toolbelt-0.9.1-py2.py3-none-any.whl", hash = "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f"}, 1030 | ] 1031 | rfc3986 = [ 1032 | {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, 1033 | {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, 1034 | ] 1035 | secretstorage = [ 1036 | {file = "SecretStorage-3.3.1-py3-none-any.whl", hash = "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f"}, 1037 | {file = "SecretStorage-3.3.1.tar.gz", hash = "sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195"}, 1038 | ] 1039 | six = [ 1040 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 1041 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 1042 | ] 1043 | toml = [ 1044 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, 1045 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, 1046 | ] 1047 | tomli = [ 1048 | {file = "tomli-1.2.2-py3-none-any.whl", hash = "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade"}, 1049 | {file = "tomli-1.2.2.tar.gz", hash = "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee"}, 1050 | ] 1051 | towncrier = [ 1052 | {file = "towncrier-21.3.0-py2.py3-none-any.whl", hash = "sha256:e6ccec65418bbcb8de5c908003e130e37fe0e9d6396cb77c1338241071edc082"}, 1053 | {file = "towncrier-21.3.0.tar.gz", hash = "sha256:6eed0bc924d72c98c000cb8a64de3bd566e5cb0d11032b73fcccf8a8f956ddfe"}, 1054 | ] 1055 | tqdm = [ 1056 | {file = "tqdm-4.62.3-py2.py3-none-any.whl", hash = "sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c"}, 1057 | {file = "tqdm-4.62.3.tar.gz", hash = "sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"}, 1058 | ] 1059 | twine = [ 1060 | {file = "twine-3.4.2-py3-none-any.whl", hash = "sha256:087328e9bb405e7ce18527a2dca4042a84c7918658f951110b38bc135acab218"}, 1061 | {file = "twine-3.4.2.tar.gz", hash = "sha256:4caec0f1ed78dc4c9b83ad537e453d03ce485725f2aea57f1bb3fdde78dae936"}, 1062 | ] 1063 | urllib3 = [ 1064 | {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"}, 1065 | {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"}, 1066 | ] 1067 | webencodings = [ 1068 | {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, 1069 | {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, 1070 | ] 1071 | zipp = [ 1072 | {file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"}, 1073 | {file = "zipp-3.6.0.tar.gz", hash = "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832"}, 1074 | ] 1075 | --------------------------------------------------------------------------------