├── bluetooth-python ├── requirements.txt └── src │ ├── logger.py │ ├── bluetooth.py │ ├── main.py │ └── stream_deck.py ├── DistributionTool ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ └── test.yml ├── com.sobolevn.bluetooth.sdPlugin ├── action │ └── images │ │ ├── icon.png │ │ ├── icon@2x.png │ │ ├── action-0-icon.png │ │ ├── action-0-icon@2x.png │ │ ├── bluetooth-active.png │ │ ├── bluetooth-inactive.png │ │ ├── bluetooth-active@2x.png │ │ └── bluetooth-inactive@2x.png ├── previews │ ├── 1-preview.png │ └── 2-preview.png └── manifest.json ├── .editorconfig ├── Makefile ├── pyproject.toml ├── LICENSE ├── setup.cfg ├── README.md ├── .gitignore └── poetry.lock /bluetooth-python/requirements.txt: -------------------------------------------------------------------------------- 1 | websockets==11.0.3 2 | -------------------------------------------------------------------------------- /DistributionTool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android7770/reposted/HEAD/DistributionTool -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: wemake-services 4 | -------------------------------------------------------------------------------- /com.sobolevn.bluetooth.sdPlugin/action/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android7770/reposted/HEAD/com.sobolevn.bluetooth.sdPlugin/action/images/icon.png -------------------------------------------------------------------------------- /com.sobolevn.bluetooth.sdPlugin/previews/1-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android7770/reposted/HEAD/com.sobolevn.bluetooth.sdPlugin/previews/1-preview.png -------------------------------------------------------------------------------- /com.sobolevn.bluetooth.sdPlugin/previews/2-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android7770/reposted/HEAD/com.sobolevn.bluetooth.sdPlugin/previews/2-preview.png -------------------------------------------------------------------------------- /com.sobolevn.bluetooth.sdPlugin/action/images/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android7770/reposted/HEAD/com.sobolevn.bluetooth.sdPlugin/action/images/icon@2x.png -------------------------------------------------------------------------------- /com.sobolevn.bluetooth.sdPlugin/action/images/action-0-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android7770/reposted/HEAD/com.sobolevn.bluetooth.sdPlugin/action/images/action-0-icon.png -------------------------------------------------------------------------------- /com.sobolevn.bluetooth.sdPlugin/action/images/action-0-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android7770/reposted/HEAD/com.sobolevn.bluetooth.sdPlugin/action/images/action-0-icon@2x.png -------------------------------------------------------------------------------- /com.sobolevn.bluetooth.sdPlugin/action/images/bluetooth-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android7770/reposted/HEAD/com.sobolevn.bluetooth.sdPlugin/action/images/bluetooth-active.png -------------------------------------------------------------------------------- /com.sobolevn.bluetooth.sdPlugin/action/images/bluetooth-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android7770/reposted/HEAD/com.sobolevn.bluetooth.sdPlugin/action/images/bluetooth-inactive.png -------------------------------------------------------------------------------- /com.sobolevn.bluetooth.sdPlugin/action/images/bluetooth-active@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android7770/reposted/HEAD/com.sobolevn.bluetooth.sdPlugin/action/images/bluetooth-active@2x.png -------------------------------------------------------------------------------- /com.sobolevn.bluetooth.sdPlugin/action/images/bluetooth-inactive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android7770/reposted/HEAD/com.sobolevn.bluetooth.sdPlugin/action/images/bluetooth-inactive@2x.png -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: pip 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "02:00" 8 | open-pull-requests-limit: 10 9 | 10 | - package-ecosystem: github-actions 11 | directory: "/" 12 | schedule: 13 | interval: daily 14 | time: "02:00" 15 | open-pull-requests-limit: 10 16 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Check http://editorconfig.org for more information 2 | # This is the main config file for this project: 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | end_of_line = lf 9 | indent_style = space 10 | insert_final_newline = true 11 | indent_size = 2 12 | 13 | [*.py] 14 | indent_size = 4 15 | 16 | [Makefile] 17 | indent_style = tab 18 | -------------------------------------------------------------------------------- /bluetooth-python/src/logger.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from typing import Final, NoReturn 3 | 4 | logging.basicConfig(filename='bluetooth.plugin.log', level=logging.INFO) 5 | 6 | logger: Final = logging.getLogger('com.sobolevn.bluetooth') 7 | 8 | 9 | def fail(message: str) -> NoReturn: 10 | """Fails something with `RuntimeError` and logs an error message.""" 11 | logger.critical(message) 12 | raise RuntimeError(message) 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL:=/usr/bin/env bash 2 | 3 | .PHONY: python-dist 4 | python-dist: 5 | @rm -rf ./com.sobolevn.bluetooth.sdPlugin/dist/macos 6 | @pyinstaller \ 7 | --clean \ 8 | --noconfirm \ 9 | --dist com.sobolevn.bluetooth.sdPlugin/dist/macos \ 10 | bluetooth-python/src/main.py 11 | 12 | .PHONY: plugin 13 | plugin: 14 | @rm -rf ./Release 15 | @mkdir ./Release 16 | @./DistributionTool -b -i ./com.sobolevn.bluetooth.sdPlugin -o ./Release 17 | 18 | .PHONY: build 19 | build: python-dist plugin 20 | 21 | .PHONY: lint 22 | lint: 23 | poetry run mypy bluetooth-python 24 | poetry run flake8 bluetooth-python 25 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "bluetooth-streamdeck-plugin" 3 | # Must match `manifest.json` 4 | version = "1.1.2" 5 | description = "This is not on PyPI" 6 | authors = ["sobolevn "] 7 | license = "MIT" 8 | 9 | [tool.poetry.dependencies] 10 | python = "3.9.x" 11 | 12 | [tool.poetry.dev-dependencies] 13 | wemake-python-styleguide = "^0.17" 14 | mypy = "^1.3" 15 | nitpick = "^0.32.0" 16 | 17 | [build-system] 18 | requires = ["poetry-core>=1.5.0"] 19 | build-backend = "poetry.core.masonry.api" 20 | 21 | 22 | [tool.nitpick] 23 | style = "https://raw.githubusercontent.com/wemake-services/wemake-python-styleguide/master/styles/nitpick-style-wemake.toml" 24 | -------------------------------------------------------------------------------- /com.sobolevn.bluetooth.sdPlugin/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "Actions": [ 3 | { 4 | "Icon": "action/images/action-0-icon", 5 | "Name": "Bluetooth Switcher", 6 | "States": [ 7 | { 8 | "Image": "action/images/bluetooth-inactive" 9 | }, 10 | { 11 | "Image": "action/images/bluetooth-active" 12 | } 13 | ], 14 | "Tooltip": "Bluetooth Switcher", 15 | "UUID": "com.sobolevn.bluetooth.action" 16 | } 17 | ], 18 | "SDKVersion": 2, 19 | "Author": "sobolevn", 20 | "Name": "Bluetooth Switcher", 21 | "Description": "Shows your Bluetooth status and allows to toggle it", 22 | "Icon": "action/images/icon", 23 | "URL": "https://github.com/sobolevn/bluetooth-streamdeck-plugin", 24 | "Version": "1.1.2", 25 | "OS": [ 26 | { 27 | "Platform": "mac", 28 | "MinimumVersion": "13.0" 29 | } 30 | ], 31 | "Software": { 32 | "MinimumVersion": "6.2" 33 | }, 34 | "CodePathMac": "dist/macos/main/main" 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright 2022, Nikita Sobolev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | workflow_dispatch: 9 | 10 | concurrency: 11 | group: ${{ github.head_ref || github.run_id }} 12 | cancel-in-progress: true 13 | 14 | jobs: 15 | build: 16 | runs-on: ubuntu-latest 17 | strategy: 18 | matrix: 19 | python-version: ['3.9'] 20 | 21 | steps: 22 | - uses: actions/checkout@v3 23 | - name: Set up Python ${{ matrix.python-version }} 24 | uses: actions/setup-python@v4 25 | with: 26 | python-version: ${{ matrix.python-version }} 27 | 28 | - name: Install poetry 29 | run: | 30 | curl -sSL \ 31 | "https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py" | python 32 | 33 | # Adding `poetry` to `$PATH`: 34 | echo "$HOME/.poetry/bin" >> $GITHUB_PATH 35 | 36 | - name: Install dependencies 37 | run: | 38 | poetry config virtualenvs.in-project true 39 | poetry run pip install -U pip 40 | poetry install 41 | 42 | - name: Run lint 43 | run: make lint 44 | -------------------------------------------------------------------------------- /bluetooth-python/src/bluetooth.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Callable, Dict 2 | 3 | import objc 4 | from logger import fail 5 | 6 | bundle = objc.loadBundle( 7 | 'IOBluetooth', 8 | globals(), # noqa: WPS421 9 | bundle_path=objc.pathForFramework( 10 | '/System/Library/Frameworks/IOBluetooth.framework', 11 | ), 12 | ) 13 | if not bundle: 14 | fail('Failed to load IOBluetooth framework') 15 | 16 | # Request handles to functions: 17 | function_specs = [ 18 | ('IOBluetoothPreferenceGetControllerPowerState', b'oI'), 19 | ('IOBluetoothPreferenceSetControllerPowerState', b'vI'), 20 | ] 21 | namespace: Dict[str, Any] = {} 22 | objc.loadBundleFunctions(bundle, namespace, function_specs) 23 | 24 | # Did we get everything we need? 25 | for function_name, _ in function_specs: 26 | if function_name not in namespace: 27 | fail('Failed to load: {0}'.format(function_name)) 28 | 29 | _bs_getter: Callable[[], int] = namespace[function_specs[0][0]] 30 | _bs_setter: Callable[[int], int] = namespace[function_specs[1][0]] 31 | 32 | 33 | def toggle_bluetooth_state() -> int: 34 | """Turn on if turned off and vice a versa.""" 35 | current_state = _bs_getter() 36 | new_state = _next_state(current_state) 37 | _bs_setter(new_state) 38 | return new_state 39 | 40 | 41 | def get_bluetooth_state() -> int: 42 | """Returns 0 or 1 state. Where 1 is 'turned on'.""" 43 | return _bs_getter() 44 | 45 | 46 | def _next_state(current: int) -> int: 47 | if current == 1: 48 | return 0 49 | return 1 50 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | # All configuration for plugins and other utils is defined here. 2 | # Read more about `setup.cfg`: 3 | # https://docs.python.org/3/distutils/configfile.html 4 | 5 | 6 | [flake8] 7 | format = wemake 8 | show-source = True 9 | doctests = True 10 | statistics = False 11 | 12 | # darglint configuration: 13 | # https://github.com/terrencepreilly/darglint 14 | strictness = long 15 | docstring-style = numpy 16 | 17 | # Plugins: 18 | max-complexity = 6 19 | max-line-length = 80 20 | 21 | ignore = 22 | S101, 23 | D100, 24 | D401, 25 | NIP102 26 | 27 | 28 | [isort] 29 | # isort configuration: 30 | # https://github.com/timothycrosley/isort/wiki/isort-Settings 31 | include_trailing_comma = true 32 | use_parentheses = true 33 | # See https://github.com/timothycrosley/isort#multi-line-output-modes 34 | multi_line_output = 3 35 | line_length = 80 36 | 37 | 38 | [mypy] 39 | # mypy configurations: http://bit.ly/2zEl9WI 40 | enable_error_code = 41 | truthy-bool, 42 | unused-awaitable, 43 | redundant-expr 44 | 45 | allow_redefinition = False 46 | check_untyped_defs = True 47 | disallow_any_generics = True 48 | disallow_untyped_calls = True 49 | disallow_subclassing_any = True 50 | follow_imports = silent 51 | ignore_errors = False 52 | ignore_missing_imports = True 53 | implicit_reexport = False 54 | strict_optional = True 55 | strict_equality = True 56 | no_implicit_optional = True 57 | local_partial_types = True 58 | warn_no_return = True 59 | warn_unused_ignores = True 60 | warn_redundant_casts = True 61 | warn_return_any = True 62 | warn_unused_configs = True 63 | warn_unreachable = True 64 | -------------------------------------------------------------------------------- /bluetooth-python/src/main.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import asyncio 3 | from typing import Protocol 4 | 5 | from logger import logger 6 | from stream_deck import StreamDeckExchange 7 | 8 | 9 | class _ParsedArgs(Protocol): 10 | port: int 11 | plugin_uuid: str 12 | register_event: str 13 | 14 | 15 | def _parse_cli_args() -> _ParsedArgs: 16 | """ 17 | Parse args passed by SteamDeck. 18 | 19 | They'll be set by the Stream Deck desktop software 20 | when it launches our plugin. 21 | """ 22 | parser = argparse.ArgumentParser() 23 | 24 | parser.add_argument('-port', type=int, required=True) 25 | parser.add_argument( 26 | '-pluginUUID', 27 | dest='plugin_uuid', 28 | type=str, 29 | required=True, 30 | ) 31 | parser.add_argument( 32 | '-registerEvent', 33 | dest='register_event', 34 | type=str, 35 | required=True, 36 | ) 37 | 38 | # Ignore unknown args in case a Stream Deck update 39 | # adds optional flags later. 40 | (known_args, _) = parser.parse_known_args() 41 | return known_args 42 | 43 | 44 | if __name__ == '__main__': 45 | logger.info('Starting') 46 | args = _parse_cli_args() 47 | logger.info('Got args: {0}'.format(args)) 48 | 49 | loop = asyncio.get_event_loop() 50 | exchange = StreamDeckExchange() 51 | 52 | try: 53 | loop.run_until_complete( 54 | exchange.start( 55 | port=args.port, 56 | plugin_uuid=args.plugin_uuid, 57 | register_event=args.register_event, 58 | ), 59 | ) 60 | except Exception as exc: 61 | logger.critical(exc) 62 | raise 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Elgato StreamDeck Bluetooth Plugin 2 | 3 | [![test](https://github.com/sobolevn/bluetooth-streamdeck-plugin/actions/workflows/test.yml/badge.svg)](https://github.com/sobolevn/bluetooth-streamdeck-plugin/actions/workflows/test.yml) 4 | 5 | Allows you to toggle your bluetooth state from the StreamDeck. 6 | 7 | 8 | ## Installation 9 | 10 | Right now this tool **only works on macOS**. 11 | Windows support is welcome, but I don't want to do it myself :) 12 | 13 | To install, please: 14 | 1. Download `com.sobolevn.bluetooth.streamDeckPlugin` from [releases](https://github.com/sobolevn/bluetooth-streamdeck-plugin/releases) 15 | 2. Double click on this file, StreamDeck will promt you about further installation 16 | 17 | 18 | ## Development 19 | 20 | ### Setting up your venv 21 | 22 | Install latest `3.9.x` python via: 23 | 24 | ```bash 25 | PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 3.9 26 | ``` 27 | 28 | Then create and activate `venv` using this version of python. 29 | Then run `pip install -r bluetooth-python/requirements.txt` 30 | 31 | ### Creating an `.exe` file from Python's source 32 | 33 | We use `pyinstaller` to do that. 34 | Make sure you run `pip install pyinstaller` in your `venv`. 35 | It is not listed 36 | And then run `make python-dist` 37 | 38 | ### Creating a StreamDeck plugin 39 | 40 | We bundle `DistributionTool` with this plugin for better DX ([docs](https://developer.elgato.com/documentation/stream-deck/sdk/packaging/)). 41 | 42 | Run `make plugin` to create a release after python dist is created. 43 | 44 | ### CI 45 | 46 | We use `poetry` and `pyproject.toml` to specify dev-only dependencies. 47 | This is required because we use `pyinstaller` 48 | and we don't want to polute `requirements.txt` and production env. 49 | 50 | 51 | ## Acknowledgements 52 | 53 | Code: 54 | 55 | - https://github.com/ChrisRegado/streamdeck-googlemeet 56 | - https://gist.github.com/rnaveiras/2224859 57 | - https://github.com/alvaroiramirez/SensorTile 58 | 59 | Icons: 60 | 61 | - https://iconarchive.com/show/papirus-status-icons-by-papirus-team.html 62 | - https://www.iconsdb.com/white-icons/bluetooth-icon.html 63 | 64 | DistributionTool: 65 | 66 | - https://developer.elgato.com/documentation/stream-deck/sdk/packaging/ 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #### joe made this: http://goel.io/joe 2 | #### python #### 3 | # Byte-compiled / optimized / DLL files 4 | .pytest_cache 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | pip-wheel-metadata/ 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | local_settings.py 59 | 60 | # Flask stuff: 61 | instance/ 62 | .webassets-cache 63 | 64 | # Scrapy stuff: 65 | .scrapy 66 | 67 | # Sphinx documentation 68 | docs/_build/ 69 | 70 | # PyBuilder 71 | target/ 72 | 73 | # Jupyter Notebook 74 | .ipynb_checkpoints 75 | 76 | # pyenv 77 | .python-version 78 | 79 | # celery beat schedule file 80 | celerybeat-schedule 81 | 82 | # SageMath parsed files 83 | *.sage.py 84 | 85 | # Environments 86 | .env 87 | .venv 88 | env/ 89 | venv/ 90 | ENV/ 91 | 92 | # Spyder project settings 93 | .spyderproject 94 | .spyproject 95 | 96 | # Rope project settings 97 | .ropeproject 98 | 99 | # mkdocs documentation 100 | /site 101 | 102 | # mypy 103 | .mypy_cache/ 104 | #### macos #### 105 | # General 106 | *.DS_Store 107 | .AppleDouble 108 | .LSOverride 109 | 110 | # Icon must end with two \r 111 | Icon 112 | 113 | 114 | # Thumbnails 115 | ._* 116 | 117 | # Files that might appear in the root of a volume 118 | .DocumentRevisions-V100 119 | .fseventsd 120 | .Spotlight-V100 121 | .TemporaryItems 122 | .Trashes 123 | .VolumeIcon.icns 124 | .com.apple.timemachine.donotpresent 125 | 126 | # Directories potentially created on remote AFP share 127 | .AppleDB 128 | .AppleDesktop 129 | Network Trash Folder 130 | Temporary Items 131 | .apdisk 132 | #### windows #### 133 | # Windows thumbnail cache files 134 | Thumbs.db 135 | ehthumbs.db 136 | ehthumbs_vista.db 137 | 138 | # Dump file 139 | *.stackdump 140 | 141 | # Folder config file 142 | Desktop.ini 143 | 144 | # Recycle Bin used on file shares 145 | $RECYCLE.BIN/ 146 | 147 | # Windows Installer files 148 | *.cab 149 | *.msi 150 | *.msm 151 | *.msp 152 | 153 | # Windows shortcuts 154 | *.lnk 155 | #### linux #### 156 | *~ 157 | 158 | # temporary files which can be created if a process still has a handle open of a deleted file 159 | .fuse_hidden* 160 | 161 | # KDE directory preferences 162 | .directory 163 | 164 | # Linux trash folder which might appear on any partition or disk 165 | .Trash-* 166 | 167 | # .nfs files are created when an open file is removed but is still being accessed 168 | .nfs* 169 | #### jetbrains #### 170 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 171 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 172 | 173 | # User-specific stuff: 174 | .idea/ 175 | 176 | ## File-based project format: 177 | *.iws 178 | 179 | ## Plugin-specific files: 180 | 181 | # IntelliJ 182 | /out/ 183 | 184 | # mpeltonen/sbt-idea plugin 185 | .idea_modules/ 186 | 187 | # JIRA plugin 188 | atlassian-ide-plugin.xml 189 | 190 | # Cursive Clojure plugin 191 | .idea/replstate.xml 192 | 193 | # Crashlytics plugin (for Android Studio and IntelliJ) 194 | com_crashlytics_export_strings.xml 195 | crashlytics.properties 196 | crashlytics-build.properties 197 | fabric.properties 198 | 199 | ### Custom ### 200 | ex.py 201 | experiments/ 202 | .vscode/tags 203 | .pyre 204 | .pytype 205 | build/ 206 | Release/ 207 | -------------------------------------------------------------------------------- /bluetooth-python/src/stream_deck.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import json 3 | from typing import Any, Dict, Final, Optional, Tuple, Union, final 4 | 5 | import bluetooth 6 | from logger import logger 7 | from websockets.legacy.client import WebSocketClientProtocol 8 | from websockets.legacy.client import connect as ws_connect 9 | 10 | _WS_URI_TEMPLATE: Final = 'ws://localhost:{port}' 11 | _WS_PAYLOAD: Final = '{"event": "willAppear"}' 12 | _JsonType = Dict[str, Any] 13 | 14 | 15 | @final 16 | class StreamDeckExchange(object): 17 | """Websocket event exchange with Elgato StreamDeck.""" 18 | 19 | def __init__(self) -> None: 20 | """Nothing fancy here.""" 21 | self._websocket: Optional[WebSocketClientProtocol] = None 22 | self._context: Optional[str] = None 23 | self._controller = _BluetoothMessageController() 24 | self._bluetooth_state: Optional[int] = None 25 | 26 | async def start( 27 | self, 28 | port: int, 29 | register_event: str, 30 | plugin_uuid: str, 31 | ) -> None: 32 | """Run websocket and listen for events.""" 33 | self._websocket = await ws_connect(_WS_URI_TEMPLATE.format(port=port)) 34 | logger.info('Websocket connection is created on port {0}'.format(port)) 35 | 36 | # Complete the mandatory Stream Deck Plugin registration procedure: 37 | await self._send_message({ 38 | 'event': register_event, 39 | 'uuid': plugin_uuid, 40 | }) 41 | logger.info('Plugin registration is succesful') 42 | 43 | asyncio.create_task( # type: ignore[unused-awaitable] 44 | self._update_periodically(0.1), 45 | ) 46 | 47 | try: # noqa: WPS501 48 | # This is an infinite loop until the connection dies: 49 | await self._message_receive_loop() 50 | finally: 51 | await self._websocket.close() 52 | 53 | async def _update_periodically(self, period: float) -> None: 54 | # Technically, this loop never ends, but that's the whole point. 55 | while True: # noqa: WPS457 56 | await asyncio.sleep(period) 57 | await self._process_inbound_message(_WS_PAYLOAD) 58 | 59 | async def _message_receive_loop(self) -> None: 60 | """ 61 | Waiting for and processing inbound websocket messages. 62 | 63 | Until the connection dies. 64 | """ 65 | assert self._websocket is not None, 'Please, call `.start()` first' 66 | async for message in self._websocket: 67 | await self._process_inbound_message(message) 68 | 69 | async def _process_inbound_message( 70 | self, 71 | message: Union[str, bytes], 72 | ) -> None: 73 | if isinstance(message, bytes): 74 | message = message.decode('utf-8') 75 | 76 | # You can log the message here, but it take a lot of space on disk: 77 | parsed = json.loads(message) 78 | 79 | self._maybe_store_context(parsed) 80 | reply = self._controller.handle_event(parsed, self._context) 81 | if reply is not None and self._bluetooth_state != reply[0]: 82 | self._bluetooth_state = reply[0] 83 | await self._send_message(reply[1]) 84 | 85 | async def _send_message(self, payload: _JsonType) -> None: 86 | assert self._websocket is not None, 'Please, call `.start()` first' 87 | 88 | await self._websocket.send(json.dumps(payload)) 89 | logger.info('Sent payload: {0}'.format(payload)) 90 | 91 | def _maybe_store_context(self, payload: _JsonType) -> None: 92 | context = payload.get('context') 93 | if context is not None and context != self._context: 94 | self._context = context 95 | logger.info('Got new plugin context: {0}'.format(context)) 96 | 97 | 98 | @final 99 | class _BluetoothMessageController(object): 100 | def handle_event( 101 | self, 102 | payload: _JsonType, 103 | context: Optional[str], 104 | ) -> Optional[Tuple[int, _JsonType]]: 105 | event_type = payload['event'] 106 | if event_type == 'keyUp': 107 | self._handle_key_up() 108 | elif event_type == 'willAppear': 109 | return self._handle_will_appear(context) 110 | return None 111 | 112 | def _handle_key_up(self) -> None: 113 | bluetooth.toggle_bluetooth_state() 114 | 115 | def _handle_will_appear( 116 | self, 117 | context: Optional[str], 118 | ) -> Optional[Tuple[int, _JsonType]]: 119 | if context is None: 120 | return None # We don't have a context yet to send a message. 121 | 122 | state = bluetooth.get_bluetooth_state() 123 | return state, { 124 | 'event': 'setState', 125 | 'context': context, 126 | 'payload': { 127 | 'state': state, 128 | }, 129 | } 130 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.5.0 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "astor" 5 | version = "0.8.1" 6 | description = "Read/rewrite/write Python ASTs" 7 | optional = false 8 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" 9 | files = [ 10 | {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, 11 | {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, 12 | ] 13 | 14 | [[package]] 15 | name = "attrs" 16 | version = "23.1.0" 17 | description = "Classes Without Boilerplate" 18 | optional = false 19 | python-versions = ">=3.7" 20 | files = [ 21 | {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, 22 | {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, 23 | ] 24 | 25 | [package.extras] 26 | cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] 27 | dev = ["attrs[docs,tests]", "pre-commit"] 28 | docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] 29 | tests = ["attrs[tests-no-zope]", "zope-interface"] 30 | tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] 31 | 32 | [[package]] 33 | name = "autorepr" 34 | version = "0.3.0" 35 | description = "Makes civilized __repr__, __str__, and __unicode__ methods" 36 | optional = false 37 | python-versions = "*" 38 | files = [ 39 | {file = "autorepr-0.3.0-py2-none-any.whl", hash = "sha256:c34567e4073630feb52d9c788fc198085e9e9de4817e3b93b7c4c534fc689f11"}, 40 | {file = "autorepr-0.3.0-py2.py3-none-any.whl", hash = "sha256:1d9010d14fb325d3961e3aa73692685563f97d6ba4a2f0f735329fb37422599c"}, 41 | {file = "autorepr-0.3.0.tar.gz", hash = "sha256:ef770b84793d5433e6bb893054973b8c7ce6b487274f9c3f734f678cae11e85e"}, 42 | ] 43 | 44 | [[package]] 45 | name = "bandit" 46 | version = "1.7.5" 47 | description = "Security oriented static analyser for python code." 48 | optional = false 49 | python-versions = ">=3.7" 50 | files = [ 51 | {file = "bandit-1.7.5-py3-none-any.whl", hash = "sha256:75665181dc1e0096369112541a056c59d1c5f66f9bb74a8d686c3c362b83f549"}, 52 | {file = "bandit-1.7.5.tar.gz", hash = "sha256:bdfc739baa03b880c2d15d0431b31c658ffc348e907fe197e54e0389dd59e11e"}, 53 | ] 54 | 55 | [package.dependencies] 56 | colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} 57 | GitPython = ">=1.0.1" 58 | PyYAML = ">=5.3.1" 59 | rich = "*" 60 | stevedore = ">=1.20.0" 61 | 62 | [package.extras] 63 | test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "tomli (>=1.1.0)"] 64 | toml = ["tomli (>=1.1.0)"] 65 | yaml = ["PyYAML"] 66 | 67 | [[package]] 68 | name = "cattrs" 69 | version = "22.2.0" 70 | description = "Composable complex class support for attrs and dataclasses." 71 | optional = false 72 | python-versions = ">=3.7" 73 | files = [ 74 | {file = "cattrs-22.2.0-py3-none-any.whl", hash = "sha256:bc12b1f0d000b9f9bee83335887d532a1d3e99a833d1bf0882151c97d3e68c21"}, 75 | {file = "cattrs-22.2.0.tar.gz", hash = "sha256:f0eed5642399423cf656e7b66ce92cdc5b963ecafd041d1b24d136fdde7acf6d"}, 76 | ] 77 | 78 | [package.dependencies] 79 | attrs = ">=20" 80 | exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} 81 | 82 | [[package]] 83 | name = "certifi" 84 | version = "2023.5.7" 85 | description = "Python package for providing Mozilla's CA Bundle." 86 | optional = false 87 | python-versions = ">=3.6" 88 | files = [ 89 | {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, 90 | {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, 91 | ] 92 | 93 | [[package]] 94 | name = "charset-normalizer" 95 | version = "3.1.0" 96 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 97 | optional = false 98 | python-versions = ">=3.7.0" 99 | files = [ 100 | {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, 101 | {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, 102 | {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, 103 | {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, 104 | {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, 105 | {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, 106 | {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, 107 | {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, 108 | {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, 109 | {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, 110 | {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, 111 | {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, 112 | {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, 113 | {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, 114 | {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, 115 | {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, 116 | {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, 117 | {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, 118 | {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, 119 | {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, 120 | {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, 121 | {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, 122 | {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, 123 | {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, 124 | {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, 125 | {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, 126 | {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, 127 | {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, 128 | {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, 129 | {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, 130 | {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, 131 | {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, 132 | {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, 133 | {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, 134 | {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, 135 | {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, 136 | {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, 137 | {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, 138 | {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, 139 | {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, 140 | {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, 141 | {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, 142 | {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, 143 | {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, 144 | {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, 145 | {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, 146 | {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, 147 | {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, 148 | {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, 149 | {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, 150 | {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, 151 | {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, 152 | {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, 153 | {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, 154 | {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, 155 | {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, 156 | {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, 157 | {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, 158 | {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, 159 | {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, 160 | {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, 161 | {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, 162 | {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, 163 | {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, 164 | {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, 165 | {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, 166 | {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, 167 | {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, 168 | {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, 169 | {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, 170 | {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, 171 | {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, 172 | {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, 173 | {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, 174 | {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, 175 | ] 176 | 177 | [[package]] 178 | name = "click" 179 | version = "8.1.3" 180 | description = "Composable command line interface toolkit" 181 | optional = false 182 | python-versions = ">=3.7" 183 | files = [ 184 | {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, 185 | {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, 186 | ] 187 | 188 | [package.dependencies] 189 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 190 | 191 | [[package]] 192 | name = "colorama" 193 | version = "0.4.6" 194 | description = "Cross-platform colored terminal text." 195 | optional = false 196 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 197 | files = [ 198 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 199 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 200 | ] 201 | 202 | [[package]] 203 | name = "configupdater" 204 | version = "3.1.1" 205 | description = "Parser like ConfigParser but for updating configuration files" 206 | optional = false 207 | python-versions = ">=3.6" 208 | files = [ 209 | {file = "ConfigUpdater-3.1.1-py2.py3-none-any.whl", hash = "sha256:805986dbeba317886c7a8d348b2e34986dc9e3128cd3761ecc35decbd372b286"}, 210 | {file = "ConfigUpdater-3.1.1.tar.gz", hash = "sha256:46f0c74d73efa723776764b43c9739f68052495dd3d734319c1d0eb58511f15b"}, 211 | ] 212 | 213 | [package.extras] 214 | testing = ["flake8", "pytest", "pytest-cov", "pytest-virtualenv", "pytest-xdist", "sphinx"] 215 | 216 | [[package]] 217 | name = "darglint" 218 | version = "1.8.1" 219 | description = "A utility for ensuring Google-style docstrings stay up to date with the source code." 220 | optional = false 221 | python-versions = ">=3.6,<4.0" 222 | files = [ 223 | {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, 224 | {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, 225 | ] 226 | 227 | [[package]] 228 | name = "dictdiffer" 229 | version = "0.9.0" 230 | description = "Dictdiffer is a library that helps you to diff and patch dictionaries." 231 | optional = false 232 | python-versions = "*" 233 | files = [ 234 | {file = "dictdiffer-0.9.0-py2.py3-none-any.whl", hash = "sha256:442bfc693cfcadaf46674575d2eba1c53b42f5e404218ca2c2ff549f2df56595"}, 235 | {file = "dictdiffer-0.9.0.tar.gz", hash = "sha256:17bacf5fbfe613ccf1b6d512bd766e6b21fb798822a133aa86098b8ac9997578"}, 236 | ] 237 | 238 | [package.extras] 239 | all = ["Sphinx (>=3)", "check-manifest (>=0.42)", "mock (>=1.3.0)", "numpy (>=1.13.0)", "numpy (>=1.15.0)", "numpy (>=1.18.0)", "numpy (>=1.20.0)", "pytest (==5.4.3)", "pytest (>=6)", "pytest-cov (>=2.10.1)", "pytest-isort (>=1.2.0)", "pytest-pycodestyle (>=2)", "pytest-pycodestyle (>=2.2.0)", "pytest-pydocstyle (>=2)", "pytest-pydocstyle (>=2.2.0)", "sphinx (>=3)", "sphinx-rtd-theme (>=0.2)", "tox (>=3.7.0)"] 240 | docs = ["Sphinx (>=3)", "sphinx-rtd-theme (>=0.2)"] 241 | numpy = ["numpy (>=1.13.0)", "numpy (>=1.15.0)", "numpy (>=1.18.0)", "numpy (>=1.20.0)"] 242 | tests = ["check-manifest (>=0.42)", "mock (>=1.3.0)", "pytest (==5.4.3)", "pytest (>=6)", "pytest-cov (>=2.10.1)", "pytest-isort (>=1.2.0)", "pytest-pycodestyle (>=2)", "pytest-pycodestyle (>=2.2.0)", "pytest-pydocstyle (>=2)", "pytest-pydocstyle (>=2.2.0)", "sphinx (>=3)", "tox (>=3.7.0)"] 243 | 244 | [[package]] 245 | name = "docutils" 246 | version = "0.20.1" 247 | description = "Docutils -- Python Documentation Utilities" 248 | optional = false 249 | python-versions = ">=3.7" 250 | files = [ 251 | {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, 252 | {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, 253 | ] 254 | 255 | [[package]] 256 | name = "dpath" 257 | version = "2.1.6" 258 | description = "Filesystem-like pathing and searching for dictionaries" 259 | optional = false 260 | python-versions = ">=3.7" 261 | files = [ 262 | {file = "dpath-2.1.6-py3-none-any.whl", hash = "sha256:31407395b177ab63ef72e2f6ae268c15e938f2990a8ecf6510f5686c02b6db73"}, 263 | {file = "dpath-2.1.6.tar.gz", hash = "sha256:f1e07c72e8605c6a9e80b64bc8f42714de08a789c7de417e49c3f87a19692e47"}, 264 | ] 265 | 266 | [[package]] 267 | name = "eradicate" 268 | version = "2.2.0" 269 | description = "Removes commented-out code." 270 | optional = false 271 | python-versions = "*" 272 | files = [ 273 | {file = "eradicate-2.2.0-py3-none-any.whl", hash = "sha256:751813c315a48ce7e3d0483410991015342d380a956e86e0265c61bfb875bcbc"}, 274 | {file = "eradicate-2.2.0.tar.gz", hash = "sha256:c329a05def6a4b558dab58bb1b694f5209706b7c99ba174d226dfdb69a5ba0da"}, 275 | ] 276 | 277 | [[package]] 278 | name = "exceptiongroup" 279 | version = "1.1.1" 280 | description = "Backport of PEP 654 (exception groups)" 281 | optional = false 282 | python-versions = ">=3.7" 283 | files = [ 284 | {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, 285 | {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, 286 | ] 287 | 288 | [package.extras] 289 | test = ["pytest (>=6)"] 290 | 291 | [[package]] 292 | name = "flake8" 293 | version = "4.0.1" 294 | description = "the modular source code checker: pep8 pyflakes and co" 295 | optional = false 296 | python-versions = ">=3.6" 297 | files = [ 298 | {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, 299 | {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, 300 | ] 301 | 302 | [package.dependencies] 303 | mccabe = ">=0.6.0,<0.7.0" 304 | pycodestyle = ">=2.8.0,<2.9.0" 305 | pyflakes = ">=2.4.0,<2.5.0" 306 | 307 | [[package]] 308 | name = "flake8-bandit" 309 | version = "3.0.0" 310 | description = "Automated security testing with bandit and flake8." 311 | optional = false 312 | python-versions = ">=3.6" 313 | files = [ 314 | {file = "flake8_bandit-3.0.0-py2.py3-none-any.whl", hash = "sha256:61b617f4f7cdaa0e2b1e6bf7b68afb2b619a227bb3e3ae00dd36c213bd17900a"}, 315 | {file = "flake8_bandit-3.0.0.tar.gz", hash = "sha256:54d19427e6a8d50322a7b02e1841c0a7c22d856975f3459803320e0e18e2d6a1"}, 316 | ] 317 | 318 | [package.dependencies] 319 | bandit = ">=1.7.3" 320 | flake8 = "*" 321 | flake8-polyfill = "*" 322 | pycodestyle = "*" 323 | 324 | [[package]] 325 | name = "flake8-broken-line" 326 | version = "0.5.0" 327 | description = "Flake8 plugin to forbid backslashes for line breaks" 328 | optional = false 329 | python-versions = ">=3.6,<4.0" 330 | files = [ 331 | {file = "flake8-broken-line-0.5.0.tar.gz", hash = "sha256:7c98de9dd1385b71e888709c7f2aee3f0514107ecb5875bc95d0c03392191c97"}, 332 | {file = "flake8_broken_line-0.5.0-py3-none-any.whl", hash = "sha256:daafb19b67eead0410ce7ba155d51a15b9d020ebe7630d87de9c2b93cedb6703"}, 333 | ] 334 | 335 | [package.dependencies] 336 | flake8 = ">=3.5,<6" 337 | 338 | [[package]] 339 | name = "flake8-bugbear" 340 | version = "22.12.6" 341 | description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." 342 | optional = false 343 | python-versions = ">=3.7" 344 | files = [ 345 | {file = "flake8-bugbear-22.12.6.tar.gz", hash = "sha256:4cdb2c06e229971104443ae293e75e64c6107798229202fbe4f4091427a30ac0"}, 346 | {file = "flake8_bugbear-22.12.6-py3-none-any.whl", hash = "sha256:b69a510634f8a9c298dfda2b18a8036455e6b19ecac4fe582e4d7a0abfa50a30"}, 347 | ] 348 | 349 | [package.dependencies] 350 | attrs = ">=19.2.0" 351 | flake8 = ">=3.0.0" 352 | 353 | [package.extras] 354 | dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "tox"] 355 | 356 | [[package]] 357 | name = "flake8-commas" 358 | version = "2.1.0" 359 | description = "Flake8 lint for trailing commas." 360 | optional = false 361 | python-versions = "*" 362 | files = [ 363 | {file = "flake8-commas-2.1.0.tar.gz", hash = "sha256:940441ab8ee544df564ae3b3f49f20462d75d5c7cac2463e0b27436e2050f263"}, 364 | {file = "flake8_commas-2.1.0-py2.py3-none-any.whl", hash = "sha256:ebb96c31e01d0ef1d0685a21f3f0e2f8153a0381430e748bf0bbbb5d5b453d54"}, 365 | ] 366 | 367 | [package.dependencies] 368 | flake8 = ">=2" 369 | 370 | [[package]] 371 | name = "flake8-comprehensions" 372 | version = "3.12.0" 373 | description = "A flake8 plugin to help you write better list/set/dict comprehensions." 374 | optional = false 375 | python-versions = ">=3.7" 376 | files = [ 377 | {file = "flake8_comprehensions-3.12.0-py3-none-any.whl", hash = "sha256:013234637ec7dfcb7cd2900578fb53c512f81db909cefe371c019232695c362d"}, 378 | {file = "flake8_comprehensions-3.12.0.tar.gz", hash = "sha256:419ef1a6e8de929203791a5e8ff5e3906caeba13eb3290eebdbf88a9078d502e"}, 379 | ] 380 | 381 | [package.dependencies] 382 | flake8 = ">=3.0,<3.2.0 || >3.2.0" 383 | 384 | [[package]] 385 | name = "flake8-debugger" 386 | version = "4.1.2" 387 | description = "ipdb/pdb statement checker plugin for flake8" 388 | optional = false 389 | python-versions = ">=3.7" 390 | files = [ 391 | {file = "flake8-debugger-4.1.2.tar.gz", hash = "sha256:52b002560941e36d9bf806fca2523dc7fb8560a295d5f1a6e15ac2ded7a73840"}, 392 | {file = "flake8_debugger-4.1.2-py3-none-any.whl", hash = "sha256:0a5e55aeddcc81da631ad9c8c366e7318998f83ff00985a49e6b3ecf61e571bf"}, 393 | ] 394 | 395 | [package.dependencies] 396 | flake8 = ">=3.0" 397 | pycodestyle = "*" 398 | 399 | [[package]] 400 | name = "flake8-docstrings" 401 | version = "1.7.0" 402 | description = "Extension for flake8 which uses pydocstyle to check docstrings" 403 | optional = false 404 | python-versions = ">=3.7" 405 | files = [ 406 | {file = "flake8_docstrings-1.7.0-py2.py3-none-any.whl", hash = "sha256:51f2344026da083fc084166a9353f5082b01f72901df422f74b4d953ae88ac75"}, 407 | {file = "flake8_docstrings-1.7.0.tar.gz", hash = "sha256:4c8cc748dc16e6869728699e5d0d685da9a10b0ea718e090b1ba088e67a941af"}, 408 | ] 409 | 410 | [package.dependencies] 411 | flake8 = ">=3" 412 | pydocstyle = ">=2.1" 413 | 414 | [[package]] 415 | name = "flake8-eradicate" 416 | version = "1.4.0" 417 | description = "Flake8 plugin to find commented out code" 418 | optional = false 419 | python-versions = ">=3.7,<4.0" 420 | files = [ 421 | {file = "flake8-eradicate-1.4.0.tar.gz", hash = "sha256:3088cfd6717d1c9c6c3ac45ef2e5f5b6c7267f7504d5a74b781500e95cb9c7e1"}, 422 | {file = "flake8_eradicate-1.4.0-py3-none-any.whl", hash = "sha256:e3bbd0871be358e908053c1ab728903c114f062ba596b4d40c852fd18f473d56"}, 423 | ] 424 | 425 | [package.dependencies] 426 | attrs = "*" 427 | eradicate = ">=2.0,<3.0" 428 | flake8 = ">=3.5,<6" 429 | 430 | [[package]] 431 | name = "flake8-isort" 432 | version = "4.2.0" 433 | description = "flake8 plugin that integrates isort ." 434 | optional = false 435 | python-versions = "*" 436 | files = [ 437 | {file = "flake8-isort-4.2.0.tar.gz", hash = "sha256:26571500cd54976bbc0cf1006ffbcd1a68dd102f816b7a1051b219616ba9fee0"}, 438 | {file = "flake8_isort-4.2.0-py3-none-any.whl", hash = "sha256:5b87630fb3719bf4c1833fd11e0d9534f43efdeba524863e15d8f14a7ef6adbf"}, 439 | ] 440 | 441 | [package.dependencies] 442 | flake8 = ">=3.2.1,<6" 443 | isort = ">=4.3.5,<6" 444 | 445 | [package.extras] 446 | test = ["pytest-cov"] 447 | 448 | [[package]] 449 | name = "flake8-polyfill" 450 | version = "1.0.2" 451 | description = "Polyfill package for Flake8 plugins" 452 | optional = false 453 | python-versions = "*" 454 | files = [ 455 | {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, 456 | {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, 457 | ] 458 | 459 | [package.dependencies] 460 | flake8 = "*" 461 | 462 | [[package]] 463 | name = "flake8-quotes" 464 | version = "3.3.2" 465 | description = "Flake8 lint for quotes." 466 | optional = false 467 | python-versions = "*" 468 | files = [ 469 | {file = "flake8-quotes-3.3.2.tar.gz", hash = "sha256:6e26892b632dacba517bf27219c459a8396dcfac0f5e8204904c5a4ba9b480e1"}, 470 | ] 471 | 472 | [package.dependencies] 473 | flake8 = "*" 474 | 475 | [[package]] 476 | name = "flake8-rst-docstrings" 477 | version = "0.2.7" 478 | description = "Python docstring reStructuredText (RST) validator" 479 | optional = false 480 | python-versions = ">=3.7" 481 | files = [ 482 | {file = "flake8-rst-docstrings-0.2.7.tar.gz", hash = "sha256:2740067ab9237559dd45a3434d8c987792c7b259ca563621a3b95efe201f5382"}, 483 | {file = "flake8_rst_docstrings-0.2.7-py3-none-any.whl", hash = "sha256:5d56075dce360bcc9c6775bfe7cb431aa395de600ca7e8d40580a28d50b2a803"}, 484 | ] 485 | 486 | [package.dependencies] 487 | flake8 = ">=3.0.0" 488 | pygments = "*" 489 | restructuredtext-lint = "*" 490 | 491 | [[package]] 492 | name = "flake8-string-format" 493 | version = "0.3.0" 494 | description = "string format checker, plugin for flake8" 495 | optional = false 496 | python-versions = "*" 497 | files = [ 498 | {file = "flake8-string-format-0.3.0.tar.gz", hash = "sha256:65f3da786a1461ef77fca3780b314edb2853c377f2e35069723348c8917deaa2"}, 499 | {file = "flake8_string_format-0.3.0-py2.py3-none-any.whl", hash = "sha256:812ff431f10576a74c89be4e85b8e075a705be39bc40c4b4278b5b13e2afa9af"}, 500 | ] 501 | 502 | [package.dependencies] 503 | flake8 = "*" 504 | 505 | [[package]] 506 | name = "flatten-dict" 507 | version = "0.4.2" 508 | description = "A flexible utility for flattening and unflattening dict-like objects in Python." 509 | optional = false 510 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 511 | files = [ 512 | {file = "flatten-dict-0.4.2.tar.gz", hash = "sha256:506a96b6e6f805b81ae46a0f9f31290beb5fa79ded9d80dbe1b7fa236ab43076"}, 513 | {file = "flatten_dict-0.4.2-py2.py3-none-any.whl", hash = "sha256:7e245b20c4c718981212210eec4284a330c9f713e632e98765560e05421e48ad"}, 514 | ] 515 | 516 | [package.dependencies] 517 | six = ">=1.12,<2.0" 518 | 519 | [[package]] 520 | name = "furl" 521 | version = "2.1.3" 522 | description = "URL manipulation made simple." 523 | optional = false 524 | python-versions = "*" 525 | files = [ 526 | {file = "furl-2.1.3-py2.py3-none-any.whl", hash = "sha256:9ab425062c4217f9802508e45feb4a83e54324273ac4b202f1850363309666c0"}, 527 | {file = "furl-2.1.3.tar.gz", hash = "sha256:5a6188fe2666c484a12159c18be97a1977a71d632ef5bb867ef15f54af39cc4e"}, 528 | ] 529 | 530 | [package.dependencies] 531 | orderedmultidict = ">=1.0.1" 532 | six = ">=1.8.0" 533 | 534 | [[package]] 535 | name = "gitdb" 536 | version = "4.0.10" 537 | description = "Git Object Database" 538 | optional = false 539 | python-versions = ">=3.7" 540 | files = [ 541 | {file = "gitdb-4.0.10-py3-none-any.whl", hash = "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7"}, 542 | {file = "gitdb-4.0.10.tar.gz", hash = "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a"}, 543 | ] 544 | 545 | [package.dependencies] 546 | smmap = ">=3.0.1,<6" 547 | 548 | [[package]] 549 | name = "gitpython" 550 | version = "3.1.31" 551 | description = "GitPython is a Python library used to interact with Git repositories" 552 | optional = false 553 | python-versions = ">=3.7" 554 | files = [ 555 | {file = "GitPython-3.1.31-py3-none-any.whl", hash = "sha256:f04893614f6aa713a60cbbe1e6a97403ef633103cdd0ef5eb6efe0deb98dbe8d"}, 556 | {file = "GitPython-3.1.31.tar.gz", hash = "sha256:8ce3bcf69adfdf7c7d503e78fd3b1c492af782d58893b650adb2ac8912ddd573"}, 557 | ] 558 | 559 | [package.dependencies] 560 | gitdb = ">=4.0.1,<5" 561 | 562 | [[package]] 563 | name = "identify" 564 | version = "2.5.24" 565 | description = "File identification library for Python" 566 | optional = false 567 | python-versions = ">=3.7" 568 | files = [ 569 | {file = "identify-2.5.24-py2.py3-none-any.whl", hash = "sha256:986dbfb38b1140e763e413e6feb44cd731faf72d1909543178aa79b0e258265d"}, 570 | {file = "identify-2.5.24.tar.gz", hash = "sha256:0aac67d5b4812498056d28a9a512a483f5085cc28640b02b258a59dac34301d4"}, 571 | ] 572 | 573 | [package.extras] 574 | license = ["ukkonen"] 575 | 576 | [[package]] 577 | name = "idna" 578 | version = "3.4" 579 | description = "Internationalized Domain Names in Applications (IDNA)" 580 | optional = false 581 | python-versions = ">=3.5" 582 | files = [ 583 | {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, 584 | {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, 585 | ] 586 | 587 | [[package]] 588 | name = "isort" 589 | version = "5.12.0" 590 | description = "A Python utility / library to sort Python imports." 591 | optional = false 592 | python-versions = ">=3.8.0" 593 | files = [ 594 | {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, 595 | {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, 596 | ] 597 | 598 | [package.extras] 599 | colors = ["colorama (>=0.4.3)"] 600 | pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] 601 | plugins = ["setuptools"] 602 | requirements-deprecated-finder = ["pip-api", "pipreqs"] 603 | 604 | [[package]] 605 | name = "jmespath" 606 | version = "1.0.1" 607 | description = "JSON Matching Expressions" 608 | optional = false 609 | python-versions = ">=3.7" 610 | files = [ 611 | {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, 612 | {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, 613 | ] 614 | 615 | [[package]] 616 | name = "loguru" 617 | version = "0.7.0" 618 | description = "Python logging made (stupidly) simple" 619 | optional = false 620 | python-versions = ">=3.5" 621 | files = [ 622 | {file = "loguru-0.7.0-py3-none-any.whl", hash = "sha256:b93aa30099fa6860d4727f1b81f8718e965bb96253fa190fab2077aaad6d15d3"}, 623 | {file = "loguru-0.7.0.tar.gz", hash = "sha256:1612053ced6ae84d7959dd7d5e431a0532642237ec21f7fd83ac73fe539e03e1"}, 624 | ] 625 | 626 | [package.dependencies] 627 | colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} 628 | win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} 629 | 630 | [package.extras] 631 | dev = ["Sphinx (==5.3.0)", "colorama (==0.4.5)", "colorama (==0.4.6)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v0.990)", "pre-commit (==3.2.1)", "pytest (==6.1.2)", "pytest (==7.2.1)", "pytest-cov (==2.12.1)", "pytest-cov (==4.0.0)", "pytest-mypy-plugins (==1.10.1)", "pytest-mypy-plugins (==1.9.3)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.2.0)", "tox (==3.27.1)", "tox (==4.4.6)"] 632 | 633 | [[package]] 634 | name = "markdown-it-py" 635 | version = "2.2.0" 636 | description = "Python port of markdown-it. Markdown parsing, done right!" 637 | optional = false 638 | python-versions = ">=3.7" 639 | files = [ 640 | {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"}, 641 | {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"}, 642 | ] 643 | 644 | [package.dependencies] 645 | mdurl = ">=0.1,<1.0" 646 | 647 | [package.extras] 648 | benchmarking = ["psutil", "pytest", "pytest-benchmark"] 649 | code-style = ["pre-commit (>=3.0,<4.0)"] 650 | compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] 651 | linkify = ["linkify-it-py (>=1,<3)"] 652 | plugins = ["mdit-py-plugins"] 653 | profiling = ["gprof2dot"] 654 | rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] 655 | testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] 656 | 657 | [[package]] 658 | name = "marshmallow" 659 | version = "3.19.0" 660 | description = "A lightweight library for converting complex datatypes to and from native Python datatypes." 661 | optional = false 662 | python-versions = ">=3.7" 663 | files = [ 664 | {file = "marshmallow-3.19.0-py3-none-any.whl", hash = "sha256:93f0958568da045b0021ec6aeb7ac37c81bfcccbb9a0e7ed8559885070b3a19b"}, 665 | {file = "marshmallow-3.19.0.tar.gz", hash = "sha256:90032c0fd650ce94b6ec6dc8dfeb0e3ff50c144586462c389b81a07205bedb78"}, 666 | ] 667 | 668 | [package.dependencies] 669 | packaging = ">=17.0" 670 | 671 | [package.extras] 672 | dev = ["flake8 (==5.0.4)", "flake8-bugbear (==22.10.25)", "mypy (==0.990)", "pre-commit (>=2.4,<3.0)", "pytest", "pytz", "simplejson", "tox"] 673 | docs = ["alabaster (==0.7.12)", "autodocsumm (==0.2.9)", "sphinx (==5.3.0)", "sphinx-issues (==3.0.1)", "sphinx-version-warning (==1.1.2)"] 674 | lint = ["flake8 (==5.0.4)", "flake8-bugbear (==22.10.25)", "mypy (==0.990)", "pre-commit (>=2.4,<3.0)"] 675 | tests = ["pytest", "pytz", "simplejson"] 676 | 677 | [[package]] 678 | name = "marshmallow-polyfield" 679 | version = "5.11" 680 | description = "An unofficial extension to Marshmallow to allow for polymorphic fields" 681 | optional = false 682 | python-versions = ">=3.5" 683 | files = [ 684 | {file = "marshmallow-polyfield-5.11.tar.gz", hash = "sha256:8075a9cc490da4af58b902b4a40a99882dd031adb7aaa96abd147a4fcd53415f"}, 685 | ] 686 | 687 | [package.dependencies] 688 | marshmallow = ">=3.0.0b10" 689 | 690 | [[package]] 691 | name = "mccabe" 692 | version = "0.6.1" 693 | description = "McCabe checker, plugin for flake8" 694 | optional = false 695 | python-versions = "*" 696 | files = [ 697 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 698 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, 699 | ] 700 | 701 | [[package]] 702 | name = "mdurl" 703 | version = "0.1.2" 704 | description = "Markdown URL utilities" 705 | optional = false 706 | python-versions = ">=3.7" 707 | files = [ 708 | {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, 709 | {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, 710 | ] 711 | 712 | [[package]] 713 | name = "more-itertools" 714 | version = "9.1.0" 715 | description = "More routines for operating on iterables, beyond itertools" 716 | optional = false 717 | python-versions = ">=3.7" 718 | files = [ 719 | {file = "more-itertools-9.1.0.tar.gz", hash = "sha256:cabaa341ad0389ea83c17a94566a53ae4c9d07349861ecb14dc6d0345cf9ac5d"}, 720 | {file = "more_itertools-9.1.0-py3-none-any.whl", hash = "sha256:d2bc7f02446e86a68911e58ded76d6561eea00cddfb2a91e7019bbb586c799f3"}, 721 | ] 722 | 723 | [[package]] 724 | name = "mypy" 725 | version = "1.3.0" 726 | description = "Optional static typing for Python" 727 | optional = false 728 | python-versions = ">=3.7" 729 | files = [ 730 | {file = "mypy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eb485cea53f4f5284e5baf92902cd0088b24984f4209e25981cc359d64448d"}, 731 | {file = "mypy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c99c3ecf223cf2952638da9cd82793d8f3c0c5fa8b6ae2b2d9ed1e1ff51ba85"}, 732 | {file = "mypy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:550a8b3a19bb6589679a7c3c31f64312e7ff482a816c96e0cecec9ad3a7564dd"}, 733 | {file = "mypy-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cbc07246253b9e3d7d74c9ff948cd0fd7a71afcc2b77c7f0a59c26e9395cb152"}, 734 | {file = "mypy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:a22435632710a4fcf8acf86cbd0d69f68ac389a3892cb23fbad176d1cddaf228"}, 735 | {file = "mypy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6e33bb8b2613614a33dff70565f4c803f889ebd2f859466e42b46e1df76018dd"}, 736 | {file = "mypy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d23370d2a6b7a71dc65d1266f9a34e4cde9e8e21511322415db4b26f46f6b8c"}, 737 | {file = "mypy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:658fe7b674769a0770d4b26cb4d6f005e88a442fe82446f020be8e5f5efb2fae"}, 738 | {file = "mypy-1.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d29e324cdda61daaec2336c42512e59c7c375340bd202efa1fe0f7b8f8ca"}, 739 | {file = "mypy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:d0b6c62206e04061e27009481cb0ec966f7d6172b5b936f3ead3d74f29fe3dcf"}, 740 | {file = "mypy-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:76ec771e2342f1b558c36d49900dfe81d140361dd0d2df6cd71b3db1be155409"}, 741 | {file = "mypy-1.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc95f8386314272bbc817026f8ce8f4f0d2ef7ae44f947c4664efac9adec929"}, 742 | {file = "mypy-1.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:faff86aa10c1aa4a10e1a301de160f3d8fc8703b88c7e98de46b531ff1276a9a"}, 743 | {file = "mypy-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8c5979d0deb27e0f4479bee18ea0f83732a893e81b78e62e2dda3e7e518c92ee"}, 744 | {file = "mypy-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c5d2cc54175bab47011b09688b418db71403aefad07cbcd62d44010543fc143f"}, 745 | {file = "mypy-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:87df44954c31d86df96c8bd6e80dfcd773473e877ac6176a8e29898bfb3501cb"}, 746 | {file = "mypy-1.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:473117e310febe632ddf10e745a355714e771ffe534f06db40702775056614c4"}, 747 | {file = "mypy-1.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:74bc9b6e0e79808bf8678d7678b2ae3736ea72d56eede3820bd3849823e7f305"}, 748 | {file = "mypy-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:44797d031a41516fcf5cbfa652265bb994e53e51994c1bd649ffcd0c3a7eccbf"}, 749 | {file = "mypy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddae0f39ca146972ff6bb4399f3b2943884a774b8771ea0a8f50e971f5ea5ba8"}, 750 | {file = "mypy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c4c42c60a8103ead4c1c060ac3cdd3ff01e18fddce6f1016e08939647a0e703"}, 751 | {file = "mypy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e86c2c6852f62f8f2b24cb7a613ebe8e0c7dc1402c61d36a609174f63e0ff017"}, 752 | {file = "mypy-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f9dca1e257d4cc129517779226753dbefb4f2266c4eaad610fc15c6a7e14283e"}, 753 | {file = "mypy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:95d8d31a7713510685b05fbb18d6ac287a56c8f6554d88c19e73f724a445448a"}, 754 | {file = "mypy-1.3.0-py3-none-any.whl", hash = "sha256:a8763e72d5d9574d45ce5881962bc8e9046bf7b375b0abf031f3e6811732a897"}, 755 | {file = "mypy-1.3.0.tar.gz", hash = "sha256:e1f4d16e296f5135624b34e8fb741eb0eadedca90862405b1f1fde2040b9bd11"}, 756 | ] 757 | 758 | [package.dependencies] 759 | mypy-extensions = ">=1.0.0" 760 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 761 | typing-extensions = ">=3.10" 762 | 763 | [package.extras] 764 | dmypy = ["psutil (>=4.0)"] 765 | install-types = ["pip"] 766 | python2 = ["typed-ast (>=1.4.0,<2)"] 767 | reports = ["lxml"] 768 | 769 | [[package]] 770 | name = "mypy-extensions" 771 | version = "1.0.0" 772 | description = "Type system extensions for programs checked with the mypy type checker." 773 | optional = false 774 | python-versions = ">=3.5" 775 | files = [ 776 | {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, 777 | {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, 778 | ] 779 | 780 | [[package]] 781 | name = "nitpick" 782 | version = "0.32.0" 783 | description = "Enforce the same settings across multiple language-independent projects" 784 | optional = false 785 | python-versions = ">=3.7,<4.0" 786 | files = [ 787 | {file = "nitpick-0.32.0-py3-none-any.whl", hash = "sha256:a2befd6371f8726846d4c127b80b4bc2cc510f97ee8d1a698d879e9d20a95a89"}, 788 | {file = "nitpick-0.32.0.tar.gz", hash = "sha256:9df66107d9dfc5f8631ee5af1c3a1050ef9db0549e04873bef91bf6681a55b61"}, 789 | ] 790 | 791 | [package.dependencies] 792 | attrs = ">=20.1.0" 793 | autorepr = "*" 794 | click = "*" 795 | ConfigUpdater = "*" 796 | dictdiffer = "*" 797 | dpath = "*" 798 | flake8 = ">=3.0.0" 799 | flatten-dict = "*" 800 | furl = "*" 801 | identify = "*" 802 | jmespath = "*" 803 | loguru = "*" 804 | marshmallow = ">=3.0.0b10" 805 | marshmallow-polyfield = ">=5.10,<6.0" 806 | more-itertools = "*" 807 | pluggy = "*" 808 | python-slugify = "*" 809 | requests = "*" 810 | requests-cache = "*" 811 | "ruamel.yaml" = "*" 812 | sortedcontainers = "*" 813 | StrEnum = "*" 814 | toml = "*" 815 | tomlkit = ">=0.8.0" 816 | 817 | [package.extras] 818 | doc = ["sphinx", "sphinx-gitref", "sphinx_rtd_theme", "sphobjinv"] 819 | lint = ["pylint"] 820 | test = ["freezegun", "pytest", "pytest-cov", "pytest-datadir", "pytest-socket", "pytest-testmon", "pytest-watch", "responses", "testfixtures"] 821 | 822 | [[package]] 823 | name = "orderedmultidict" 824 | version = "1.0.1" 825 | description = "Ordered Multivalue Dictionary" 826 | optional = false 827 | python-versions = "*" 828 | files = [ 829 | {file = "orderedmultidict-1.0.1-py2.py3-none-any.whl", hash = "sha256:43c839a17ee3cdd62234c47deca1a8508a3f2ca1d0678a3bf791c87cf84adbf3"}, 830 | {file = "orderedmultidict-1.0.1.tar.gz", hash = "sha256:04070bbb5e87291cc9bfa51df413677faf2141c73c61d2a5f7b26bea3cd882ad"}, 831 | ] 832 | 833 | [package.dependencies] 834 | six = ">=1.8.0" 835 | 836 | [[package]] 837 | name = "packaging" 838 | version = "23.1" 839 | description = "Core utilities for Python packages" 840 | optional = false 841 | python-versions = ">=3.7" 842 | files = [ 843 | {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, 844 | {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, 845 | ] 846 | 847 | [[package]] 848 | name = "pbr" 849 | version = "5.11.1" 850 | description = "Python Build Reasonableness" 851 | optional = false 852 | python-versions = ">=2.6" 853 | files = [ 854 | {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"}, 855 | {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"}, 856 | ] 857 | 858 | [[package]] 859 | name = "pep8-naming" 860 | version = "0.13.2" 861 | description = "Check PEP-8 naming conventions, plugin for flake8" 862 | optional = false 863 | python-versions = ">=3.7" 864 | files = [ 865 | {file = "pep8-naming-0.13.2.tar.gz", hash = "sha256:93eef62f525fd12a6f8c98f4dcc17fa70baae2f37fa1f73bec00e3e44392fa48"}, 866 | {file = "pep8_naming-0.13.2-py3-none-any.whl", hash = "sha256:59e29e55c478db69cffbe14ab24b5bd2cd615c0413edf790d47d3fb7ba9a4e23"}, 867 | ] 868 | 869 | [package.dependencies] 870 | flake8 = ">=3.9.1" 871 | 872 | [[package]] 873 | name = "platformdirs" 874 | version = "3.5.1" 875 | description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 876 | optional = false 877 | python-versions = ">=3.7" 878 | files = [ 879 | {file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"}, 880 | {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"}, 881 | ] 882 | 883 | [package.extras] 884 | docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] 885 | test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] 886 | 887 | [[package]] 888 | name = "pluggy" 889 | version = "1.0.0" 890 | description = "plugin and hook calling mechanisms for python" 891 | optional = false 892 | python-versions = ">=3.6" 893 | files = [ 894 | {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, 895 | {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, 896 | ] 897 | 898 | [package.extras] 899 | dev = ["pre-commit", "tox"] 900 | testing = ["pytest", "pytest-benchmark"] 901 | 902 | [[package]] 903 | name = "pycodestyle" 904 | version = "2.8.0" 905 | description = "Python style guide checker" 906 | optional = false 907 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 908 | files = [ 909 | {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, 910 | {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, 911 | ] 912 | 913 | [[package]] 914 | name = "pydocstyle" 915 | version = "6.3.0" 916 | description = "Python docstring style checker" 917 | optional = false 918 | python-versions = ">=3.6" 919 | files = [ 920 | {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, 921 | {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, 922 | ] 923 | 924 | [package.dependencies] 925 | snowballstemmer = ">=2.2.0" 926 | 927 | [package.extras] 928 | toml = ["tomli (>=1.2.3)"] 929 | 930 | [[package]] 931 | name = "pyflakes" 932 | version = "2.4.0" 933 | description = "passive checker of Python programs" 934 | optional = false 935 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 936 | files = [ 937 | {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, 938 | {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, 939 | ] 940 | 941 | [[package]] 942 | name = "pygments" 943 | version = "2.15.1" 944 | description = "Pygments is a syntax highlighting package written in Python." 945 | optional = false 946 | python-versions = ">=3.7" 947 | files = [ 948 | {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"}, 949 | {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"}, 950 | ] 951 | 952 | [package.extras] 953 | plugins = ["importlib-metadata"] 954 | 955 | [[package]] 956 | name = "python-slugify" 957 | version = "8.0.1" 958 | description = "A Python slugify application that also handles Unicode" 959 | optional = false 960 | python-versions = ">=3.7" 961 | files = [ 962 | {file = "python-slugify-8.0.1.tar.gz", hash = "sha256:ce0d46ddb668b3be82f4ed5e503dbc33dd815d83e2eb6824211310d3fb172a27"}, 963 | {file = "python_slugify-8.0.1-py2.py3-none-any.whl", hash = "sha256:70ca6ea68fe63ecc8fa4fcf00ae651fc8a5d02d93dcd12ae6d4fc7ca46c4d395"}, 964 | ] 965 | 966 | [package.dependencies] 967 | text-unidecode = ">=1.3" 968 | 969 | [package.extras] 970 | unidecode = ["Unidecode (>=1.1.1)"] 971 | 972 | [[package]] 973 | name = "pyyaml" 974 | version = "6.0" 975 | description = "YAML parser and emitter for Python" 976 | optional = false 977 | python-versions = ">=3.6" 978 | files = [ 979 | {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, 980 | {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, 981 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, 982 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, 983 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, 984 | {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, 985 | {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, 986 | {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, 987 | {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, 988 | {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, 989 | {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, 990 | {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, 991 | {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, 992 | {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, 993 | {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, 994 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, 995 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, 996 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, 997 | {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, 998 | {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, 999 | {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, 1000 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, 1001 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, 1002 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, 1003 | {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, 1004 | {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, 1005 | {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, 1006 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, 1007 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, 1008 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, 1009 | {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, 1010 | {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, 1011 | {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, 1012 | {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, 1013 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, 1014 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, 1015 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, 1016 | {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, 1017 | {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, 1018 | {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, 1019 | ] 1020 | 1021 | [[package]] 1022 | name = "requests" 1023 | version = "2.31.0" 1024 | description = "Python HTTP for Humans." 1025 | optional = false 1026 | python-versions = ">=3.7" 1027 | files = [ 1028 | {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, 1029 | {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, 1030 | ] 1031 | 1032 | [package.dependencies] 1033 | certifi = ">=2017.4.17" 1034 | charset-normalizer = ">=2,<4" 1035 | idna = ">=2.5,<4" 1036 | urllib3 = ">=1.21.1,<3" 1037 | 1038 | [package.extras] 1039 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 1040 | use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] 1041 | 1042 | [[package]] 1043 | name = "requests-cache" 1044 | version = "1.0.1" 1045 | description = "A persistent cache for python requests" 1046 | optional = false 1047 | python-versions = ">=3.7,<4.0" 1048 | files = [ 1049 | {file = "requests_cache-1.0.1-py3-none-any.whl", hash = "sha256:55c5765c26fd98a38c633d6e3931a507b7708cdd07c0afb48773d0718ac15969"}, 1050 | {file = "requests_cache-1.0.1.tar.gz", hash = "sha256:d42e6c2f11de54e6a134c9a00c5ca2a3c8edde3c3f2bdfd942586fafa8990e14"}, 1051 | ] 1052 | 1053 | [package.dependencies] 1054 | attrs = ">=21.2" 1055 | cattrs = ">=22.2" 1056 | platformdirs = ">=2.5" 1057 | requests = ">=2.22" 1058 | url-normalize = ">=1.4" 1059 | urllib3 = ">=1.25.5" 1060 | 1061 | [package.extras] 1062 | all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=5.4)", "redis (>=3)", "ujson (>=5.4)"] 1063 | bson = ["bson (>=0.5)"] 1064 | docs = ["furo (>=2022.12.7,<2023.0.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.6)"] 1065 | dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"] 1066 | json = ["ujson (>=5.4)"] 1067 | mongodb = ["pymongo (>=3)"] 1068 | redis = ["redis (>=3)"] 1069 | security = ["itsdangerous (>=2.0)"] 1070 | yaml = ["pyyaml (>=5.4)"] 1071 | 1072 | [[package]] 1073 | name = "restructuredtext-lint" 1074 | version = "1.4.0" 1075 | description = "reStructuredText linter" 1076 | optional = false 1077 | python-versions = "*" 1078 | files = [ 1079 | {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"}, 1080 | ] 1081 | 1082 | [package.dependencies] 1083 | docutils = ">=0.11,<1.0" 1084 | 1085 | [[package]] 1086 | name = "rich" 1087 | version = "13.3.5" 1088 | description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" 1089 | optional = false 1090 | python-versions = ">=3.7.0" 1091 | files = [ 1092 | {file = "rich-13.3.5-py3-none-any.whl", hash = "sha256:69cdf53799e63f38b95b9bf9c875f8c90e78dd62b2f00c13a911c7a3b9fa4704"}, 1093 | {file = "rich-13.3.5.tar.gz", hash = "sha256:2d11b9b8dd03868f09b4fffadc84a6a8cda574e40dc90821bd845720ebb8e89c"}, 1094 | ] 1095 | 1096 | [package.dependencies] 1097 | markdown-it-py = ">=2.2.0,<3.0.0" 1098 | pygments = ">=2.13.0,<3.0.0" 1099 | 1100 | [package.extras] 1101 | jupyter = ["ipywidgets (>=7.5.1,<9)"] 1102 | 1103 | [[package]] 1104 | name = "ruamel-yaml" 1105 | version = "0.17.28" 1106 | description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" 1107 | optional = false 1108 | python-versions = ">=3" 1109 | files = [ 1110 | {file = "ruamel.yaml-0.17.28-py3-none-any.whl", hash = "sha256:823aff68f88260805049d6a4825e36cb7f1e273a7dd8f391e7b35a16a67a30ea"}, 1111 | {file = "ruamel.yaml-0.17.28.tar.gz", hash = "sha256:3bf6df1c481d2463a633be6ee86e8aece941bb3298a9a0cd6d0865f47b1ddce6"}, 1112 | ] 1113 | 1114 | [package.dependencies] 1115 | "ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.12\""} 1116 | 1117 | [package.extras] 1118 | docs = ["ryd"] 1119 | jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] 1120 | 1121 | [[package]] 1122 | name = "ruamel-yaml-clib" 1123 | version = "0.2.7" 1124 | description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" 1125 | optional = false 1126 | python-versions = ">=3.5" 1127 | files = [ 1128 | {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5859983f26d8cd7bb5c287ef452e8aacc86501487634573d260968f753e1d71"}, 1129 | {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:debc87a9516b237d0466a711b18b6ebeb17ba9f391eb7f91c649c5c4ec5006c7"}, 1130 | {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:df5828871e6648db72d1c19b4bd24819b80a755c4541d3409f0f7acd0f335c80"}, 1131 | {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:efa08d63ef03d079dcae1dfe334f6c8847ba8b645d08df286358b1f5293d24ab"}, 1132 | {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"}, 1133 | {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"}, 1134 | {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, 1135 | {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"}, 1136 | {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"}, 1137 | {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win32.whl", hash = "sha256:f6d3d39611ac2e4f62c3128a9eed45f19a6608670c5a2f4f07f24e8de3441d38"}, 1138 | {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:da538167284de58a52109a9b89b8f6a53ff8437dd6dc26d33b57bf6699153122"}, 1139 | {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072"}, 1140 | {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_12_0_arm64.whl", hash = "sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8"}, 1141 | {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3"}, 1142 | {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:370445fd795706fd291ab00c9df38a0caed0f17a6fb46b0f607668ecb16ce763"}, 1143 | {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win32.whl", hash = "sha256:ecdf1a604009bd35c674b9225a8fa609e0282d9b896c03dd441a91e5f53b534e"}, 1144 | {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win_amd64.whl", hash = "sha256:f34019dced51047d6f70cb9383b2ae2853b7fc4dce65129a5acd49f4f9256646"}, 1145 | {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aa261c29a5545adfef9296b7e33941f46aa5bbd21164228e833412af4c9c75f"}, 1146 | {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f01da5790e95815eb5a8a138508c01c758e5f5bc0ce4286c4f7028b8dd7ac3d0"}, 1147 | {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:40d030e2329ce5286d6b231b8726959ebbe0404c92f0a578c0e2482182e38282"}, 1148 | {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c3ca1fbba4ae962521e5eb66d72998b51f0f4d0f608d3c0347a48e1af262efa7"}, 1149 | {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win32.whl", hash = "sha256:7bdb4c06b063f6fd55e472e201317a3bb6cdeeee5d5a38512ea5c01e1acbdd93"}, 1150 | {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:be2a7ad8fd8f7442b24323d24ba0b56c51219513cfa45b9ada3b87b76c374d4b"}, 1151 | {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91a789b4aa0097b78c93e3dc4b40040ba55bef518f84a40d4442f713b4094acb"}, 1152 | {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:99e77daab5d13a48a4054803d052ff40780278240a902b880dd37a51ba01a307"}, 1153 | {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:3243f48ecd450eddadc2d11b5feb08aca941b5cd98c9b1db14b2fd128be8c697"}, 1154 | {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8831a2cedcd0f0927f788c5bdf6567d9dc9cc235646a434986a852af1cb54b4b"}, 1155 | {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win32.whl", hash = "sha256:3110a99e0f94a4a3470ff67fc20d3f96c25b13d24c6980ff841e82bafe827cac"}, 1156 | {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:92460ce908546ab69770b2e576e4f99fbb4ce6ab4b245345a3869a0a0410488f"}, 1157 | {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc0667c1eb8f83a3752b71b9c4ba55ef7c7058ae57022dd9b29065186a113d9"}, 1158 | {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:4a4d8d417868d68b979076a9be6a38c676eca060785abaa6709c7b31593c35d1"}, 1159 | {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bf9a6bc4a0221538b1a7de3ed7bca4c93c02346853f44e1cd764be0023cd3640"}, 1160 | {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a7b301ff08055d73223058b5c46c55638917f04d21577c95e00e0c4d79201a6b"}, 1161 | {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win32.whl", hash = "sha256:d5e51e2901ec2366b79f16c2299a03e74ba4531ddcfacc1416639c557aef0ad8"}, 1162 | {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:184faeaec61dbaa3cace407cffc5819f7b977e75360e8d5ca19461cd851a5fc5"}, 1163 | {file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"}, 1164 | ] 1165 | 1166 | [[package]] 1167 | name = "six" 1168 | version = "1.16.0" 1169 | description = "Python 2 and 3 compatibility utilities" 1170 | optional = false 1171 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 1172 | files = [ 1173 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 1174 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 1175 | ] 1176 | 1177 | [[package]] 1178 | name = "smmap" 1179 | version = "5.0.0" 1180 | description = "A pure Python implementation of a sliding window memory map manager" 1181 | optional = false 1182 | python-versions = ">=3.6" 1183 | files = [ 1184 | {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, 1185 | {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, 1186 | ] 1187 | 1188 | [[package]] 1189 | name = "snowballstemmer" 1190 | version = "2.2.0" 1191 | description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." 1192 | optional = false 1193 | python-versions = "*" 1194 | files = [ 1195 | {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, 1196 | {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, 1197 | ] 1198 | 1199 | [[package]] 1200 | name = "sortedcontainers" 1201 | version = "2.4.0" 1202 | description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" 1203 | optional = false 1204 | python-versions = "*" 1205 | files = [ 1206 | {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, 1207 | {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, 1208 | ] 1209 | 1210 | [[package]] 1211 | name = "stevedore" 1212 | version = "5.1.0" 1213 | description = "Manage dynamic plugins for Python applications" 1214 | optional = false 1215 | python-versions = ">=3.8" 1216 | files = [ 1217 | {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"}, 1218 | {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"}, 1219 | ] 1220 | 1221 | [package.dependencies] 1222 | pbr = ">=2.0.0,<2.1.0 || >2.1.0" 1223 | 1224 | [[package]] 1225 | name = "strenum" 1226 | version = "0.4.10" 1227 | description = "An Enum that inherits from str." 1228 | optional = false 1229 | python-versions = "*" 1230 | files = [ 1231 | {file = "StrEnum-0.4.10-py3-none-any.whl", hash = "sha256:aebf04bba8e5af435937c452d69a86798b6f8d5ca5f20ba18561dbfad571ccdd"}, 1232 | {file = "StrEnum-0.4.10.tar.gz", hash = "sha256:898cc0ebb5054ee07400341ac1d75fdfee489d76d6df3fbc1c2eaf95971e3916"}, 1233 | ] 1234 | 1235 | [package.extras] 1236 | docs = ["myst-parser[linkify]", "sphinx", "sphinx-rtd-theme"] 1237 | release = ["twine"] 1238 | test = ["pylint", "pytest", "pytest-black", "pytest-cov", "pytest-pylint"] 1239 | 1240 | [[package]] 1241 | name = "text-unidecode" 1242 | version = "1.3" 1243 | description = "The most basic Text::Unidecode port" 1244 | optional = false 1245 | python-versions = "*" 1246 | files = [ 1247 | {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, 1248 | {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, 1249 | ] 1250 | 1251 | [[package]] 1252 | name = "toml" 1253 | version = "0.10.2" 1254 | description = "Python Library for Tom's Obvious, Minimal Language" 1255 | optional = false 1256 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 1257 | files = [ 1258 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, 1259 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, 1260 | ] 1261 | 1262 | [[package]] 1263 | name = "tomli" 1264 | version = "2.0.1" 1265 | description = "A lil' TOML parser" 1266 | optional = false 1267 | python-versions = ">=3.7" 1268 | files = [ 1269 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 1270 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 1271 | ] 1272 | 1273 | [[package]] 1274 | name = "tomlkit" 1275 | version = "0.11.8" 1276 | description = "Style preserving TOML library" 1277 | optional = false 1278 | python-versions = ">=3.7" 1279 | files = [ 1280 | {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, 1281 | {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, 1282 | ] 1283 | 1284 | [[package]] 1285 | name = "typing-extensions" 1286 | version = "4.6.2" 1287 | description = "Backported and Experimental Type Hints for Python 3.7+" 1288 | optional = false 1289 | python-versions = ">=3.7" 1290 | files = [ 1291 | {file = "typing_extensions-4.6.2-py3-none-any.whl", hash = "sha256:3a8b36f13dd5fdc5d1b16fe317f5668545de77fa0b8e02006381fd49d731ab98"}, 1292 | {file = "typing_extensions-4.6.2.tar.gz", hash = "sha256:06006244c70ac8ee83fa8282cb188f697b8db25bc8b4df07be1873c43897060c"}, 1293 | ] 1294 | 1295 | [[package]] 1296 | name = "url-normalize" 1297 | version = "1.4.3" 1298 | description = "URL normalization for Python" 1299 | optional = false 1300 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 1301 | files = [ 1302 | {file = "url-normalize-1.4.3.tar.gz", hash = "sha256:d23d3a070ac52a67b83a1c59a0e68f8608d1cd538783b401bc9de2c0fac999b2"}, 1303 | {file = "url_normalize-1.4.3-py2.py3-none-any.whl", hash = "sha256:ec3c301f04e5bb676d333a7fa162fa977ad2ca04b7e652bfc9fac4e405728eed"}, 1304 | ] 1305 | 1306 | [package.dependencies] 1307 | six = "*" 1308 | 1309 | [[package]] 1310 | name = "urllib3" 1311 | version = "2.0.2" 1312 | description = "HTTP library with thread-safe connection pooling, file post, and more." 1313 | optional = false 1314 | python-versions = ">=3.7" 1315 | files = [ 1316 | {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"}, 1317 | {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"}, 1318 | ] 1319 | 1320 | [package.extras] 1321 | brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] 1322 | secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] 1323 | socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] 1324 | zstd = ["zstandard (>=0.18.0)"] 1325 | 1326 | [[package]] 1327 | name = "wemake-python-styleguide" 1328 | version = "0.17.0" 1329 | description = "The strictest and most opinionated python linter ever" 1330 | optional = false 1331 | python-versions = ">=3.7,<4.0" 1332 | files = [ 1333 | {file = "wemake-python-styleguide-0.17.0.tar.gz", hash = "sha256:c8869fac392019c2bb3eae4287399245d10d2726b23f1b3c68d1564909c3a71a"}, 1334 | {file = "wemake_python_styleguide-0.17.0-py3-none-any.whl", hash = "sha256:d10b953bbe4fba83a34f4c224a0e1849ede89e486eacfc760690e6c87a28eaae"}, 1335 | ] 1336 | 1337 | [package.dependencies] 1338 | astor = ">=0.8,<0.9" 1339 | attrs = "*" 1340 | darglint = ">=1.2,<2.0" 1341 | flake8 = ">=3.7,<5" 1342 | flake8-bandit = ">=2.1,<4" 1343 | flake8-broken-line = ">=0.5,<0.6" 1344 | flake8-bugbear = ">=22.9,<23.0" 1345 | flake8-commas = ">=2.0,<3.0" 1346 | flake8-comprehensions = ">=3.1,<4.0" 1347 | flake8-debugger = ">=4.0,<5.0" 1348 | flake8-docstrings = ">=1.3,<2.0" 1349 | flake8-eradicate = ">=1.0,<2.0" 1350 | flake8-isort = ">=4.0,<5.0" 1351 | flake8-quotes = ">=3.0,<4.0" 1352 | flake8-rst-docstrings = ">=0.2,<0.3" 1353 | flake8-string-format = ">=0.3,<0.4" 1354 | pep8-naming = ">=0.13,<0.14" 1355 | pygments = ">=2.4,<3.0" 1356 | typing_extensions = ">=4.0,<5.0" 1357 | 1358 | [[package]] 1359 | name = "win32-setctime" 1360 | version = "1.1.0" 1361 | description = "A small Python utility to set file creation time on Windows" 1362 | optional = false 1363 | python-versions = ">=3.5" 1364 | files = [ 1365 | {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, 1366 | {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, 1367 | ] 1368 | 1369 | [package.extras] 1370 | dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] 1371 | 1372 | [metadata] 1373 | lock-version = "2.0" 1374 | python-versions = "3.9.x" 1375 | content-hash = "13050f0a9991a0bcdb563b2502ecbb15e5c0505bc338e10d90cb5c3872b53e09" 1376 | --------------------------------------------------------------------------------