├── .github └── workflows │ └── publish.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── async_iamport ├── __init__.py └── client.py ├── poetry.lock ├── pyproject.toml └── tests ├── __init__.py ├── conftest.py ├── test_cancel.py ├── test_certification.py ├── test_client.py ├── test_customer_create.py ├── test_customer_get.py ├── test_find.py ├── test_find_with_status.py ├── test_is_paid.py ├── test_pay_again.py ├── test_pay_foreign.py ├── test_pay_onetime.py ├── test_pay_schedule.py ├── test_pay_unschedule.py ├── test_prepare.py └── test_token_reuse.py /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | 4 | on: 5 | release: 6 | types: [published] 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | publish: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Dump GitHub context 16 | env: 17 | GITHUB_CONTEXT: ${{ toJson(github) }} 18 | run: echo "$GITHUB_CONTEXT" 19 | 20 | - uses: actions/checkout@v3 21 | 22 | - name: Set up Python 23 | uses: actions/setup-python@v4 24 | with: 25 | python-version: '3.7' 26 | 27 | - uses: actions/cache@v3 28 | id: cache 29 | with: 30 | path: ${{ env.pythonLocation }} 31 | key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-publish 32 | 33 | - name: Install poetry 34 | if: steps.cache.outputs.cache-hit != 'true' 35 | run: pip install poetry 36 | 37 | - name: Install Dependencies 38 | if: steps.cache.outputs.cache-hit != 'true' 39 | run: poetry install 40 | 41 | - name: Publish 42 | env: 43 | POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }} 44 | run: poetry publish --build 45 | 46 | - name: Dump GitHub context 47 | env: 48 | GITHUB_CONTEXT: ${{ toJson(github) }} 49 | run: echo "$GITHUB_CONTEXT" 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/python,macos,pycharm+all 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=python,macos,pycharm+all 3 | 4 | ### macOS ### 5 | # General 6 | .DS_Store 7 | .AppleDouble 8 | .LSOverride 9 | 10 | # Icon must end with two \r 11 | Icon 12 | 13 | 14 | # Thumbnails 15 | ._* 16 | 17 | # Files that might appear in the root of a volume 18 | .DocumentRevisions-V100 19 | .fseventsd 20 | .Spotlight-V100 21 | .TemporaryItems 22 | .Trashes 23 | .VolumeIcon.icns 24 | .com.apple.timemachine.donotpresent 25 | 26 | # Directories potentially created on remote AFP share 27 | .AppleDB 28 | .AppleDesktop 29 | Network Trash Folder 30 | Temporary Items 31 | .apdisk 32 | 33 | ### macOS Patch ### 34 | # iCloud generated files 35 | *.icloud 36 | 37 | ### PyCharm+all ### 38 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 39 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 40 | 41 | # User-specific stuff 42 | .idea/**/workspace.xml 43 | .idea/**/tasks.xml 44 | .idea/**/usage.statistics.xml 45 | .idea/**/dictionaries 46 | .idea/**/shelf 47 | 48 | # AWS User-specific 49 | .idea/**/aws.xml 50 | 51 | # Generated files 52 | .idea/**/contentModel.xml 53 | 54 | # Sensitive or high-churn files 55 | .idea/**/dataSources/ 56 | .idea/**/dataSources.ids 57 | .idea/**/dataSources.local.xml 58 | .idea/**/sqlDataSources.xml 59 | .idea/**/dynamic.xml 60 | .idea/**/uiDesigner.xml 61 | .idea/**/dbnavigator.xml 62 | 63 | # Gradle 64 | .idea/**/gradle.xml 65 | .idea/**/libraries 66 | 67 | # Gradle and Maven with auto-import 68 | # When using Gradle or Maven with auto-import, you should exclude module files, 69 | # since they will be recreated, and may cause churn. Uncomment if using 70 | # auto-import. 71 | # .idea/artifacts 72 | # .idea/compiler.xml 73 | # .idea/jarRepositories.xml 74 | # .idea/modules.xml 75 | # .idea/*.iml 76 | # .idea/modules 77 | # *.iml 78 | # *.ipr 79 | 80 | # CMake 81 | cmake-build-*/ 82 | 83 | # Mongo Explorer plugin 84 | .idea/**/mongoSettings.xml 85 | 86 | # File-based project format 87 | *.iws 88 | 89 | # IntelliJ 90 | out/ 91 | 92 | # mpeltonen/sbt-idea plugin 93 | .idea_modules/ 94 | 95 | # JIRA plugin 96 | atlassian-ide-plugin.xml 97 | 98 | # Cursive Clojure plugin 99 | .idea/replstate.xml 100 | 101 | # SonarLint plugin 102 | .idea/sonarlint/ 103 | 104 | # Crashlytics plugin (for Android Studio and IntelliJ) 105 | com_crashlytics_export_strings.xml 106 | crashlytics.properties 107 | crashlytics-build.properties 108 | fabric.properties 109 | 110 | # Editor-based Rest Client 111 | .idea/httpRequests 112 | 113 | # Android studio 3.1+ serialized cache file 114 | .idea/caches/build_file_checksums.ser 115 | 116 | ### PyCharm+all Patch ### 117 | # Ignore everything but code style settings and run configurations 118 | # that are supposed to be shared within teams. 119 | 120 | .idea/* 121 | 122 | !.idea/codeStyles 123 | !.idea/runConfigurations 124 | 125 | ### Python ### 126 | # Byte-compiled / optimized / DLL files 127 | __pycache__/ 128 | *.py[cod] 129 | *$py.class 130 | 131 | # C extensions 132 | *.so 133 | 134 | # Distribution / packaging 135 | .Python 136 | build/ 137 | develop-eggs/ 138 | dist/ 139 | downloads/ 140 | eggs/ 141 | .eggs/ 142 | lib/ 143 | lib64/ 144 | parts/ 145 | sdist/ 146 | var/ 147 | wheels/ 148 | share/python-wheels/ 149 | *.egg-info/ 150 | .installed.cfg 151 | *.egg 152 | MANIFEST 153 | 154 | # PyInstaller 155 | # Usually these files are written by a python script from a template 156 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 157 | *.manifest 158 | *.spec 159 | 160 | # Installer logs 161 | pip-log.txt 162 | pip-delete-this-directory.txt 163 | 164 | # Unit test / coverage reports 165 | htmlcov/ 166 | .tox/ 167 | .nox/ 168 | .coverage 169 | .coverage.* 170 | .cache 171 | nosetests.xml 172 | coverage.xml 173 | *.cover 174 | *.py,cover 175 | .hypothesis/ 176 | .pytest_cache/ 177 | cover/ 178 | 179 | # Translations 180 | *.mo 181 | *.pot 182 | 183 | # Django stuff: 184 | *.log 185 | local_settings.py 186 | db.sqlite3 187 | db.sqlite3-journal 188 | 189 | # Flask stuff: 190 | instance/ 191 | .webassets-cache 192 | 193 | # Scrapy stuff: 194 | .scrapy 195 | 196 | # Sphinx documentation 197 | docs/_build/ 198 | 199 | # PyBuilder 200 | .pybuilder/ 201 | target/ 202 | 203 | # Jupyter Notebook 204 | .ipynb_checkpoints 205 | 206 | # IPython 207 | profile_default/ 208 | ipython_config.py 209 | 210 | # pyenv 211 | # For a library or package, you might want to ignore these files since the code is 212 | # intended to run in multiple environments; otherwise, check them in: 213 | # .python-version 214 | 215 | # pipenv 216 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 217 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 218 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 219 | # install all needed dependencies. 220 | #Pipfile.lock 221 | 222 | # poetry 223 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 224 | # This is especially recommended for binary packages to ensure reproducibility, and is more 225 | # commonly ignored for libraries. 226 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 227 | #poetry.lock 228 | 229 | # pdm 230 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 231 | #pdm.lock 232 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 233 | # in version control. 234 | # https://pdm.fming.dev/#use-with-ide 235 | .pdm.toml 236 | 237 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 238 | __pypackages__/ 239 | 240 | # Celery stuff 241 | celerybeat-schedule 242 | celerybeat.pid 243 | 244 | # SageMath parsed files 245 | *.sage.py 246 | 247 | # Environments 248 | .env 249 | .venv 250 | env/ 251 | venv/ 252 | ENV/ 253 | env.bak/ 254 | venv.bak/ 255 | 256 | # Spyder project settings 257 | .spyderproject 258 | .spyproject 259 | 260 | # Rope project settings 261 | .ropeproject 262 | 263 | # mkdocs documentation 264 | /site 265 | 266 | # mypy 267 | .mypy_cache/ 268 | .dmypy.json 269 | dmypy.json 270 | 271 | # Pyre type checker 272 | .pyre/ 273 | 274 | # pytype static type analyzer 275 | .pytype/ 276 | 277 | # Cython debug symbols 278 | cython_debug/ 279 | 280 | # PyCharm 281 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 282 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 283 | # and can be added to the global gitignore or merged into this file. For a more nuclear 284 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 285 | #.idea/ 286 | 287 | ### Python Patch ### 288 | # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration 289 | poetry.toml 290 | 291 | 292 | # End of https://www.toptal.com/developers/gitignore/api/python,macos,pycharm+all 293 | .python-version 294 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v0.2.0 (2023-01-28) 2 | 3 | ### Feat 4 | 5 | - **/payments/prepare**: PUT mehtod: adjust_prepare_amount 6 | - instance method: _put for PUT request 7 | - otp certification method 8 | 9 | ### Refactor 10 | 11 | - **func-pay_schedule_get**: change parameter name merchant_id -> merchant_uid 12 | - **/subscribe/payments/**: delete key validation 13 | - **/subscribe/**: add type annotations and docstring 14 | - **/payments/**: add type annotation and docstring 15 | - **/payments/status/**: add docstring 16 | - **/payments/prepare**: add type annotation and docstring 17 | - add type annotation and docs on function related /certification 18 | - delete empty workflow.yml 19 | 20 | ## v0.1.1 (2023-01-18) 21 | 22 | ### Fix 23 | 24 | - **client.py**: fix TOKEN_REFRESH_GAP 120 -> 60 25 | 26 | ### Refactor 27 | 28 | - _get_user code block 29 | - formatting using mypy 30 | - formatting using isort 31 | 32 | ## v0.1.0 (2023-01-14) 33 | 34 | ### Feat 35 | 36 | - sync rest client -> async rest client 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 rumbarum and other contributors. 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IAMPORT async python rest client 2 | 3 | from https://github.com/iamport/iamport-rest-client-python 4 | 5 | ## 개선 사항 6 | 1. sync -> async 7 | 2. Token 재사용 8 | - 만료 60s 이상 남았을 경우 재사용 9 | - 그 이하일 경우 재인증 10 | 3. .format() -> f-string 11 | 4. typing 적용, mypy 적용 12 | 13 | 14 | ## 변경 사항 15 | 1. python2 지원 안함 16 | 2. requests -> aiohttp 17 | 3. 기존 retry(3회) 옵션 제거 18 | 19 | ## 작업 예정 20 | 1. 필수 필드 검증을 아에 제거하고 iamport api 의 응답만 확인하도록 해서 필드 변경에 대한 유연성 및 코드의 책임 범위를 낮추기 21 | - 기존 method 호환을 위해 유지 22 | - 추가 API는 path parameter 만 positional args 으로 처리, 나머지는 kwargs로 payload 담음 23 | 2. ~~함수들의 이름을 iamport api들의 호출 이름과 유사하게 전부 정리하기~~ 24 | - 기존 client api 유지 25 | 3. 미구현 API 추가 예정 26 | - param validation 제거 27 | - type annotation 추가 28 | - docstring 추가 29 | 30 | ## 주의 사항 31 | - 사용 중 발생한 문제의 책임은 사용자에게 있습니다. 32 | - iamport 정식 api로 동작 완전성 테스트 되지 않았습니다. url 이상 여부만 검증 되었습니다. 33 | 34 | 35 | ## Deps 36 | 37 | - python >= 3.7 38 | 39 | - Aiohttp >= 3.8.3 40 | - arrow >= 1.2.3 41 | 42 | 43 | ## Install 44 | 45 | ```commandline 46 | pip install async-iamport 47 | ``` 48 | 49 | ## FastAPI Example 50 | 51 | ```python 52 | from fastapi import FastAPI 53 | 54 | from async_iamport import AsyncIamport 55 | 56 | DEFAULT_TEST_IMP_KEY = "imp_apikey" 57 | DEFAULT_TEST_IMP_SECRET = ( 58 | "ekKoeW8RyKuT0zgaZsUtXXTLQ4AhPFW3ZGseDA6b" 59 | "kA5lamv9OqDMnxyeB9wqOsuO9W3Mx9YSJ4dTqJ3f" 60 | ) 61 | 62 | async_iamport = AsyncIamport( 63 | imp_key=DEFAULT_TEST_IMP_KEY, imp_secret=DEFAULT_TEST_IMP_SECRET 64 | ) 65 | 66 | app = FastAPI(on_shutdown=[async_iamport.close_session]) 67 | 68 | 69 | mocked_response = { 70 | "status": "paid", 71 | "amount": 1000, 72 | } 73 | 74 | @app.get("/") 75 | async def root(): 76 | return await async_iamport.find_by_merchant_uid(merchant_uid="1234qwer") 77 | ``` 78 | ```commandline 79 | uvicorn main:app --reload 80 | ``` 81 | -------------------------------------------------------------------------------- /async_iamport/__init__.py: -------------------------------------------------------------------------------- 1 | from .client import AsyncIamport, HttpError, ResponseError 2 | 3 | __all__ = ["AsyncIamport", "HttpError", "ResponseError"] 4 | -------------------------------------------------------------------------------- /async_iamport/client.py: -------------------------------------------------------------------------------- 1 | import json 2 | from http import HTTPStatus 3 | from socket import AF_INET 4 | from typing import Any, Dict, Optional 5 | 6 | import aiohttp 7 | import arrow 8 | 9 | IAMPORT_API_URL = "https://api.iamport.kr" 10 | TOKEN_REFRESH_GAP = 60 # token 만료 1500s 정도 11 | DEFAULT_TIMEOUT = 5 12 | DEFAULT_POOL_SIZE = 100 13 | 14 | 15 | class ResponseError(Exception): 16 | def __init__(self, code: int, message: str) -> None: 17 | self.code = code 18 | self.message = message 19 | 20 | 21 | class HttpError(Exception): 22 | def __init__(self, code: int, reason: str) -> None: 23 | self.code = code 24 | self.reason = reason 25 | 26 | 27 | class AsyncIamport: 28 | """ 29 | sync Iamport -> async Iamport 30 | """ 31 | 32 | def __init__( 33 | self, 34 | *, 35 | imp_key: Optional[str] = None, 36 | imp_secret: Optional[str] = None, 37 | imp_url: str = IAMPORT_API_URL, 38 | pool_size: int = DEFAULT_POOL_SIZE, 39 | time_out: int = DEFAULT_TIMEOUT, 40 | token_refresh_gap: int = TOKEN_REFRESH_GAP, 41 | ) -> None: 42 | if imp_key is None or imp_secret is None: 43 | raise ValueError("IMP_KEY OR IMP_SECRET MISSED") 44 | self.imp_key = imp_key 45 | self.imp_secret = imp_secret 46 | self.imp_url = imp_url 47 | self.pool_size = pool_size 48 | self.time_out = time_out 49 | self.token_refresh_gap = token_refresh_gap 50 | self.token: Optional[str] = None 51 | self.token_expire: Optional[arrow.Arrow] = None 52 | self.session: Optional[aiohttp.ClientSession] = None 53 | 54 | self._init_session() 55 | 56 | def _init_session(self) -> None: 57 | if self.session is None: 58 | timeout = aiohttp.ClientTimeout(total=self.time_out) 59 | connector = aiohttp.TCPConnector( 60 | family=AF_INET, limit_per_host=self.pool_size 61 | ) 62 | self.session = aiohttp.ClientSession( 63 | base_url=self.imp_url, timeout=timeout, connector=connector 64 | ) 65 | 66 | async def close_session(self) -> None: 67 | if self.session: 68 | await self.session.close() 69 | self.session = None 70 | 71 | async def _get(self, url, payload=None) -> Dict: 72 | headers = await self._get_auth_headers() 73 | if self.session is not None: 74 | response = await self.session.get(url, headers=headers, params=payload) 75 | return await self.get_response(response) 76 | else: 77 | raise ConnectionError("SESSION IS CLOSED") 78 | 79 | async def _post(self, url, payload=None) -> Dict: 80 | headers = await self._get_auth_headers() 81 | headers["Content-Type"] = "application/json" 82 | if self.session is not None: 83 | response = await self.session.post( 84 | url, headers=headers, data=json.dumps(payload) 85 | ) 86 | return await self.get_response(response) 87 | else: 88 | raise ConnectionError("SESSION IS CLOSED") 89 | 90 | async def _put(self, url, payload=None) -> Dict[str, Any]: 91 | headers = await self._get_auth_headers() 92 | headers["Content-Type"] = "application/json" 93 | if self.session is not None: 94 | response = await self.session.put( 95 | url, headers=headers, data=json.dumps(payload) 96 | ) 97 | return await self.get_response(response) 98 | else: 99 | raise ConnectionError("SESSION IS CLOSED") 100 | 101 | async def _delete(self, url) -> Dict: 102 | headers = await self._get_auth_headers() 103 | if self.session is not None: 104 | response = await self.session.delete(url, headers=headers) 105 | return await self.get_response(response) 106 | else: 107 | raise ConnectionError("SESSION IS CLOSED") 108 | 109 | @staticmethod 110 | async def get_response(response) -> Dict: 111 | if response.status != HTTPStatus.OK: 112 | raise HttpError(response.status, response.reason) 113 | result = await response.json() 114 | if result["code"] != 0: 115 | raise ResponseError(result.get("code"), result.get("message")) 116 | return result.get("response") 117 | 118 | async def _get_auth_headers(self) -> Dict: 119 | return {"Authorization": await self._get_token()} 120 | 121 | async def _get_token(self) -> Optional[str]: 122 | if ( 123 | self.token is not None 124 | and self.token_expire is not None 125 | and (self.token_expire - arrow.utcnow()).seconds > self.token_refresh_gap 126 | ): 127 | return self.token 128 | else: 129 | self.token = None 130 | url = "/users/getToken" 131 | payload = {"imp_key": self.imp_key, "imp_secret": self.imp_secret} 132 | if self.session is not None: 133 | response = await self.session.post( 134 | url, 135 | headers={"Content-Type": "application/json"}, 136 | data=json.dumps(payload), 137 | ) 138 | else: 139 | raise ConnectionError("SESSION IS CLOSED") 140 | resp = await self.get_response(response) 141 | timestamp: Optional[int] = resp.get("expired_at") 142 | if timestamp is not None: 143 | self.token_expire = arrow.Arrow.utcfromtimestamp(timestamp) 144 | self.token = resp.get("access_token") 145 | return self.token 146 | 147 | async def find_by_status(self, status: str, **params) -> Dict: 148 | """ 149 | query payment history by status 150 | 151 | GET 'IAMPORT_API_URL/payments/status/{status}' 152 | 153 | :param status: ["all", "ready", "paid", "cancelled", "failed"] 154 | :param params: kwargs 155 | :return: result 156 | """ 157 | 158 | url = f"/payments/status/{status}" 159 | return await self._get(url, payload=params) 160 | 161 | async def find_by_merchant_uid( 162 | self, merchant_uid: str, status: Optional[str] = None 163 | ) -> Dict: 164 | """ 165 | query payment by merchant_uid and status(optional) 166 | 167 | GET 'IAMPORT_API_URL/payments/{merchant_uid}' 168 | or 169 | GET 'IAMPORT_API_URL/payments/{merchant_uid}/{status}' 170 | 171 | :param merchant_uid: merchant unique id 172 | :param status: ["ready", "paid", "cancelled", "failed"] 173 | :return: result 174 | """ 175 | url = f"/payments/find/{merchant_uid}" 176 | if status is not None: 177 | url = f"{url}/{status}" 178 | return await self._get(url) 179 | 180 | async def find_by_imp_uid(self, imp_uid: str) -> Dict: 181 | """ 182 | query payment by imp_uid 183 | 184 | GET 'IAMPORT_API_URL/payments/{imp_uid}' 185 | 186 | :param imp_uid: iamport unique id 187 | :return: result 188 | """ 189 | url = f"/payments/{imp_uid}" 190 | return await self._get(url) 191 | 192 | async def find(self, **kwargs) -> Dict: 193 | """ 194 | query payments by merchant_uid or imp_uid 195 | 196 | :param kwargs: kwargs 197 | :return: result 198 | """ 199 | merchant_uid = kwargs.get("merchant_uid") 200 | if merchant_uid: 201 | return await self.find_by_merchant_uid(merchant_uid) 202 | try: 203 | imp_uid = kwargs["imp_uid"] 204 | except KeyError: 205 | raise KeyError("merchant_uid or imp_uid is required") 206 | return await self.find_by_imp_uid(imp_uid) 207 | 208 | async def _cancel(self, payload: dict) -> Dict: 209 | """ 210 | cancel payment 211 | 212 | POST 'IAMPORT_API_URL/payments/cancel' 213 | 214 | :param payload: payload 215 | :return: result 216 | """ 217 | url = "/payments/cancel" 218 | return await self._post(url, payload) 219 | 220 | async def cancel_by_merchant_uid( 221 | self, merchant_uid: str, reason: str, **kwargs 222 | ) -> Dict: 223 | """ 224 | cancel payment by merchant_uid 225 | 226 | POST 'IAMPORT_API_URL/payments/cancel' 227 | 228 | :param merchant_uid: merchant unique id 229 | :param reason: reason for cancel 230 | :param kwargs: keyword arguments 231 | :return: result 232 | """ 233 | 234 | payload = {"merchant_uid": merchant_uid, "reason": reason} 235 | if kwargs: 236 | payload.update(kwargs) 237 | return await self._cancel(payload) 238 | 239 | async def cancel_by_imp_uid(self, imp_uid: str, reason: str, **kwargs) -> Dict: 240 | """ 241 | cancel payment by imp_uid 242 | 243 | POST 'IAMPORT_API_URL/payments/cancel' 244 | 245 | :param imp_uid: iamport unique id 246 | :param reason: reason for cancel 247 | :param kwargs: keyword arguments 248 | :return: 249 | """ 250 | payload = {"imp_uid": imp_uid, "reason": reason} 251 | if kwargs: 252 | payload.update(kwargs) 253 | return await self._cancel(payload) 254 | 255 | async def cancel(self, reason: str, **kwargs) -> Dict: 256 | """ 257 | cancel payment by merchant_uid or imp_uid 258 | 259 | POST 'IAMPORT_API_URL/payments/cancel' 260 | 261 | :param reason: reason for cancel 262 | :param kwargs: keyword arguments 263 | :return: result 264 | """ 265 | imp_uid = kwargs.pop("imp_uid", None) 266 | if imp_uid: 267 | return await self.cancel_by_imp_uid(imp_uid, reason, **kwargs) 268 | 269 | merchant_uid = kwargs.pop("merchant_uid", None) 270 | if merchant_uid is None: 271 | raise KeyError("merchant_uid or imp_uid is required") 272 | return await self.cancel_by_merchant_uid(merchant_uid, reason, **kwargs) 273 | 274 | async def is_paid(self, amount: float, **kwargs) -> bool: 275 | """ 276 | check that payment is paid 277 | 278 | :param amount: payment value 279 | :param kwargs: keyword arguments 280 | :return: 281 | """ 282 | response = kwargs.get("response") 283 | if not response: 284 | response = await self.find(**kwargs) 285 | status = response.get("status") 286 | response_amount = response.get("amount") 287 | return status == "paid" and response_amount == amount 288 | 289 | async def pay_onetime(self, **kwargs) -> Dict: 290 | """ 291 | payments once only with card information 292 | 293 | POST 'IAMPORT_API_URL/subscribe/payments/onetime' 294 | 295 | :param kwargs: keyword arguments 296 | :return: result 297 | """ 298 | url = "/subscribe/payments/onetime" 299 | 300 | return await self._post(url, kwargs) 301 | 302 | async def pay_again(self, **kwargs) -> Dict: 303 | """ 304 | payment again with saved billing key 305 | 306 | POST 'IAMPORT_API_URL/subscribe/payments/again' 307 | 308 | :param kwargs: keyword arguments 309 | :return: result 310 | """ 311 | url = "/subscribe/payments/again" 312 | 313 | return await self._post(url, kwargs) 314 | 315 | async def pay_foreign(self, **kwargs) -> Dict: 316 | """ 317 | depreciated 318 | 319 | :param kwargs: 320 | :return: 321 | """ 322 | url = "/subscribe/payments/foreign" 323 | 324 | return await self._post(url, kwargs) 325 | 326 | async def pay_schedule(self, **kwargs) -> Dict: 327 | """ 328 | register scheduled payment 329 | 330 | POST 'IAMPORT_API_URL/subscribe/payments/schedule' 331 | 332 | :param kwargs: keyword arguments 333 | :return: result 334 | """ 335 | 336 | headers = await self._get_auth_headers() 337 | headers["Content-Type"] = "application/json" 338 | url = "/subscribe/payments/schedule" 339 | 340 | return await self._post(url, kwargs) 341 | 342 | async def pay_schedule_get(self, merchant_uid: str) -> Dict: 343 | """ 344 | query scheduled payment by merchant_uid 345 | 346 | GET 'IAMPORT_API_URL/subscribe/payments/schedule/{merchant_uid} 347 | 348 | :param merchant_uid: merchant unique id 349 | :return: result 350 | """ 351 | url = f"/subscribe/payments/schedule/{merchant_uid}" 352 | return await self._get(url) 353 | 354 | async def pay_schedule_get_between(self, **kwargs) -> Dict: 355 | """ 356 | query scheduled payment by datetime range 357 | 358 | GET 'IAMPORT_API_URL/subscribe/payments/schedule' 359 | 360 | :param kwargs: keyword arguments 361 | :return: result 362 | """ 363 | url = f"/subscribe/payments/schedule" 364 | 365 | return await self._get(url, kwargs) 366 | 367 | async def pay_unschedule(self, **kwargs) -> Dict: 368 | """ 369 | cancel scheduled payment 370 | 371 | POST 'IAMPORT_API_URL/subscribe/payments/unschedule' 372 | 373 | :param kwargs: keyword arguments 374 | :return: result 375 | """ 376 | url = f"/subscribe/payments/unschedule" 377 | 378 | return await self._post(url, kwargs) 379 | 380 | async def customer_create(self, **kwargs) -> Dict: 381 | """ 382 | create customer billing key 383 | 384 | POST 'IAMPORT_API_URL/subscribe/customers/{customer_uid}' 385 | 386 | :param kwargs: keyword arguments 387 | :return: result 388 | """ 389 | customer_uid = kwargs.get("customer_uid") 390 | url = f"/subscribe/customers/{customer_uid}" 391 | 392 | return await self._post(url, kwargs) 393 | 394 | async def customer_get(self, customer_uid: str) -> Dict: 395 | """ 396 | query customer billing key 397 | 398 | GET 'IAMPORT_API_URL/subscribe/customers/{customer_uid}' 399 | 400 | :param customer_uid: customer's payment method unique id 401 | :return: result 402 | """ 403 | url = f"/subscribe/customers/{customer_uid}" 404 | return await self._get(url) 405 | 406 | async def customer_delete(self, customer_uid: str) -> Dict: 407 | """ 408 | delete customer billing key 409 | 410 | DELETE 'IAMPORT_API_URL/subscribe/customers/{customer_uid}' 411 | 412 | :param customer_uid: customer's payment method unique id 413 | :return: result 414 | """ 415 | url = f"/subscribe/customers/{customer_uid}" 416 | return await self._delete(url) 417 | 418 | async def prepare(self, merchant_uid: str, amount: float) -> Dict: 419 | """ 420 | register payment amount with uid in advance for safety 421 | '/payments/prepare' 422 | 423 | :param merchant_uid: merchant unique id 424 | :param amount: amount 425 | :return: result 426 | """ 427 | url = "/payments/prepare" 428 | payload = {"merchant_uid": merchant_uid, "amount": amount} 429 | return await self._post(url, payload) 430 | 431 | async def prepare_validate(self, merchant_uid: str, amount: float) -> bool: 432 | """ 433 | validate payment amount with uid on registered payment 434 | '/payments/prepare/{merchant_uid}' 435 | 436 | :param merchant_uid: merchant unique id 437 | :param amount: amount 438 | :return: result 439 | """ 440 | url = f"/payments/prepare/{merchant_uid}" 441 | response = await self._get(url) 442 | response_amount = response.get("amount") 443 | return response_amount == amount 444 | 445 | async def adjust_prepare_amount( 446 | self, merchant_uid: str, amount: float 447 | ) -> Dict[str, Any]: 448 | """ 449 | adjust amount of pre-registered payment 450 | 451 | PUT 'IAMPORT_API_URL/payments/prepare' 452 | 453 | :param merchant_uid: merchant unique id 454 | :param amount: amount 455 | :return: result 456 | """ 457 | url = f"/payments/prepare" 458 | payload = {"merchant_uid": merchant_uid, "amount": amount} 459 | return await self._put(url, payload=payload) 460 | 461 | async def revoke_vbank_by_imp_uid(self, imp_uid) -> Dict: 462 | url = f"/vbanks/{imp_uid}" 463 | return await self._delete(url) 464 | 465 | async def find_certification(self, imp_uid: str) -> Dict: 466 | """ 467 | query sms authentication result 468 | 469 | GET 'IAMPORT_API_URL/certifications/{imp_uid}' 470 | 471 | :param imp_uid: imp_uid 472 | :return: result 473 | """ 474 | url = f"/certifications/{imp_uid}" 475 | return await self._get(url) 476 | 477 | async def cancel_certification(self, imp_uid: str) -> Dict: 478 | """ 479 | delete sms authentication result 480 | 481 | DELETE 'IAMPORT_API_URL/certifications/{imp_uid}' 482 | 483 | :param imp_uid: imp_uid 484 | :return: result 485 | """ 486 | 487 | url = f"/certifications/{imp_uid}" 488 | return await self._delete(url) 489 | 490 | async def init_otp_certification(self, **kwargs) -> Dict: 491 | """ 492 | init otp authentication through sms with personal information 493 | 494 | POST 'IAMPORT_API_URL/certifications/otp/request' 495 | 496 | :return: result 497 | """ 498 | 499 | url = f"/certifications/otp/request" 500 | return await self._post(url, payload=kwargs) 501 | 502 | async def confirm_otp_certification(self, imp_uid: str, **kwargs) -> Dict: 503 | """ 504 | complete otp authentication through sms with personal information 505 | 506 | POST 'IAMPORT_API_URL/certifications/otp/confirm/{imp_uid}' 507 | 508 | :return: result 509 | """ 510 | 511 | url = f"/certifications/otp/confirm/{imp_uid}" 512 | return await self._post(url, payload=kwargs) 513 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "aiohttp" 5 | version = "3.8.3" 6 | description = "Async http client/server framework (asyncio)" 7 | category = "main" 8 | optional = false 9 | python-versions = ">=3.6" 10 | files = [ 11 | {file = "aiohttp-3.8.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ba71c9b4dcbb16212f334126cc3d8beb6af377f6703d9dc2d9fb3874fd667ee9"}, 12 | {file = "aiohttp-3.8.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d24b8bb40d5c61ef2d9b6a8f4528c2f17f1c5d2d31fed62ec860f6006142e83e"}, 13 | {file = "aiohttp-3.8.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f88df3a83cf9df566f171adba39d5bd52814ac0b94778d2448652fc77f9eb491"}, 14 | {file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97decbb3372d4b69e4d4c8117f44632551c692bb1361b356a02b97b69e18a62"}, 15 | {file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:309aa21c1d54b8ef0723181d430347d7452daaff93e8e2363db8e75c72c2fb2d"}, 16 | {file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad5383a67514e8e76906a06741febd9126fc7c7ff0f599d6fcce3e82b80d026f"}, 17 | {file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20acae4f268317bb975671e375493dbdbc67cddb5f6c71eebdb85b34444ac46b"}, 18 | {file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05a3c31c6d7cd08c149e50dc7aa2568317f5844acd745621983380597f027a18"}, 19 | {file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d6f76310355e9fae637c3162936e9504b4767d5c52ca268331e2756e54fd4ca5"}, 20 | {file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:256deb4b29fe5e47893fa32e1de2d73c3afe7407738bd3c63829874661d4822d"}, 21 | {file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:5c59fcd80b9049b49acd29bd3598cada4afc8d8d69bd4160cd613246912535d7"}, 22 | {file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:059a91e88f2c00fe40aed9031b3606c3f311414f86a90d696dd982e7aec48142"}, 23 | {file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2feebbb6074cdbd1ac276dbd737b40e890a1361b3cc30b74ac2f5e24aab41f7b"}, 24 | {file = "aiohttp-3.8.3-cp310-cp310-win32.whl", hash = "sha256:5bf651afd22d5f0c4be16cf39d0482ea494f5c88f03e75e5fef3a85177fecdeb"}, 25 | {file = "aiohttp-3.8.3-cp310-cp310-win_amd64.whl", hash = "sha256:653acc3880459f82a65e27bd6526e47ddf19e643457d36a2250b85b41a564715"}, 26 | {file = "aiohttp-3.8.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:86fc24e58ecb32aee09f864cb11bb91bc4c1086615001647dbfc4dc8c32f4008"}, 27 | {file = "aiohttp-3.8.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75e14eac916f024305db517e00a9252714fce0abcb10ad327fb6dcdc0d060f1d"}, 28 | {file = "aiohttp-3.8.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d1fde0f44029e02d02d3993ad55ce93ead9bb9b15c6b7ccd580f90bd7e3de476"}, 29 | {file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ab94426ddb1ecc6a0b601d832d5d9d421820989b8caa929114811369673235c"}, 30 | {file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89d2e02167fa95172c017732ed7725bc8523c598757f08d13c5acca308e1a061"}, 31 | {file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:02f9a2c72fc95d59b881cf38a4b2be9381b9527f9d328771e90f72ac76f31ad8"}, 32 | {file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c7149272fb5834fc186328e2c1fa01dda3e1fa940ce18fded6d412e8f2cf76d"}, 33 | {file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:512bd5ab136b8dc0ffe3fdf2dfb0c4b4f49c8577f6cae55dca862cd37a4564e2"}, 34 | {file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7018ecc5fe97027214556afbc7c502fbd718d0740e87eb1217b17efd05b3d276"}, 35 | {file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:88c70ed9da9963d5496d38320160e8eb7e5f1886f9290475a881db12f351ab5d"}, 36 | {file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:da22885266bbfb3f78218dc40205fed2671909fbd0720aedba39b4515c038091"}, 37 | {file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:e65bc19919c910127c06759a63747ebe14f386cda573d95bcc62b427ca1afc73"}, 38 | {file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:08c78317e950e0762c2983f4dd58dc5e6c9ff75c8a0efeae299d363d439c8e34"}, 39 | {file = "aiohttp-3.8.3-cp311-cp311-win32.whl", hash = "sha256:45d88b016c849d74ebc6f2b6e8bc17cabf26e7e40c0661ddd8fae4c00f015697"}, 40 | {file = "aiohttp-3.8.3-cp311-cp311-win_amd64.whl", hash = "sha256:96372fc29471646b9b106ee918c8eeb4cca423fcbf9a34daa1b93767a88a2290"}, 41 | {file = "aiohttp-3.8.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c971bf3786b5fad82ce5ad570dc6ee420f5b12527157929e830f51c55dc8af77"}, 42 | {file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff25f48fc8e623d95eca0670b8cc1469a83783c924a602e0fbd47363bb54aaca"}, 43 | {file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e381581b37db1db7597b62a2e6b8b57c3deec95d93b6d6407c5b61ddc98aca6d"}, 44 | {file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db19d60d846283ee275d0416e2a23493f4e6b6028825b51290ac05afc87a6f97"}, 45 | {file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25892c92bee6d9449ffac82c2fe257f3a6f297792cdb18ad784737d61e7a9a85"}, 46 | {file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:398701865e7a9565d49189f6c90868efaca21be65c725fc87fc305906be915da"}, 47 | {file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:4a4fbc769ea9b6bd97f4ad0b430a6807f92f0e5eb020f1e42ece59f3ecfc4585"}, 48 | {file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:b29bfd650ed8e148f9c515474a6ef0ba1090b7a8faeee26b74a8ff3b33617502"}, 49 | {file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:1e56b9cafcd6531bab5d9b2e890bb4937f4165109fe98e2b98ef0dcfcb06ee9d"}, 50 | {file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ec40170327d4a404b0d91855d41bfe1fe4b699222b2b93e3d833a27330a87a6d"}, 51 | {file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2df5f139233060578d8c2c975128fb231a89ca0a462b35d4b5fcf7c501ebdbe1"}, 52 | {file = "aiohttp-3.8.3-cp36-cp36m-win32.whl", hash = "sha256:f973157ffeab5459eefe7b97a804987876dd0a55570b8fa56b4e1954bf11329b"}, 53 | {file = "aiohttp-3.8.3-cp36-cp36m-win_amd64.whl", hash = "sha256:437399385f2abcd634865705bdc180c8314124b98299d54fe1d4c8990f2f9494"}, 54 | {file = "aiohttp-3.8.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:09e28f572b21642128ef31f4e8372adb6888846f32fecb288c8b0457597ba61a"}, 55 | {file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f3553510abdbec67c043ca85727396ceed1272eef029b050677046d3387be8d"}, 56 | {file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e168a7560b7c61342ae0412997b069753f27ac4862ec7867eff74f0fe4ea2ad9"}, 57 | {file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db4c979b0b3e0fa7e9e69ecd11b2b3174c6963cebadeecfb7ad24532ffcdd11a"}, 58 | {file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e164e0a98e92d06da343d17d4e9c4da4654f4a4588a20d6c73548a29f176abe2"}, 59 | {file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8a78079d9a39ca9ca99a8b0ac2fdc0c4d25fc80c8a8a82e5c8211509c523363"}, 60 | {file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:21b30885a63c3f4ff5b77a5d6caf008b037cb521a5f33eab445dc566f6d092cc"}, 61 | {file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4b0f30372cef3fdc262f33d06e7b411cd59058ce9174ef159ad938c4a34a89da"}, 62 | {file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:8135fa153a20d82ffb64f70a1b5c2738684afa197839b34cc3e3c72fa88d302c"}, 63 | {file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:ad61a9639792fd790523ba072c0555cd6be5a0baf03a49a5dd8cfcf20d56df48"}, 64 | {file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:978b046ca728073070e9abc074b6299ebf3501e8dee5e26efacb13cec2b2dea0"}, 65 | {file = "aiohttp-3.8.3-cp37-cp37m-win32.whl", hash = "sha256:0d2c6d8c6872df4a6ec37d2ede71eff62395b9e337b4e18efd2177de883a5033"}, 66 | {file = "aiohttp-3.8.3-cp37-cp37m-win_amd64.whl", hash = "sha256:21d69797eb951f155026651f7e9362877334508d39c2fc37bd04ff55b2007091"}, 67 | {file = "aiohttp-3.8.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ca9af5f8f5812d475c5259393f52d712f6d5f0d7fdad9acdb1107dd9e3cb7eb"}, 68 | {file = "aiohttp-3.8.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d90043c1882067f1bd26196d5d2db9aa6d268def3293ed5fb317e13c9413ea4"}, 69 | {file = "aiohttp-3.8.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d737fc67b9a970f3234754974531dc9afeea11c70791dcb7db53b0cf81b79784"}, 70 | {file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebf909ea0a3fc9596e40d55d8000702a85e27fd578ff41a5500f68f20fd32e6c"}, 71 | {file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5835f258ca9f7c455493a57ee707b76d2d9634d84d5d7f62e77be984ea80b849"}, 72 | {file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da37dcfbf4b7f45d80ee386a5f81122501ec75672f475da34784196690762f4b"}, 73 | {file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87f44875f2804bc0511a69ce44a9595d5944837a62caecc8490bbdb0e18b1342"}, 74 | {file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:527b3b87b24844ea7865284aabfab08eb0faf599b385b03c2aa91fc6edd6e4b6"}, 75 | {file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d5ba88df9aa5e2f806650fcbeedbe4f6e8736e92fc0e73b0400538fd25a4dd96"}, 76 | {file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e7b8813be97cab8cb52b1375f41f8e6804f6507fe4660152e8ca5c48f0436017"}, 77 | {file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:2dea10edfa1a54098703cb7acaa665c07b4e7568472a47f4e64e6319d3821ccf"}, 78 | {file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:713d22cd9643ba9025d33c4af43943c7a1eb8547729228de18d3e02e278472b6"}, 79 | {file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2d252771fc85e0cf8da0b823157962d70639e63cb9b578b1dec9868dd1f4f937"}, 80 | {file = "aiohttp-3.8.3-cp38-cp38-win32.whl", hash = "sha256:66bd5f950344fb2b3dbdd421aaa4e84f4411a1a13fca3aeb2bcbe667f80c9f76"}, 81 | {file = "aiohttp-3.8.3-cp38-cp38-win_amd64.whl", hash = "sha256:84b14f36e85295fe69c6b9789b51a0903b774046d5f7df538176516c3e422446"}, 82 | {file = "aiohttp-3.8.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16c121ba0b1ec2b44b73e3a8a171c4f999b33929cd2397124a8c7fcfc8cd9e06"}, 83 | {file = "aiohttp-3.8.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8d6aaa4e7155afaf994d7924eb290abbe81a6905b303d8cb61310a2aba1c68ba"}, 84 | {file = "aiohttp-3.8.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:43046a319664a04b146f81b40e1545d4c8ac7b7dd04c47e40bf09f65f2437346"}, 85 | {file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:599418aaaf88a6d02a8c515e656f6faf3d10618d3dd95866eb4436520096c84b"}, 86 | {file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92a2964319d359f494f16011e23434f6f8ef0434acd3cf154a6b7bec511e2fb7"}, 87 | {file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73a4131962e6d91109bca6536416aa067cf6c4efb871975df734f8d2fd821b37"}, 88 | {file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598adde339d2cf7d67beaccda3f2ce7c57b3b412702f29c946708f69cf8222aa"}, 89 | {file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75880ed07be39beff1881d81e4a907cafb802f306efd6d2d15f2b3c69935f6fb"}, 90 | {file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a0239da9fbafd9ff82fd67c16704a7d1bccf0d107a300e790587ad05547681c8"}, 91 | {file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:4e3a23ec214e95c9fe85a58470b660efe6534b83e6cbe38b3ed52b053d7cb6ad"}, 92 | {file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:47841407cc89a4b80b0c52276f3cc8138bbbfba4b179ee3acbd7d77ae33f7ac4"}, 93 | {file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:54d107c89a3ebcd13228278d68f1436d3f33f2dd2af5415e3feaeb1156e1a62c"}, 94 | {file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c37c5cce780349d4d51739ae682dec63573847a2a8dcb44381b174c3d9c8d403"}, 95 | {file = "aiohttp-3.8.3-cp39-cp39-win32.whl", hash = "sha256:f178d2aadf0166be4df834c4953da2d7eef24719e8aec9a65289483eeea9d618"}, 96 | {file = "aiohttp-3.8.3-cp39-cp39-win_amd64.whl", hash = "sha256:88e5be56c231981428f4f506c68b6a46fa25c4123a2e86d156c58a8369d31ab7"}, 97 | {file = "aiohttp-3.8.3.tar.gz", hash = "sha256:3828fb41b7203176b82fe5d699e0d845435f2374750a44b480ea6b930f6be269"}, 98 | ] 99 | 100 | [package.dependencies] 101 | aiosignal = ">=1.1.2" 102 | async-timeout = ">=4.0.0a3,<5.0" 103 | asynctest = {version = "0.13.0", markers = "python_version < \"3.8\""} 104 | attrs = ">=17.3.0" 105 | charset-normalizer = ">=2.0,<3.0" 106 | frozenlist = ">=1.1.1" 107 | multidict = ">=4.5,<7.0" 108 | typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} 109 | yarl = ">=1.0,<2.0" 110 | 111 | [package.extras] 112 | speedups = ["Brotli", "aiodns", "cchardet"] 113 | 114 | [[package]] 115 | name = "aiosignal" 116 | version = "1.3.1" 117 | description = "aiosignal: a list of registered asynchronous callbacks" 118 | category = "main" 119 | optional = false 120 | python-versions = ">=3.7" 121 | files = [ 122 | {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, 123 | {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, 124 | ] 125 | 126 | [package.dependencies] 127 | frozenlist = ">=1.1.0" 128 | 129 | [[package]] 130 | name = "arrow" 131 | version = "1.2.3" 132 | description = "Better dates & times for Python" 133 | category = "main" 134 | optional = false 135 | python-versions = ">=3.6" 136 | files = [ 137 | {file = "arrow-1.2.3-py3-none-any.whl", hash = "sha256:5a49ab92e3b7b71d96cd6bfcc4df14efefc9dfa96ea19045815914a6ab6b1fe2"}, 138 | {file = "arrow-1.2.3.tar.gz", hash = "sha256:3934b30ca1b9f292376d9db15b19446088d12ec58629bc3f0da28fd55fb633a1"}, 139 | ] 140 | 141 | [package.dependencies] 142 | python-dateutil = ">=2.7.0" 143 | typing-extensions = {version = "*", markers = "python_version < \"3.8\""} 144 | 145 | [[package]] 146 | name = "async-timeout" 147 | version = "4.0.2" 148 | description = "Timeout context manager for asyncio programs" 149 | category = "main" 150 | optional = false 151 | python-versions = ">=3.6" 152 | files = [ 153 | {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, 154 | {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, 155 | ] 156 | 157 | [package.dependencies] 158 | typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""} 159 | 160 | [[package]] 161 | name = "asynctest" 162 | version = "0.13.0" 163 | description = "Enhance the standard unittest package with features for testing asyncio libraries" 164 | category = "main" 165 | optional = false 166 | python-versions = ">=3.5" 167 | files = [ 168 | {file = "asynctest-0.13.0-py3-none-any.whl", hash = "sha256:5da6118a7e6d6b54d83a8f7197769d046922a44d2a99c21382f0a6e4fadae676"}, 169 | {file = "asynctest-0.13.0.tar.gz", hash = "sha256:c27862842d15d83e6a34eb0b2866c323880eb3a75e4485b079ea11748fd77fac"}, 170 | ] 171 | 172 | [[package]] 173 | name = "attrs" 174 | version = "22.2.0" 175 | description = "Classes Without Boilerplate" 176 | category = "main" 177 | optional = false 178 | python-versions = ">=3.6" 179 | files = [ 180 | {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, 181 | {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, 182 | ] 183 | 184 | [package.extras] 185 | cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] 186 | dev = ["attrs[docs,tests]"] 187 | docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] 188 | tests = ["attrs[tests-no-zope]", "zope.interface"] 189 | tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] 190 | 191 | [[package]] 192 | name = "black" 193 | version = "22.12.0" 194 | description = "The uncompromising code formatter." 195 | category = "dev" 196 | optional = false 197 | python-versions = ">=3.7" 198 | files = [ 199 | {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, 200 | {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, 201 | {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, 202 | {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, 203 | {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, 204 | {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, 205 | {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, 206 | {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, 207 | {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, 208 | {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, 209 | {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, 210 | {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, 211 | ] 212 | 213 | [package.dependencies] 214 | click = ">=8.0.0" 215 | mypy-extensions = ">=0.4.3" 216 | pathspec = ">=0.9.0" 217 | platformdirs = ">=2" 218 | tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} 219 | typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} 220 | typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} 221 | 222 | [package.extras] 223 | colorama = ["colorama (>=0.4.3)"] 224 | d = ["aiohttp (>=3.7.4)"] 225 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] 226 | uvloop = ["uvloop (>=0.15.2)"] 227 | 228 | [[package]] 229 | name = "charset-normalizer" 230 | version = "2.1.1" 231 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 232 | category = "main" 233 | optional = false 234 | python-versions = ">=3.6.0" 235 | files = [ 236 | {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, 237 | {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, 238 | ] 239 | 240 | [package.extras] 241 | unicode-backport = ["unicodedata2"] 242 | 243 | [[package]] 244 | name = "click" 245 | version = "8.1.3" 246 | description = "Composable command line interface toolkit" 247 | category = "dev" 248 | optional = false 249 | python-versions = ">=3.7" 250 | files = [ 251 | {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, 252 | {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, 253 | ] 254 | 255 | [package.dependencies] 256 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 257 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 258 | 259 | [[package]] 260 | name = "colorama" 261 | version = "0.4.6" 262 | description = "Cross-platform colored terminal text." 263 | category = "dev" 264 | optional = false 265 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 266 | files = [ 267 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 268 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 269 | ] 270 | 271 | [[package]] 272 | name = "exceptiongroup" 273 | version = "1.1.0" 274 | description = "Backport of PEP 654 (exception groups)" 275 | category = "dev" 276 | optional = false 277 | python-versions = ">=3.7" 278 | files = [ 279 | {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"}, 280 | {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"}, 281 | ] 282 | 283 | [package.extras] 284 | test = ["pytest (>=6)"] 285 | 286 | [[package]] 287 | name = "frozenlist" 288 | version = "1.3.3" 289 | description = "A list-like structure which implements collections.abc.MutableSequence" 290 | category = "main" 291 | optional = false 292 | python-versions = ">=3.7" 293 | files = [ 294 | {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff8bf625fe85e119553b5383ba0fb6aa3d0ec2ae980295aaefa552374926b3f4"}, 295 | {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dfbac4c2dfcc082fcf8d942d1e49b6aa0766c19d3358bd86e2000bf0fa4a9cf0"}, 296 | {file = "frozenlist-1.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b1c63e8d377d039ac769cd0926558bb7068a1f7abb0f003e3717ee003ad85530"}, 297 | {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fdfc24dcfce5b48109867c13b4cb15e4660e7bd7661741a391f821f23dfdca7"}, 298 | {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c926450857408e42f0bbc295e84395722ce74bae69a3b2aa2a65fe22cb14b99"}, 299 | {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1841e200fdafc3d51f974d9d377c079a0694a8f06de2e67b48150328d66d5483"}, 300 | {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f470c92737afa7d4c3aacc001e335062d582053d4dbe73cda126f2d7031068dd"}, 301 | {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:783263a4eaad7c49983fe4b2e7b53fa9770c136c270d2d4bbb6d2192bf4d9caf"}, 302 | {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:924620eef691990dfb56dc4709f280f40baee568c794b5c1885800c3ecc69816"}, 303 | {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae4dc05c465a08a866b7a1baf360747078b362e6a6dbeb0c57f234db0ef88ae0"}, 304 | {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bed331fe18f58d844d39ceb398b77d6ac0b010d571cba8267c2e7165806b00ce"}, 305 | {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:02c9ac843e3390826a265e331105efeab489ffaf4dd86384595ee8ce6d35ae7f"}, 306 | {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9545a33965d0d377b0bc823dcabf26980e77f1b6a7caa368a365a9497fb09420"}, 307 | {file = "frozenlist-1.3.3-cp310-cp310-win32.whl", hash = "sha256:d5cd3ab21acbdb414bb6c31958d7b06b85eeb40f66463c264a9b343a4e238642"}, 308 | {file = "frozenlist-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:b756072364347cb6aa5b60f9bc18e94b2f79632de3b0190253ad770c5df17db1"}, 309 | {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4395e2f8d83fbe0c627b2b696acce67868793d7d9750e90e39592b3626691b7"}, 310 | {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14143ae966a6229350021384870458e4777d1eae4c28d1a7aa47f24d030e6678"}, 311 | {file = "frozenlist-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d8860749e813a6f65bad8285a0520607c9500caa23fea6ee407e63debcdbef6"}, 312 | {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23d16d9f477bb55b6154654e0e74557040575d9d19fe78a161bd33d7d76808e8"}, 313 | {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb82dbba47a8318e75f679690190c10a5e1f447fbf9df41cbc4c3afd726d88cb"}, 314 | {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9309869032abb23d196cb4e4db574232abe8b8be1339026f489eeb34a4acfd91"}, 315 | {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a97b4fe50b5890d36300820abd305694cb865ddb7885049587a5678215782a6b"}, 316 | {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c188512b43542b1e91cadc3c6c915a82a5eb95929134faf7fd109f14f9892ce4"}, 317 | {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:303e04d422e9b911a09ad499b0368dc551e8c3cd15293c99160c7f1f07b59a48"}, 318 | {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0771aed7f596c7d73444c847a1c16288937ef988dc04fb9f7be4b2aa91db609d"}, 319 | {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:66080ec69883597e4d026f2f71a231a1ee9887835902dbe6b6467d5a89216cf6"}, 320 | {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:41fe21dc74ad3a779c3d73a2786bdf622ea81234bdd4faf90b8b03cad0c2c0b4"}, 321 | {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f20380df709d91525e4bee04746ba612a4df0972c1b8f8e1e8af997e678c7b81"}, 322 | {file = "frozenlist-1.3.3-cp311-cp311-win32.whl", hash = "sha256:f30f1928162e189091cf4d9da2eac617bfe78ef907a761614ff577ef4edfb3c8"}, 323 | {file = "frozenlist-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a6394d7dadd3cfe3f4b3b186e54d5d8504d44f2d58dcc89d693698e8b7132b32"}, 324 | {file = "frozenlist-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8df3de3a9ab8325f94f646609a66cbeeede263910c5c0de0101079ad541af332"}, 325 | {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0693c609e9742c66ba4870bcee1ad5ff35462d5ffec18710b4ac89337ff16e27"}, 326 | {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd4210baef299717db0a600d7a3cac81d46ef0e007f88c9335db79f8979c0d3d"}, 327 | {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:394c9c242113bfb4b9aa36e2b80a05ffa163a30691c7b5a29eba82e937895d5e"}, 328 | {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6327eb8e419f7d9c38f333cde41b9ae348bec26d840927332f17e887a8dcb70d"}, 329 | {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e24900aa13212e75e5b366cb9065e78bbf3893d4baab6052d1aca10d46d944c"}, 330 | {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3843f84a6c465a36559161e6c59dce2f2ac10943040c2fd021cfb70d58c4ad56"}, 331 | {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:84610c1502b2461255b4c9b7d5e9c48052601a8957cd0aea6ec7a7a1e1fb9420"}, 332 | {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:c21b9aa40e08e4f63a2f92ff3748e6b6c84d717d033c7b3438dd3123ee18f70e"}, 333 | {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:efce6ae830831ab6a22b9b4091d411698145cb9b8fc869e1397ccf4b4b6455cb"}, 334 | {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:40de71985e9042ca00b7953c4f41eabc3dc514a2d1ff534027f091bc74416401"}, 335 | {file = "frozenlist-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:180c00c66bde6146a860cbb81b54ee0df350d2daf13ca85b275123bbf85de18a"}, 336 | {file = "frozenlist-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9bbbcedd75acdfecf2159663b87f1bb5cfc80e7cd99f7ddd9d66eb98b14a8411"}, 337 | {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:034a5c08d36649591be1cbb10e09da9f531034acfe29275fc5454a3b101ce41a"}, 338 | {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba64dc2b3b7b158c6660d49cdb1d872d1d0bf4e42043ad8d5006099479a194e5"}, 339 | {file = "frozenlist-1.3.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:47df36a9fe24054b950bbc2db630d508cca3aa27ed0566c0baf661225e52c18e"}, 340 | {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:008a054b75d77c995ea26629ab3a0c0d7281341f2fa7e1e85fa6153ae29ae99c"}, 341 | {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:841ea19b43d438a80b4de62ac6ab21cfe6827bb8a9dc62b896acc88eaf9cecba"}, 342 | {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e235688f42b36be2b6b06fc37ac2126a73b75fb8d6bc66dd632aa35286238703"}, 343 | {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca713d4af15bae6e5d79b15c10c8522859a9a89d3b361a50b817c98c2fb402a2"}, 344 | {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ac5995f2b408017b0be26d4a1d7c61bce106ff3d9e3324374d66b5964325448"}, 345 | {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4ae8135b11652b08a8baf07631d3ebfe65a4c87909dbef5fa0cdde440444ee4"}, 346 | {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4ea42116ceb6bb16dbb7d526e242cb6747b08b7710d9782aa3d6732bd8d27649"}, 347 | {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:810860bb4bdce7557bc0febb84bbd88198b9dbc2022d8eebe5b3590b2ad6c842"}, 348 | {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ee78feb9d293c323b59a6f2dd441b63339a30edf35abcb51187d2fc26e696d13"}, 349 | {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0af2e7c87d35b38732e810befb9d797a99279cbb85374d42ea61c1e9d23094b3"}, 350 | {file = "frozenlist-1.3.3-cp38-cp38-win32.whl", hash = "sha256:899c5e1928eec13fd6f6d8dc51be23f0d09c5281e40d9cf4273d188d9feeaf9b"}, 351 | {file = "frozenlist-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:7f44e24fa70f6fbc74aeec3e971f60a14dde85da364aa87f15d1be94ae75aeef"}, 352 | {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2b07ae0c1edaa0a36339ec6cce700f51b14a3fc6545fdd32930d2c83917332cf"}, 353 | {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ebb86518203e12e96af765ee89034a1dbb0c3c65052d1b0c19bbbd6af8a145e1"}, 354 | {file = "frozenlist-1.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5cf820485f1b4c91e0417ea0afd41ce5cf5965011b3c22c400f6d144296ccbc0"}, 355 | {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c11e43016b9024240212d2a65043b70ed8dfd3b52678a1271972702d990ac6d"}, 356 | {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8fa3c6e3305aa1146b59a09b32b2e04074945ffcfb2f0931836d103a2c38f936"}, 357 | {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:352bd4c8c72d508778cf05ab491f6ef36149f4d0cb3c56b1b4302852255d05d5"}, 358 | {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65a5e4d3aa679610ac6e3569e865425b23b372277f89b5ef06cf2cdaf1ebf22b"}, 359 | {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e2c1185858d7e10ff045c496bbf90ae752c28b365fef2c09cf0fa309291669"}, 360 | {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f163d2fd041c630fed01bc48d28c3ed4a3b003c00acd396900e11ee5316b56bb"}, 361 | {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:05cdb16d09a0832eedf770cb7bd1fe57d8cf4eaf5aced29c4e41e3f20b30a784"}, 362 | {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8bae29d60768bfa8fb92244b74502b18fae55a80eac13c88eb0b496d4268fd2d"}, 363 | {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eedab4c310c0299961ac285591acd53dc6723a1ebd90a57207c71f6e0c2153ab"}, 364 | {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3bbdf44855ed8f0fbcd102ef05ec3012d6a4fd7c7562403f76ce6a52aeffb2b1"}, 365 | {file = "frozenlist-1.3.3-cp39-cp39-win32.whl", hash = "sha256:efa568b885bca461f7c7b9e032655c0c143d305bf01c30caf6db2854a4532b38"}, 366 | {file = "frozenlist-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfe33efc9cb900a4c46f91a5ceba26d6df370ffddd9ca386eb1d4f0ad97b9ea9"}, 367 | {file = "frozenlist-1.3.3.tar.gz", hash = "sha256:58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a"}, 368 | ] 369 | 370 | [[package]] 371 | name = "idna" 372 | version = "3.4" 373 | description = "Internationalized Domain Names in Applications (IDNA)" 374 | category = "main" 375 | optional = false 376 | python-versions = ">=3.5" 377 | files = [ 378 | {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, 379 | {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, 380 | ] 381 | 382 | [[package]] 383 | name = "importlib-metadata" 384 | version = "6.0.0" 385 | description = "Read metadata from Python packages" 386 | category = "dev" 387 | optional = false 388 | python-versions = ">=3.7" 389 | files = [ 390 | {file = "importlib_metadata-6.0.0-py3-none-any.whl", hash = "sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad"}, 391 | {file = "importlib_metadata-6.0.0.tar.gz", hash = "sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d"}, 392 | ] 393 | 394 | [package.dependencies] 395 | typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} 396 | zipp = ">=0.5" 397 | 398 | [package.extras] 399 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] 400 | perf = ["ipython"] 401 | testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] 402 | 403 | [[package]] 404 | name = "iniconfig" 405 | version = "2.0.0" 406 | description = "brain-dead simple config-ini parsing" 407 | category = "dev" 408 | optional = false 409 | python-versions = ">=3.7" 410 | files = [ 411 | {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, 412 | {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, 413 | ] 414 | 415 | [[package]] 416 | name = "isort" 417 | version = "5.11.4" 418 | description = "A Python utility / library to sort Python imports." 419 | category = "dev" 420 | optional = false 421 | python-versions = ">=3.7.0" 422 | files = [ 423 | {file = "isort-5.11.4-py3-none-any.whl", hash = "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b"}, 424 | {file = "isort-5.11.4.tar.gz", hash = "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6"}, 425 | ] 426 | 427 | [package.extras] 428 | colors = ["colorama (>=0.4.3,<0.5.0)"] 429 | pipfile-deprecated-finder = ["pipreqs", "requirementslib"] 430 | plugins = ["setuptools"] 431 | requirements-deprecated-finder = ["pip-api", "pipreqs"] 432 | 433 | [[package]] 434 | name = "multidict" 435 | version = "6.0.4" 436 | description = "multidict implementation" 437 | category = "main" 438 | optional = false 439 | python-versions = ">=3.7" 440 | files = [ 441 | {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, 442 | {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, 443 | {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, 444 | {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, 445 | {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, 446 | {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, 447 | {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, 448 | {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, 449 | {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, 450 | {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, 451 | {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, 452 | {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, 453 | {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, 454 | {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, 455 | {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, 456 | {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, 457 | {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, 458 | {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, 459 | {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, 460 | {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, 461 | {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, 462 | {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, 463 | {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, 464 | {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, 465 | {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, 466 | {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, 467 | {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, 468 | {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, 469 | {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, 470 | {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, 471 | {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, 472 | {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, 473 | {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, 474 | {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, 475 | {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, 476 | {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, 477 | {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, 478 | {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, 479 | {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, 480 | {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, 481 | {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, 482 | {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, 483 | {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, 484 | {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, 485 | {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, 486 | {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, 487 | {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, 488 | {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, 489 | {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, 490 | {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, 491 | {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, 492 | {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, 493 | {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, 494 | {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, 495 | {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, 496 | {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, 497 | {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, 498 | {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, 499 | {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, 500 | {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, 501 | {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, 502 | {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, 503 | {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, 504 | {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, 505 | {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, 506 | {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, 507 | {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, 508 | {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, 509 | {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, 510 | {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, 511 | {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, 512 | {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, 513 | {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, 514 | {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, 515 | ] 516 | 517 | [[package]] 518 | name = "mypy" 519 | version = "0.991" 520 | description = "Optional static typing for Python" 521 | category = "dev" 522 | optional = false 523 | python-versions = ">=3.7" 524 | files = [ 525 | {file = "mypy-0.991-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7d17e0a9707d0772f4a7b878f04b4fd11f6f5bcb9b3813975a9b13c9332153ab"}, 526 | {file = "mypy-0.991-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0714258640194d75677e86c786e80ccf294972cc76885d3ebbb560f11db0003d"}, 527 | {file = "mypy-0.991-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0c8f3be99e8a8bd403caa8c03be619544bc2c77a7093685dcf308c6b109426c6"}, 528 | {file = "mypy-0.991-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9ec663ed6c8f15f4ae9d3c04c989b744436c16d26580eaa760ae9dd5d662eb"}, 529 | {file = "mypy-0.991-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4307270436fd7694b41f913eb09210faff27ea4979ecbcd849e57d2da2f65305"}, 530 | {file = "mypy-0.991-cp310-cp310-win_amd64.whl", hash = "sha256:901c2c269c616e6cb0998b33d4adbb4a6af0ac4ce5cd078afd7bc95830e62c1c"}, 531 | {file = "mypy-0.991-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d13674f3fb73805ba0c45eb6c0c3053d218aa1f7abead6e446d474529aafc372"}, 532 | {file = "mypy-0.991-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1c8cd4fb70e8584ca1ed5805cbc7c017a3d1a29fb450621089ffed3e99d1857f"}, 533 | {file = "mypy-0.991-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:209ee89fbb0deed518605edddd234af80506aec932ad28d73c08f1400ef80a33"}, 534 | {file = "mypy-0.991-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37bd02ebf9d10e05b00d71302d2c2e6ca333e6c2a8584a98c00e038db8121f05"}, 535 | {file = "mypy-0.991-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:26efb2fcc6b67e4d5a55561f39176821d2adf88f2745ddc72751b7890f3194ad"}, 536 | {file = "mypy-0.991-cp311-cp311-win_amd64.whl", hash = "sha256:3a700330b567114b673cf8ee7388e949f843b356a73b5ab22dd7cff4742a5297"}, 537 | {file = "mypy-0.991-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1f7d1a520373e2272b10796c3ff721ea1a0712288cafaa95931e66aa15798813"}, 538 | {file = "mypy-0.991-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:641411733b127c3e0dab94c45af15fea99e4468f99ac88b39efb1ad677da5711"}, 539 | {file = "mypy-0.991-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3d80e36b7d7a9259b740be6d8d906221789b0d836201af4234093cae89ced0cd"}, 540 | {file = "mypy-0.991-cp37-cp37m-win_amd64.whl", hash = "sha256:e62ebaad93be3ad1a828a11e90f0e76f15449371ffeecca4a0a0b9adc99abcef"}, 541 | {file = "mypy-0.991-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b86ce2c1866a748c0f6faca5232059f881cda6dda2a893b9a8373353cfe3715a"}, 542 | {file = "mypy-0.991-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac6e503823143464538efda0e8e356d871557ef60ccd38f8824a4257acc18d93"}, 543 | {file = "mypy-0.991-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0cca5adf694af539aeaa6ac633a7afe9bbd760df9d31be55ab780b77ab5ae8bf"}, 544 | {file = "mypy-0.991-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12c56bf73cdab116df96e4ff39610b92a348cc99a1307e1da3c3768bbb5b135"}, 545 | {file = "mypy-0.991-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:652b651d42f155033a1967739788c436491b577b6a44e4c39fb340d0ee7f0d70"}, 546 | {file = "mypy-0.991-cp38-cp38-win_amd64.whl", hash = "sha256:4175593dc25d9da12f7de8de873a33f9b2b8bdb4e827a7cae952e5b1a342e243"}, 547 | {file = "mypy-0.991-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:98e781cd35c0acf33eb0295e8b9c55cdbef64fcb35f6d3aa2186f289bed6e80d"}, 548 | {file = "mypy-0.991-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6d7464bac72a85cb3491c7e92b5b62f3dcccb8af26826257760a552a5e244aa5"}, 549 | {file = "mypy-0.991-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c9166b3f81a10cdf9b49f2d594b21b31adadb3d5e9db9b834866c3258b695be3"}, 550 | {file = "mypy-0.991-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8472f736a5bfb159a5e36740847808f6f5b659960115ff29c7cecec1741c648"}, 551 | {file = "mypy-0.991-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e80e758243b97b618cdf22004beb09e8a2de1af481382e4d84bc52152d1c476"}, 552 | {file = "mypy-0.991-cp39-cp39-win_amd64.whl", hash = "sha256:74e259b5c19f70d35fcc1ad3d56499065c601dfe94ff67ae48b85596b9ec1461"}, 553 | {file = "mypy-0.991-py3-none-any.whl", hash = "sha256:de32edc9b0a7e67c2775e574cb061a537660e51210fbf6006b0b36ea695ae9bb"}, 554 | {file = "mypy-0.991.tar.gz", hash = "sha256:3c0165ba8f354a6d9881809ef29f1a9318a236a6d81c690094c5df32107bde06"}, 555 | ] 556 | 557 | [package.dependencies] 558 | mypy-extensions = ">=0.4.3" 559 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 560 | typed-ast = {version = ">=1.4.0,<2", markers = "python_version < \"3.8\""} 561 | typing-extensions = ">=3.10" 562 | 563 | [package.extras] 564 | dmypy = ["psutil (>=4.0)"] 565 | install-types = ["pip"] 566 | python2 = ["typed-ast (>=1.4.0,<2)"] 567 | reports = ["lxml"] 568 | 569 | [[package]] 570 | name = "mypy-extensions" 571 | version = "0.4.3" 572 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 573 | category = "dev" 574 | optional = false 575 | python-versions = "*" 576 | files = [ 577 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 578 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 579 | ] 580 | 581 | [[package]] 582 | name = "packaging" 583 | version = "23.0" 584 | description = "Core utilities for Python packages" 585 | category = "dev" 586 | optional = false 587 | python-versions = ">=3.7" 588 | files = [ 589 | {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, 590 | {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, 591 | ] 592 | 593 | [[package]] 594 | name = "pathspec" 595 | version = "0.10.3" 596 | description = "Utility library for gitignore style pattern matching of file paths." 597 | category = "dev" 598 | optional = false 599 | python-versions = ">=3.7" 600 | files = [ 601 | {file = "pathspec-0.10.3-py3-none-any.whl", hash = "sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6"}, 602 | {file = "pathspec-0.10.3.tar.gz", hash = "sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6"}, 603 | ] 604 | 605 | [[package]] 606 | name = "platformdirs" 607 | version = "2.6.2" 608 | description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 609 | category = "dev" 610 | optional = false 611 | python-versions = ">=3.7" 612 | files = [ 613 | {file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"}, 614 | {file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"}, 615 | ] 616 | 617 | [package.dependencies] 618 | typing-extensions = {version = ">=4.4", markers = "python_version < \"3.8\""} 619 | 620 | [package.extras] 621 | docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] 622 | test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] 623 | 624 | [[package]] 625 | name = "pluggy" 626 | version = "1.0.0" 627 | description = "plugin and hook calling mechanisms for python" 628 | category = "dev" 629 | optional = false 630 | python-versions = ">=3.6" 631 | files = [ 632 | {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, 633 | {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, 634 | ] 635 | 636 | [package.dependencies] 637 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} 638 | 639 | [package.extras] 640 | dev = ["pre-commit", "tox"] 641 | testing = ["pytest", "pytest-benchmark"] 642 | 643 | [[package]] 644 | name = "pytest" 645 | version = "7.2.0" 646 | description = "pytest: simple powerful testing with Python" 647 | category = "dev" 648 | optional = false 649 | python-versions = ">=3.7" 650 | files = [ 651 | {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, 652 | {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, 653 | ] 654 | 655 | [package.dependencies] 656 | attrs = ">=19.2.0" 657 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 658 | exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} 659 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} 660 | iniconfig = "*" 661 | packaging = "*" 662 | pluggy = ">=0.12,<2.0" 663 | tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} 664 | 665 | [package.extras] 666 | testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] 667 | 668 | [[package]] 669 | name = "pytest-asyncio" 670 | version = "0.20.3" 671 | description = "Pytest support for asyncio" 672 | category = "dev" 673 | optional = false 674 | python-versions = ">=3.7" 675 | files = [ 676 | {file = "pytest-asyncio-0.20.3.tar.gz", hash = "sha256:83cbf01169ce3e8eb71c6c278ccb0574d1a7a3bb8eaaf5e50e0ad342afb33b36"}, 677 | {file = "pytest_asyncio-0.20.3-py3-none-any.whl", hash = "sha256:f129998b209d04fcc65c96fc85c11e5316738358909a8399e93be553d7656442"}, 678 | ] 679 | 680 | [package.dependencies] 681 | pytest = ">=6.1.0" 682 | typing-extensions = {version = ">=3.7.2", markers = "python_version < \"3.8\""} 683 | 684 | [package.extras] 685 | docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] 686 | testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] 687 | 688 | [[package]] 689 | name = "python-dateutil" 690 | version = "2.8.2" 691 | description = "Extensions to the standard Python datetime module" 692 | category = "main" 693 | optional = false 694 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 695 | files = [ 696 | {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, 697 | {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, 698 | ] 699 | 700 | [package.dependencies] 701 | six = ">=1.5" 702 | 703 | [[package]] 704 | name = "six" 705 | version = "1.16.0" 706 | description = "Python 2 and 3 compatibility utilities" 707 | category = "main" 708 | optional = false 709 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 710 | files = [ 711 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 712 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 713 | ] 714 | 715 | [[package]] 716 | name = "tomli" 717 | version = "2.0.1" 718 | description = "A lil' TOML parser" 719 | category = "dev" 720 | optional = false 721 | python-versions = ">=3.7" 722 | files = [ 723 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 724 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 725 | ] 726 | 727 | [[package]] 728 | name = "typed-ast" 729 | version = "1.5.4" 730 | description = "a fork of Python 2 and 3 ast modules with type comment support" 731 | category = "dev" 732 | optional = false 733 | python-versions = ">=3.6" 734 | files = [ 735 | {file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"}, 736 | {file = "typed_ast-1.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62"}, 737 | {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac"}, 738 | {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe"}, 739 | {file = "typed_ast-1.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72"}, 740 | {file = "typed_ast-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec"}, 741 | {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47"}, 742 | {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6"}, 743 | {file = "typed_ast-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1"}, 744 | {file = "typed_ast-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6"}, 745 | {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66"}, 746 | {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c"}, 747 | {file = "typed_ast-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2"}, 748 | {file = "typed_ast-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d"}, 749 | {file = "typed_ast-1.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f"}, 750 | {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc"}, 751 | {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6"}, 752 | {file = "typed_ast-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e"}, 753 | {file = "typed_ast-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35"}, 754 | {file = "typed_ast-1.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97"}, 755 | {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3"}, 756 | {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72"}, 757 | {file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"}, 758 | {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, 759 | ] 760 | 761 | [[package]] 762 | name = "typing-extensions" 763 | version = "4.4.0" 764 | description = "Backported and Experimental Type Hints for Python 3.7+" 765 | category = "main" 766 | optional = false 767 | python-versions = ">=3.7" 768 | files = [ 769 | {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, 770 | {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, 771 | ] 772 | 773 | [[package]] 774 | name = "yarl" 775 | version = "1.8.2" 776 | description = "Yet another URL library" 777 | category = "main" 778 | optional = false 779 | python-versions = ">=3.7" 780 | files = [ 781 | {file = "yarl-1.8.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bb81f753c815f6b8e2ddd2eef3c855cf7da193b82396ac013c661aaa6cc6b0a5"}, 782 | {file = "yarl-1.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:47d49ac96156f0928f002e2424299b2c91d9db73e08c4cd6742923a086f1c863"}, 783 | {file = "yarl-1.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3fc056e35fa6fba63248d93ff6e672c096f95f7836938241ebc8260e062832fe"}, 784 | {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58a3c13d1c3005dbbac5c9f0d3210b60220a65a999b1833aa46bd6677c69b08e"}, 785 | {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10b08293cda921157f1e7c2790999d903b3fd28cd5c208cf8826b3b508026996"}, 786 | {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de986979bbd87272fe557e0a8fcb66fd40ae2ddfe28a8b1ce4eae22681728fef"}, 787 | {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c4fcfa71e2c6a3cb568cf81aadc12768b9995323186a10827beccf5fa23d4f8"}, 788 | {file = "yarl-1.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae4d7ff1049f36accde9e1ef7301912a751e5bae0a9d142459646114c70ecba6"}, 789 | {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bf071f797aec5b96abfc735ab97da9fd8f8768b43ce2abd85356a3127909d146"}, 790 | {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:74dece2bfc60f0f70907c34b857ee98f2c6dd0f75185db133770cd67300d505f"}, 791 | {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:df60a94d332158b444301c7f569659c926168e4d4aad2cfbf4bce0e8fb8be826"}, 792 | {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:63243b21c6e28ec2375f932a10ce7eda65139b5b854c0f6b82ed945ba526bff3"}, 793 | {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cfa2bbca929aa742b5084fd4663dd4b87c191c844326fcb21c3afd2d11497f80"}, 794 | {file = "yarl-1.8.2-cp310-cp310-win32.whl", hash = "sha256:b05df9ea7496df11b710081bd90ecc3a3db6adb4fee36f6a411e7bc91a18aa42"}, 795 | {file = "yarl-1.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:24ad1d10c9db1953291f56b5fe76203977f1ed05f82d09ec97acb623a7976574"}, 796 | {file = "yarl-1.8.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2a1fca9588f360036242f379bfea2b8b44cae2721859b1c56d033adfd5893634"}, 797 | {file = "yarl-1.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f37db05c6051eff17bc832914fe46869f8849de5b92dc4a3466cd63095d23dfd"}, 798 | {file = "yarl-1.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:77e913b846a6b9c5f767b14dc1e759e5aff05502fe73079f6f4176359d832581"}, 799 | {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0978f29222e649c351b173da2b9b4665ad1feb8d1daa9d971eb90df08702668a"}, 800 | {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388a45dc77198b2460eac0aca1efd6a7c09e976ee768b0d5109173e521a19daf"}, 801 | {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2305517e332a862ef75be8fad3606ea10108662bc6fe08509d5ca99503ac2aee"}, 802 | {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42430ff511571940d51e75cf42f1e4dbdded477e71c1b7a17f4da76c1da8ea76"}, 803 | {file = "yarl-1.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3150078118f62371375e1e69b13b48288e44f6691c1069340081c3fd12c94d5b"}, 804 | {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c15163b6125db87c8f53c98baa5e785782078fbd2dbeaa04c6141935eb6dab7a"}, 805 | {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4d04acba75c72e6eb90745447d69f84e6c9056390f7a9724605ca9c56b4afcc6"}, 806 | {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e7fd20d6576c10306dea2d6a5765f46f0ac5d6f53436217913e952d19237efc4"}, 807 | {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:75c16b2a900b3536dfc7014905a128a2bea8fb01f9ee26d2d7d8db0a08e7cb2c"}, 808 | {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6d88056a04860a98341a0cf53e950e3ac9f4e51d1b6f61a53b0609df342cc8b2"}, 809 | {file = "yarl-1.8.2-cp311-cp311-win32.whl", hash = "sha256:fb742dcdd5eec9f26b61224c23baea46c9055cf16f62475e11b9b15dfd5c117b"}, 810 | {file = "yarl-1.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8c46d3d89902c393a1d1e243ac847e0442d0196bbd81aecc94fcebbc2fd5857c"}, 811 | {file = "yarl-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ceff9722e0df2e0a9e8a79c610842004fa54e5b309fe6d218e47cd52f791d7ef"}, 812 | {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f6b4aca43b602ba0f1459de647af954769919c4714706be36af670a5f44c9c1"}, 813 | {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1684a9bd9077e922300ecd48003ddae7a7474e0412bea38d4631443a91d61077"}, 814 | {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ebb78745273e51b9832ef90c0898501006670d6e059f2cdb0e999494eb1450c2"}, 815 | {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3adeef150d528ded2a8e734ebf9ae2e658f4c49bf413f5f157a470e17a4a2e89"}, 816 | {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57a7c87927a468e5a1dc60c17caf9597161d66457a34273ab1760219953f7f4c"}, 817 | {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:efff27bd8cbe1f9bd127e7894942ccc20c857aa8b5a0327874f30201e5ce83d0"}, 818 | {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a783cd344113cb88c5ff7ca32f1f16532a6f2142185147822187913eb989f739"}, 819 | {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:705227dccbe96ab02c7cb2c43e1228e2826e7ead880bb19ec94ef279e9555b5b"}, 820 | {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:34c09b43bd538bf6c4b891ecce94b6fa4f1f10663a8d4ca589a079a5018f6ed7"}, 821 | {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a48f4f7fea9a51098b02209d90297ac324241bf37ff6be6d2b0149ab2bd51b37"}, 822 | {file = "yarl-1.8.2-cp37-cp37m-win32.whl", hash = "sha256:0414fd91ce0b763d4eadb4456795b307a71524dbacd015c657bb2a39db2eab89"}, 823 | {file = "yarl-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:d881d152ae0007809c2c02e22aa534e702f12071e6b285e90945aa3c376463c5"}, 824 | {file = "yarl-1.8.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5df5e3d04101c1e5c3b1d69710b0574171cc02fddc4b23d1b2813e75f35a30b1"}, 825 | {file = "yarl-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7a66c506ec67eb3159eea5096acd05f5e788ceec7b96087d30c7d2865a243918"}, 826 | {file = "yarl-1.8.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b4fa2606adf392051d990c3b3877d768771adc3faf2e117b9de7eb977741229"}, 827 | {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e21fb44e1eff06dd6ef971d4bdc611807d6bd3691223d9c01a18cec3677939e"}, 828 | {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93202666046d9edadfe9f2e7bf5e0782ea0d497b6d63da322e541665d65a044e"}, 829 | {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fc77086ce244453e074e445104f0ecb27530d6fd3a46698e33f6c38951d5a0f1"}, 830 | {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dd68a92cab699a233641f5929a40f02a4ede8c009068ca8aa1fe87b8c20ae3"}, 831 | {file = "yarl-1.8.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b372aad2b5f81db66ee7ec085cbad72c4da660d994e8e590c997e9b01e44901"}, 832 | {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e6f3515aafe0209dd17fb9bdd3b4e892963370b3de781f53e1746a521fb39fc0"}, 833 | {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dfef7350ee369197106805e193d420b75467b6cceac646ea5ed3049fcc950a05"}, 834 | {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:728be34f70a190566d20aa13dc1f01dc44b6aa74580e10a3fb159691bc76909d"}, 835 | {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ff205b58dc2929191f68162633d5e10e8044398d7a45265f90a0f1d51f85f72c"}, 836 | {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baf211dcad448a87a0d9047dc8282d7de59473ade7d7fdf22150b1d23859f946"}, 837 | {file = "yarl-1.8.2-cp38-cp38-win32.whl", hash = "sha256:272b4f1599f1b621bf2aabe4e5b54f39a933971f4e7c9aa311d6d7dc06965165"}, 838 | {file = "yarl-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:326dd1d3caf910cd26a26ccbfb84c03b608ba32499b5d6eeb09252c920bcbe4f"}, 839 | {file = "yarl-1.8.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f8ca8ad414c85bbc50f49c0a106f951613dfa5f948ab69c10ce9b128d368baf8"}, 840 | {file = "yarl-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:418857f837347e8aaef682679f41e36c24250097f9e2f315d39bae3a99a34cbf"}, 841 | {file = "yarl-1.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ae0eec05ab49e91a78700761777f284c2df119376e391db42c38ab46fd662b77"}, 842 | {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:009a028127e0a1755c38b03244c0bea9d5565630db9c4cf9572496e947137a87"}, 843 | {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3edac5d74bb3209c418805bda77f973117836e1de7c000e9755e572c1f7850d0"}, 844 | {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da65c3f263729e47351261351b8679c6429151ef9649bba08ef2528ff2c423b2"}, 845 | {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ef8fb25e52663a1c85d608f6dd72e19bd390e2ecaf29c17fb08f730226e3a08"}, 846 | {file = "yarl-1.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcd7bb1e5c45274af9a1dd7494d3c52b2be5e6bd8d7e49c612705fd45420b12d"}, 847 | {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44ceac0450e648de86da8e42674f9b7077d763ea80c8ceb9d1c3e41f0f0a9951"}, 848 | {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:97209cc91189b48e7cfe777237c04af8e7cc51eb369004e061809bcdf4e55220"}, 849 | {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:48dd18adcf98ea9cd721a25313aef49d70d413a999d7d89df44f469edfb38a06"}, 850 | {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e59399dda559688461762800d7fb34d9e8a6a7444fd76ec33220a926c8be1516"}, 851 | {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d617c241c8c3ad5c4e78a08429fa49e4b04bedfc507b34b4d8dceb83b4af3588"}, 852 | {file = "yarl-1.8.2-cp39-cp39-win32.whl", hash = "sha256:cb6d48d80a41f68de41212f3dfd1a9d9898d7841c8f7ce6696cf2fd9cb57ef83"}, 853 | {file = "yarl-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:6604711362f2dbf7160df21c416f81fac0de6dbcf0b5445a2ef25478ecc4c778"}, 854 | {file = "yarl-1.8.2.tar.gz", hash = "sha256:49d43402c6e3013ad0978602bf6bf5328535c48d192304b91b97a3c6790b1562"}, 855 | ] 856 | 857 | [package.dependencies] 858 | idna = ">=2.0" 859 | multidict = ">=4.0" 860 | typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} 861 | 862 | [[package]] 863 | name = "zipp" 864 | version = "3.11.0" 865 | description = "Backport of pathlib-compatible object wrapper for zip files" 866 | category = "dev" 867 | optional = false 868 | python-versions = ">=3.7" 869 | files = [ 870 | {file = "zipp-3.11.0-py3-none-any.whl", hash = "sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa"}, 871 | {file = "zipp-3.11.0.tar.gz", hash = "sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766"}, 872 | ] 873 | 874 | [package.extras] 875 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] 876 | testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] 877 | 878 | [metadata] 879 | lock-version = "2.0" 880 | python-versions = "^3.7" 881 | content-hash = "8386739d0736939b8d0bd5f49bef9cc0be69fa5cacdcb573c2b7cb1ac98df092" 882 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "async-iamport" 3 | version = "0.2.0" 4 | description = "" 5 | authors = ["한바름 "] 6 | readme = "README.md" 7 | packages = [{include = "async_iamport"}] 8 | 9 | [tool.poetry.dependencies] 10 | python = "^3.7" 11 | aiohttp = "^3.8.3" 12 | arrow = "^1.2.3" 13 | 14 | 15 | [tool.poetry.group.dev.dependencies] 16 | mypy = "^0.991" 17 | pytest = "^7.2.0" 18 | black = "^22.12.0" 19 | isort = "^5.11.4" 20 | pytest-asyncio = "^0.20.3" 21 | 22 | 23 | [tool.commitizen] 24 | name = "cz_conventional_commits" 25 | version = "0.2.0" 26 | tag_format = "v$version" 27 | version_files = [ 28 | "pyproject.toml:version" 29 | ] 30 | update_changelog_on_bump = true 31 | major_version_zero = true 32 | 33 | 34 | [build-system] 35 | requires = ["poetry-core"] 36 | build-backend = "poetry.core.masonry.api" 37 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rumbarum/iamport-async-rest-client-python/19b781bd4d0912c85d7f0407bec21c99a3f5bb26/tests/__init__.py -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | import pytest 4 | import pytest_asyncio 5 | from pytest import fixture 6 | 7 | from async_iamport import AsyncIamport 8 | 9 | DEFAULT_TEST_IMP_KEY = "imp_apikey" 10 | DEFAULT_TEST_IMP_SECRET = ( 11 | "ekKoeW8RyKuT0zgaZsUtXXTLQ4AhPFW3ZGseDA6b" 12 | "kA5lamv9OqDMnxyeB9wqOsuO9W3Mx9YSJ4dTqJ3f" 13 | ) 14 | 15 | 16 | def pytest_addoption(parser): 17 | parser.addoption( 18 | "--imp-key", 19 | default=DEFAULT_TEST_IMP_KEY, 20 | help="iamport client key for testing [default: %(default)s]", 21 | ) 22 | parser.addoption( 23 | "--imp-secret", 24 | default=DEFAULT_TEST_IMP_SECRET, 25 | help="iamport secret key for testing [default: %(default)s]", 26 | ) 27 | 28 | 29 | @pytest.fixture(scope="session") 30 | def event_loop(request): 31 | loop = asyncio.get_event_loop_policy().new_event_loop() 32 | yield loop 33 | loop.close() 34 | 35 | 36 | @pytest_asyncio.fixture(scope="session") 37 | async def iamport(request): 38 | imp_key = request.config.getoption("--imp-key") 39 | imp_secret = request.config.getoption("--imp-secret") 40 | client = AsyncIamport(imp_key=imp_key, imp_secret=imp_secret) 41 | # client.get_session() 42 | yield client 43 | await client.close_session() 44 | -------------------------------------------------------------------------------- /tests/test_cancel.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from async_iamport import HttpError, ResponseError 4 | 5 | 6 | @pytest.mark.asyncio 7 | async def test_cancel(iamport): 8 | with pytest.raises(TypeError): 9 | await iamport.cancel(imp_uid="nothing") 10 | with pytest.raises(ResponseError): 11 | await iamport.cancel("reason", imp_uid="nothing") 12 | try: 13 | await iamport.cancel("reason", imp_uid="nothing") 14 | except ResponseError as e: 15 | assert e.code == 1 16 | assert e.message == "취소할 결제건이 존재하지 않습니다." 17 | 18 | 19 | @pytest.mark.asyncio 20 | async def test_partial_cancel(iamport): 21 | try: 22 | await iamport.cancel("reason", imp_uid="nothing", amount=100) 23 | except ResponseError as e: 24 | assert e.code == 1 25 | assert e.message == "취소할 결제건이 존재하지 않습니다." 26 | 27 | 28 | @pytest.mark.asyncio 29 | async def test_cancel_by_merchant_uid(iamport): 30 | payload = { 31 | "merchant_uid": "any-merchant_uid", 32 | "reason": "any-reason", 33 | } 34 | 35 | try: 36 | await iamport.cancel(**payload) 37 | except ResponseError as e: 38 | assert e.code == 1 39 | assert e.message == "취소할 결제건이 존재하지 않습니다." 40 | 41 | 42 | @pytest.mark.asyncio 43 | async def test_cancel_without_merchant_uid(iamport): 44 | payload = { 45 | "merchant_uid": None, 46 | "reason": "any-reason", 47 | } 48 | 49 | try: 50 | await iamport.cancel(**payload) 51 | except KeyError as e: 52 | assert "merchant_uid or imp_uid is required" in str(e) 53 | 54 | 55 | @pytest.mark.asyncio 56 | async def test_cancel_by_merchant_uid_with_kwargs(iamport): 57 | payload = { 58 | "merchant_uid": "any-merchant_uid", 59 | "reason": "any-reason", 60 | "amount": 1234, 61 | } 62 | 63 | try: 64 | await iamport.cancel(**payload) 65 | except ResponseError as e: 66 | assert e.code == 1 67 | assert e.message == "취소할 결제건이 존재하지 않습니다." 68 | 69 | 70 | @pytest.mark.asyncio 71 | async def test_cancel_by_imp_uid(iamport): 72 | payload = { 73 | "imp_uid": "any-imp_uid", 74 | "reason": "any-reason", 75 | } 76 | 77 | try: 78 | await iamport.cancel(**payload) 79 | except ResponseError as e: 80 | assert e.code == 1 81 | assert e.message == "취소할 결제건이 존재하지 않습니다." 82 | -------------------------------------------------------------------------------- /tests/test_certification.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | import async_iamport 4 | 5 | 6 | @pytest.mark.asyncio 7 | async def test_find_certification(iamport): 8 | imp_uid = "imp_12341234" 9 | 10 | with pytest.raises(async_iamport.HttpError) as e: 11 | await iamport.find_certification(imp_uid) 12 | assert "인증결과가 존재하지 않습니다." == e.message 13 | 14 | with pytest.raises(async_iamport.HttpError) as e: 15 | await iamport.cancel_certification(imp_uid) 16 | assert "인증결과가 존재하지 않습니다." == e.message 17 | -------------------------------------------------------------------------------- /tests/test_client.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | import async_iamport 4 | 5 | 6 | @pytest.mark.asyncio 7 | async def test_init_otp_certification(iamport): 8 | user_info = { 9 | "name": "김유저", 10 | "phone": "010-1234-1234", 11 | "birth": "2000-10-10", 12 | "gender_digit": "1", 13 | "carrier": "SKT", 14 | "is_mvno": False, 15 | "company": "coop", 16 | } 17 | 18 | with pytest.raises(async_iamport.HttpError) as e: 19 | await iamport.init_otp_certification(**user_info) 20 | assert e.code == 400 21 | 22 | 23 | @pytest.mark.asyncio 24 | async def test_confirm_otp_certification(iamport): 25 | payload = {"imp_uid": "123456", "otp": "123456"} 26 | with pytest.raises(async_iamport.HttpError) as e: 27 | await iamport.confirm_otp_certification(**payload) 28 | assert e.code == 400 29 | 30 | 31 | @pytest.mark.asyncio 32 | async def test_adjust_prepare_amount(iamport): 33 | payload = {"merchant_uid": "123456", "amount": "123456"} 34 | with pytest.raises(async_iamport.HttpError) as e: 35 | await iamport.adjust_prepare_amount(**payload) 36 | assert e.code == 400 37 | -------------------------------------------------------------------------------- /tests/test_customer_create.py: -------------------------------------------------------------------------------- 1 | import async_iamport 2 | import pytest 3 | 4 | 5 | @pytest.mark.asyncio 6 | async def test_customer_create(iamport): 7 | # Without 'card_number' 8 | 9 | payload_full = { 10 | "customer_uid": "customer_1234", 11 | "expiry": "2019-03", 12 | "birth": "500203", 13 | "card_number": "4092-0230-1234-1234", 14 | } 15 | 16 | with pytest.raises(async_iamport.ResponseError) as e: 17 | await iamport.customer_create(**payload_full) 18 | assert e.code == -1 19 | assert "카드정보 인증 및 빌키 발급에 실패하였습니다." in e.message 20 | -------------------------------------------------------------------------------- /tests/test_customer_get.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | import async_iamport 4 | 5 | 6 | @pytest.mark.asyncio 7 | async def test_customer_get(iamport): 8 | customer_uid = "000000" 9 | with pytest.raises(async_iamport.ResponseError) as e: 10 | await iamport.customer_get(customer_uid) 11 | assert "요청하신 customer_uid(000000)로 등록된 정보를 찾을 수 없습니다." == e.message 12 | -------------------------------------------------------------------------------- /tests/test_find.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | import async_iamport 4 | 5 | 6 | @pytest.mark.asyncio 7 | async def test_find(iamport): 8 | with pytest.raises(KeyError): 9 | await iamport.find() 10 | with pytest.raises(async_iamport.HttpError): 11 | await iamport.find(imp_uid="test") 12 | with pytest.raises(async_iamport.HttpError): 13 | await iamport.find(merchant_uid="âàáaā") 14 | -------------------------------------------------------------------------------- /tests/test_find_with_status.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | import async_iamport 4 | 5 | 6 | @pytest.mark.asyncio 7 | async def test_find_with_status(iamport): 8 | try: 9 | await iamport.find_by_merchant_uid(merchant_uid="1234qwer", status="cancelled") 10 | except async_iamport.HttpError as e: 11 | assert e.code == 404 12 | 13 | res = await iamport.find_by_merchant_uid(merchant_uid="1234qwer") 14 | assert res["merchant_uid"] == "1234qwer" 15 | 16 | res = await iamport.find_by_merchant_uid(merchant_uid="1234qwer", status="paid") 17 | assert res["merchant_uid"] == "1234qwer" 18 | -------------------------------------------------------------------------------- /tests/test_is_paid.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | import async_iamport 4 | 5 | 6 | @pytest.mark.asyncio 7 | async def test_is_paid_with_response(iamport): 8 | mocked_response = { 9 | "status": "paid", 10 | "amount": 1000, 11 | } 12 | assert True is await iamport.is_paid( 13 | amount=1000, response=mocked_response, merchant_uid="test" 14 | ) 15 | 16 | 17 | @pytest.mark.asyncio 18 | async def test_is_paid_without_response(iamport): 19 | assert False is await iamport.is_paid(amount=1000, merchant_uid="qwer1234") 20 | -------------------------------------------------------------------------------- /tests/test_pay_again.py: -------------------------------------------------------------------------------- 1 | import async_iamport 2 | import pytest 3 | 4 | 5 | @pytest.mark.asyncio 6 | async def test_pay_again(iamport): 7 | payload_full = { 8 | "customer_uid": "00000000", 9 | "merchant_uid": "1234qwer", 10 | "amount": 5000, 11 | } 12 | 13 | try: 14 | await iamport.pay_again(**payload_full) 15 | except async_iamport.ResponseError as e: 16 | assert e.code == -1 17 | -------------------------------------------------------------------------------- /tests/test_pay_foreign.py: -------------------------------------------------------------------------------- 1 | import async_iamport 2 | import pytest 3 | 4 | 5 | @pytest.mark.asyncio 6 | async def test_pay_foreign(iamport): 7 | payload = { 8 | "merchant_uid": "uid", 9 | "amount": 100, 10 | "card_number": "card-number", 11 | } 12 | 13 | payload.update( 14 | { 15 | "expiry": "2016-08", 16 | } 17 | ) 18 | 19 | try: 20 | await iamport.pay_foreign(**payload) 21 | except async_iamport.ResponseError as e: 22 | assert e.code == -1 23 | -------------------------------------------------------------------------------- /tests/test_pay_onetime.py: -------------------------------------------------------------------------------- 1 | import random 2 | import string 3 | 4 | import async_iamport 5 | import pytest 6 | 7 | 8 | @pytest.mark.asyncio 9 | async def test_pay_onetime(iamport): 10 | merchant_uid = "".join( 11 | random.choice(string.ascii_uppercase + string.digits) for _ in range(10) 12 | ) 13 | 14 | merchant_uid = "".join( 15 | random.choice(string.ascii_uppercase + string.digits) for _ in range(10) 16 | ) 17 | 18 | payload_full = { 19 | "merchant_uid": merchant_uid, 20 | "amount": 5000, 21 | "card_number": "4092-0230-1234-1234", 22 | "expiry": "2019-03", 23 | "birth": "500203", 24 | "pwd_2digit": "19", 25 | } 26 | 27 | try: 28 | await iamport.pay_onetime(**payload_full) 29 | except async_iamport.ResponseError as e: 30 | assert e.code == -1 31 | assert "카드정보 인증에 실패하였습니다." in e.message 32 | -------------------------------------------------------------------------------- /tests/test_pay_schedule.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | import async_iamport 4 | import pytest 5 | 6 | 7 | @pytest.mark.asyncio 8 | async def test_pay_schedule(iamport): 9 | schedule_at = int(time.time() + 1000) 10 | payload_full = { 11 | "customer_uid": "00000000", 12 | "schedules": [ 13 | { 14 | "merchant_uid": "pay_schedule_%s" % str(time.time()), 15 | "schedule_at": schedule_at, 16 | "amount": 5000, 17 | "name": "주문명", 18 | "buyer_name": "주문자명", 19 | "buyer_email": "주문자 Email주소", 20 | "buyer_tel": "주문자 전화번호", 21 | "buyer_addr": "주문자 주소", 22 | "buyer_postcode": "주문자 우편번호", 23 | }, 24 | ], 25 | } 26 | 27 | try: 28 | await iamport.pay_schedule(**payload_full) 29 | except async_iamport.ResponseError as e: 30 | assert e.code == 1 31 | assert "등록된 고객정보가 없습니다." in e.message 32 | -------------------------------------------------------------------------------- /tests/test_pay_unschedule.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | import async_iamport 4 | import pytest 5 | 6 | 7 | @pytest.mark.asyncio 8 | async def test_pay_unschedule(iamport): 9 | payload_full = { 10 | "customer_uid": "00000000", 11 | "merchant_uid": "pay_unschedule_%s" % str(time.time()), 12 | } 13 | 14 | try: 15 | await iamport.pay_unschedule(**payload_full) 16 | except async_iamport.ResponseError as e: 17 | assert e.code == 1 18 | assert "취소할 예약결제 기록이 존재하지 않습니다." in e.message 19 | -------------------------------------------------------------------------------- /tests/test_prepare.py: -------------------------------------------------------------------------------- 1 | import random 2 | import string 3 | 4 | import pytest 5 | 6 | 7 | @pytest.mark.asyncio 8 | async def test_prepare(iamport): 9 | amount = 12000 10 | mid = "".join( 11 | random.choice(string.ascii_uppercase + string.digits) for _ in range(10) 12 | ) 13 | result = await iamport.prepare(merchant_uid=mid, amount=amount) 14 | assert result["amount"] == amount 15 | assert result["merchant_uid"] == mid 16 | 17 | result = await iamport.prepare_validate(merchant_uid=mid, amount=amount) 18 | assert result 19 | -------------------------------------------------------------------------------- /tests/test_token_reuse.py: -------------------------------------------------------------------------------- 1 | import arrow 2 | import pytest 3 | 4 | 5 | @pytest.mark.asyncio 6 | async def test_token_renewed_when_expire_is_under_60s(iamport): 7 | """ 8 | given 9 | iamport client with new token 10 | when 11 | set token_expire < 60s 12 | then 13 | token expire is renewed as token set again 14 | """ 15 | await iamport._get_token() 16 | pre_token_expire = iamport.token_expire 17 | now = arrow.utcnow() 18 | iamport.token_expire = now.shift(seconds=30) 19 | await iamport._get_token() 20 | post_token_expire = iamport.token_expire 21 | assert pre_token_expire == post_token_expire 22 | --------------------------------------------------------------------------------