From f6e8465dca6081b3deecda9d3d28fceabad2e169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Mon, 18 Mar 2024 14:57:05 +0100 Subject: [PATCH 01/60] :alembic: add ruff workflow and code-spell pre-commit --- .github/workflows/pr_linting.yml | 24 ++++++ .pre-commit-config.yaml | 33 +++++--- poetry.toml | 0 pyproject.toml | 105 ++++++++++++++++++++++++++ scripts/setup_env.ps1 | 67 +++++++++++++++++ scripts/setup_env.sh | 124 +++++++++++++++++++++++++++++++ 6 files changed, 344 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/pr_linting.yml create mode 100644 poetry.toml create mode 100644 pyproject.toml create mode 100644 scripts/setup_env.ps1 create mode 100644 scripts/setup_env.sh diff --git a/.github/workflows/pr_linting.yml b/.github/workflows/pr_linting.yml new file mode 100644 index 0000000000..3d2431b69a --- /dev/null +++ b/.github/workflows/pr_linting.yml @@ -0,0 +1,24 @@ +name: 📇 Code Linting + +on: + push: + branches: [ develop ] + pull_request: + branches: [ develop ] + + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number}} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: write + +jobs: + linting: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: chartboost/ruff-action@v1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index eec388924e..8aa3e1b81b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,12 +1,27 @@ # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 - hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-yaml - - id: check-added-large-files - - id: no-commit-to-branch - args: [ '--pattern', '^(?!((release|enhancement|feature|bugfix|documentation|tests|local|chore)\/[a-zA-Z0-9\-_]+)$).*' ] + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + - id: no-commit-to-branch + args: [ '--pattern', '^(?!((release|enhancement|feature|bugfix|documentation|tests|local|chore)\/[a-zA-Z0-9\-_]+)$).*' ] + - repo: https://github.com/codespell-project/codespell + rev: v2.2.6 + hooks: + - id: codespell + additional_dependencies: + - tomli + + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.3.3 + hooks: + # Run the linter. + - id: ruff + # Run the formatter. + # - id: ruff-format diff --git a/poetry.toml b/poetry.toml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000..c50c0bad5b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,105 @@ +[tool.poetry] +name = "ayon-core" +version = "0.3.0" +description = "" +authors = ["Ynput Team "] +readme = "README.md" + +[tool.poetry.dependencies] +python = ">=3.9.1,<3.10" +aiohttp_json_rpc = "*" # TVPaint server +aiohttp-middlewares = "^2.0.0" +wsrpc_aiohttp = "^3.1.1" # websocket server +Click = "^8" +clique = "1.6.*" +jsonschema = "^4" +pyblish-base = "^1.8.11" +pynput = "^1.7.2" # Timers manager - TODO remove +speedcopy = "^2.1" +six = "^1.15" +qtawesome = "0.7.3" + + +[tool.poetry.dev-dependencies] +pytest = "^8.0" +pytest-print = "^1.0" +ayon-python-api = "^1.0" +arrow = "^1.3.0" +ruff = "^0.2.2" + + +[tool.ruff] +# Exclude a variety of commonly ignored directories. +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".ipynb_checkpoints", + ".mypy_cache", + ".nox", + ".pants.d", + ".pyenv", + ".pytest_cache", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + ".vscode", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "site-packages", + "venv", + "vendor", + "generated", +] + +# Same as Black. +line-length = 79 +indent-width = 4 + +# Assume Python 3.8 +target-version = "py39" + +[tool.ruff.lint] +# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. +select = ["E4", "E7", "E9", "F"] +ignore = [] + +# Allow fix for all enabled rules (when `--fix`) is provided. +fixable = ["ALL"] +unfixable = [] + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +[tool.ruff.format] +# Like Black, use double quotes for strings. +quote-style = "double" + +# Like Black, indent with spaces, rather than tabs. +indent-style = "space" + +# Like Black, respect magic trailing commas. +skip-magic-trailing-comma = false + +# Like Black, automatically detect the appropriate line ending. +line-ending = "auto" + +[tool.codespell] +# Ignore words that are not in the dictionary. +ignore-words-list = "ayon,ynput" +skip = "./.*,./package/*" +count = true +quiet-level = 3 + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/scripts/setup_env.ps1 b/scripts/setup_env.ps1 new file mode 100644 index 0000000000..82ff515bc6 --- /dev/null +++ b/scripts/setup_env.ps1 @@ -0,0 +1,67 @@ +$current_dir = Get-Location +$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +$repo_root = (Get-Item $script_dir).parent.FullName +& git submodule update --init --recursive + + +function Exit-WithCode($exitcode) { + # Only exit this host process if it's a child of another PowerShell parent process... + $parentPID = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$PID" | Select-Object -Property ParentProcessId).ParentProcessId + $parentProcName = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$parentPID" | Select-Object -Property Name).Name + if ('powershell.exe' -eq $parentProcName) { $host.SetShouldExit($exitcode) } + + exit $exitcode + } + + +function Install-Poetry() { + Write-Host ">>> Installing Poetry ... " + $python = "python" + if (Get-Command "pyenv" -ErrorAction SilentlyContinue) { + if (-not (Test-Path -PathType Leaf -Path "$($repo_root)\.python-version")) { + $result = & pyenv global + if ($result -eq "no global version configured") { + Write-Host "!!! Using pyenv but having no local or global version of Python set." -Color Red, Yellow + Exit-WithCode 1 + } + } + $python = & pyenv which python + + } + + $env:POETRY_HOME="$repo_root\.poetry" + (Invoke-WebRequest -Uri https://install.python-poetry.org/ -UseBasicParsing).Content | & $($python) - +} + +Write-Host ">>> Reading Poetry ... " -NoNewline +if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) { + Write-Host "NOT FOUND" + Install-Poetry + Write-Host "INSTALLED" +} else { + Write-Host "OK" +} + +if (-not (Test-Path -PathType Leaf -Path "$($repo_root)\poetry.lock")) { + Write-Host ">>> Installing virtual environment and creating lock." +} else { + Write-Host ">>> Installing virtual environment from lock." +} +$startTime = [int][double]::Parse((Get-Date -UFormat %s)) +& "$env:POETRY_HOME\bin\poetry" install --no-root $poetry_verbosity --ansi +if ($LASTEXITCODE -ne 0) { + Write-Host "!!! ", "Poetry command failed." + Set-Location -Path $current_dir + Exit-WithCode 1 +} +Write-Host ">>> Installing pre-commit hooks ..." +& "$env:POETRY_HOME\bin\poetry" run pre-commit install +if ($LASTEXITCODE -ne 0) { + Write-Host "!!! Installation of pre-commit hooks failed." + Set-Location -Path $current_dir + Exit-WithCode 1 +} + +$endTime = [int][double]::Parse((Get-Date -UFormat %s)) +Set-Location -Path $current_dir +Write-Host ">>> Done in $( $endTime - $startTime ) secs." diff --git a/scripts/setup_env.sh b/scripts/setup_env.sh new file mode 100644 index 0000000000..16298cb8bc --- /dev/null +++ b/scripts/setup_env.sh @@ -0,0 +1,124 @@ +# Colors for terminal + +RST='\033[0m' # Text Reset + +# Regular Colors +Black='\033[0;30m' # Black +Red='\033[0;31m' # Red +Green='\033[0;32m' # Green +Yellow='\033[0;33m' # Yellow +Blue='\033[0;34m' # Blue +Purple='\033[0;35m' # Purple +Cyan='\033[0;36m' # Cyan +White='\033[0;37m' # White + +# Bold +BBlack='\033[1;30m' # Black +BRed='\033[1;31m' # Red +BGreen='\033[1;32m' # Green +BYellow='\033[1;33m' # Yellow +BBlue='\033[1;34m' # Blue +BPurple='\033[1;35m' # Purple +BCyan='\033[1;36m' # Cyan +BWhite='\033[1;37m' # White + +# Bold High Intensity +BIBlack='\033[1;90m' # Black +BIRed='\033[1;91m' # Red +BIGreen='\033[1;92m' # Green +BIYellow='\033[1;93m' # Yellow +BIBlue='\033[1;94m' # Blue +BIPurple='\033[1;95m' # Purple +BICyan='\033[1;96m' # Cyan +BIWhite='\033[1;97m' # White + + +############################################################################## +# Detect required version of python +# Globals: +# colors +# PYTHON +# Arguments: +# None +# Returns: +# None +############################################################################### +detect_python () { + echo -e "${BIGreen}>>>${RST} Using python \c" + command -v python >/dev/null 2>&1 || { echo -e "${BIRed}- NOT FOUND${RST} ${BIYellow}You need Python 3.9 installed to continue.${RST}"; return 1; } + local version_command="import sys;print('{0}.{1}'.format(sys.version_info[0], sys.version_info[1]))" + local python_version="$(python <<< ${version_command})" + oIFS="$IFS" + IFS=. + set -- $python_version + IFS="$oIFS" + if [ "$1" -ge "3" ] && [ "$2" -ge "9" ] ; then + if [ "$2" -gt "9" ] ; then + echo -e "${BIWhite}[${RST} ${BIRed}$1.$2 ${BIWhite}]${RST} - ${BIRed}FAILED${RST} ${BIYellow}Version is new and unsupported, use${RST} ${BIPurple}3.9.x${RST}"; return 1; + else + echo -e "${BIWhite}[${RST} ${BIGreen}$1.$2${RST} ${BIWhite}]${RST}" + fi + else + command -v python >/dev/null 2>&1 || { echo -e "${BIRed}$1.$2$ - ${BIRed}FAILED${RST} ${BIYellow}Version is old and unsupported${RST}"; return 1; } + fi +} + +install_poetry () { + echo -e "${BIGreen}>>>${RST} Installing Poetry ..." + export POETRY_HOME="$repo_root/.poetry" + command -v curl >/dev/null 2>&1 || { echo -e "${BIRed}!!!${RST}${BIYellow} Missing ${RST}${BIBlue}curl${BIYellow} command.${RST}"; return 1; } + curl -sSL https://install.python-poetry.org/ | python - +} + +############################################################################## +# Return absolute path +# Globals: +# None +# Arguments: +# Path to resolve +# Returns: +# None +############################################################################### +realpath () { + echo $(cd $(dirname "$1"); pwd)/$(basename "$1") +} + +main () { + detect_python || return 1 + + # Directories + repo_root=$(realpath $(dirname $(dirname "${BASH_SOURCE[0]}"))) + + if [[ -z $POETRY_HOME ]]; then + export POETRY_HOME="$repo_root/.poetry" + fi + + pushd "$repo_root" > /dev/null || return > /dev/null + + echo -e "${BIGreen}>>>${RST} Reading Poetry ... \c" + if [ -f "$POETRY_HOME/bin/poetry" ]; then + echo -e "${BIGreen}OK${RST}" + else + echo -e "${BIYellow}NOT FOUND${RST}" + install_poetry || { echo -e "${BIRed}!!!${RST} Poetry installation failed"; return 1; } + fi + + if [ -f "$repo_root/poetry.lock" ]; then + echo -e "${BIGreen}>>>${RST} Updating dependencies ..." + else + echo -e "${BIGreen}>>>${RST} Installing dependencies ..." + fi + + "$POETRY_HOME/bin/poetry" install --no-root $poetry_verbosity || { echo -e "${BIRed}!!!${RST} Poetry environment installation failed"; return 1; } + if [ $? -ne 0 ] ; then + echo -e "${BIRed}!!!${RST} Virtual environment creation failed." + return 1 + fi + + echo -e "${BIGreen}>>>${RST} Installing pre-commit hooks ..." + "$POETRY_HOME/bin/poetry" run pre-commit install +} + +return_code=0 +main || return_code=$? +exit $return_code From 55e8ab0c4d155487474c3bb5791e19001ef5416f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Mon, 18 Mar 2024 14:59:02 +0100 Subject: [PATCH 02/60] :recycle: update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 502cf85b9f..acbc3e2572 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,7 @@ dump.sql # Poetry ######## +.poetry/ .python-version .editorconfig .pre-commit-config.yaml From 84c42d060ed9ff97ec4f73f0858844b33052c7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Mon, 18 Mar 2024 15:00:08 +0100 Subject: [PATCH 03/60] :heavy_plus_sign: add pre-commit --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index c50c0bad5b..14fe5fd1e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,6 +18,7 @@ pynput = "^1.7.2" # Timers manager - TODO remove speedcopy = "^2.1" six = "^1.15" qtawesome = "0.7.3" +pre-commit = "^3.6.2" [tool.poetry.dev-dependencies] From 775d53f4d29edb0d13f86c588aa36f3da111b837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Mon, 18 Mar 2024 15:06:36 +0100 Subject: [PATCH 04/60] :heavy_plus_sign: add codespell and config --- poetry.toml | 2 ++ pyproject.toml | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/poetry.toml b/poetry.toml index e69de29bb2..ab1033bd37 100644 --- a/poetry.toml +++ b/poetry.toml @@ -0,0 +1,2 @@ +[virtualenvs] +in-project = true diff --git a/pyproject.toml b/pyproject.toml index 14fe5fd1e3..f9c0f4602c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,7 @@ speedcopy = "^2.1" six = "^1.15" qtawesome = "0.7.3" pre-commit = "^3.6.2" +codespell = "^2.2.6" [tool.poetry.dev-dependencies] @@ -97,7 +98,7 @@ line-ending = "auto" [tool.codespell] # Ignore words that are not in the dictionary. ignore-words-list = "ayon,ynput" -skip = "./.*,./package/*" +skip = "./.*,./package/*,*/vendor/*,*/unreal/integration/*,*/aftereffects/api/extension/js/libs/*" count = true quiet-level = 3 From 92fc2f230860477ae5d81d9467a9078b979416de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Mon, 18 Mar 2024 15:07:04 +0100 Subject: [PATCH 05/60] :heavy_plus_sign: add `poetry.lock` --- poetry.lock | 1468 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1468 insertions(+) create mode 100644 poetry.lock diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000000..adfa083e82 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,1468 @@ +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. + +[[package]] +name = "aiohttp" +version = "3.9.3" +description = "Async http client/server framework (asyncio)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"}, + {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"}, + {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"}, + {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"}, + {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"}, + {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"}, + {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"}, + {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"}, + {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"}, + {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"}, + {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"}, + {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"}, +] + +[package.dependencies] +aiosignal = ">=1.1.2" +async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} +attrs = ">=17.3.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns", "brotlicffi"] + +[[package]] +name = "aiohttp-json-rpc" +version = "0.13.3" +description = "Implementation JSON-RPC 2.0 server and client using aiohttp on top of websockets transport" +optional = false +python-versions = ">=3.5" +files = [ + {file = "aiohttp-json-rpc-0.13.3.tar.gz", hash = "sha256:6237a104478c22c6ef96c7227a01d6832597b414e4b79a52d85593356a169e99"}, + {file = "aiohttp_json_rpc-0.13.3-py3-none-any.whl", hash = "sha256:4fbd197aced61bd2df7ae3237ead7d3e08833c2ccf48b8581e1828c95ebee680"}, +] + +[package.dependencies] +aiohttp = ">=3,<4" + +[[package]] +name = "aiohttp-middlewares" +version = "2.3.0" +description = "Collection of useful middlewares for aiohttp applications." +optional = false +python-versions = ">=3.8,<4.0" +files = [ + {file = "aiohttp_middlewares-2.3.0-py3-none-any.whl", hash = "sha256:4424b136a351b67b4c93da7d7505b56a342addaa324be30793f6cba463d18ac8"}, + {file = "aiohttp_middlewares-2.3.0.tar.gz", hash = "sha256:b2564c1dfa8dbcf7d2e101a6a03dcaad45464744531c269e8e582cb2dc551d08"}, +] + +[package.dependencies] +aiohttp = ">=3.8.1,<4.0.0" +async-timeout = ">=4.0.2,<5.0.0" +yarl = ">=1.5.1,<2.0.0" + +[[package]] +name = "aiosignal" +version = "1.3.1" +description = "aiosignal: a list of registered asynchronous callbacks" +optional = false +python-versions = ">=3.7" +files = [ + {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, + {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" + +[[package]] +name = "appdirs" +version = "1.4.4" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = "*" +files = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] + +[[package]] +name = "arrow" +version = "1.3.0" +description = "Better dates & times for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80"}, + {file = "arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85"}, +] + +[package.dependencies] +python-dateutil = ">=2.7.0" +types-python-dateutil = ">=2.8.10" + +[package.extras] +doc = ["doc8", "sphinx (>=7.0.0)", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx_rtd_theme (>=1.3.0)"] +test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (==3.*)"] + +[[package]] +name = "async-timeout" +version = "4.0.3" +description = "Timeout context manager for asyncio programs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, +] + +[[package]] +name = "attrs" +version = "23.2.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] + +[[package]] +name = "ayon-python-api" +version = "1.0.1" +description = "AYON Python API" +optional = false +python-versions = "*" +files = [ + {file = "ayon-python-api-1.0.1.tar.gz", hash = "sha256:6a53af84903317e2097f3c6bba0094e90d905d6670fb9c7d3ad3aa9de6552bc1"}, + {file = "ayon_python_api-1.0.1-py3-none-any.whl", hash = "sha256:d4b649ac39c9003cdbd60f172c0d35f05d310fba3a0649b6d16300fe67f967d6"}, +] + +[package.dependencies] +appdirs = ">=1,<2" +requests = ">=2.27.1" +six = ">=1.15" +Unidecode = ">=1.2.0" + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "clique" +version = "1.6.1" +description = "Manage collections with common numerical component" +optional = false +python-versions = ">=2.7, <4.0" +files = [ + {file = "clique-1.6.1-py2.py3-none-any.whl", hash = "sha256:8619774fa035661928dd8c93cd805acf2d42533ccea1b536c09815ed426c9858"}, + {file = "clique-1.6.1.tar.gz", hash = "sha256:90165c1cf162d4dd1baef83ceaa1afc886b453e379094fa5b60ea470d1733e66"}, +] + +[package.extras] +dev = ["lowdown (>=0.2.0,<1)", "pytest (>=2.3.5,<5)", "pytest-cov (>=2,<3)", "pytest-runner (>=2.7,<3)", "sphinx (>=2,<4)", "sphinx-rtd-theme (>=0.1.6,<1)"] +doc = ["lowdown (>=0.2.0,<1)", "sphinx (>=2,<4)", "sphinx-rtd-theme (>=0.1.6,<1)"] +test = ["pytest (>=2.3.5,<5)", "pytest-cov (>=2,<3)", "pytest-runner (>=2.7,<3)"] + +[[package]] +name = "codespell" +version = "2.2.6" +description = "Codespell" +optional = false +python-versions = ">=3.8" +files = [ + {file = "codespell-2.2.6-py3-none-any.whl", hash = "sha256:9ee9a3e5df0990604013ac2a9f22fa8e57669c827124a2e961fe8a1da4cacc07"}, + {file = "codespell-2.2.6.tar.gz", hash = "sha256:a8c65d8eb3faa03deabab6b3bbe798bea72e1799c7e9e955d57eca4096abcff9"}, +] + +[package.extras] +dev = ["Pygments", "build", "chardet", "pre-commit", "pytest", "pytest-cov", "pytest-dependency", "ruff", "tomli", "twine"] +hard-encoding-detection = ["chardet"] +toml = ["tomli"] +types = ["chardet (>=5.1.0)", "mypy", "pytest", "pytest-cov", "pytest-dependency"] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "distlib" +version = "0.3.8" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, + {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, +] + +[[package]] +name = "evdev" +version = "1.7.0" +description = "Bindings to the Linux input handling subsystem" +optional = false +python-versions = ">=3.6" +files = [ + {file = "evdev-1.7.0.tar.gz", hash = "sha256:95bd2a1e0c6ce2cd7a2ecc6e6cd9736ff794b3ad5cb54d81d8cbc2e414d0b870"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "filelock" +version = "3.13.1" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, + {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] + +[[package]] +name = "frozenlist" +version = "1.4.1" +description = "A list-like structure which implements collections.abc.MutableSequence" +optional = false +python-versions = ">=3.8" +files = [ + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, + {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, + {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, + {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, + {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, + {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, + {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, + {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, + {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, + {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, + {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, + {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, + {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, +] + +[[package]] +name = "identify" +version = "2.5.35" +description = "File identification library for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "identify-2.5.35-py2.py3-none-any.whl", hash = "sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e"}, + {file = "identify-2.5.35.tar.gz", hash = "sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791"}, +] + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "idna" +version = "3.6" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "jsonschema" +version = "4.21.1" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema-4.21.1-py3-none-any.whl", hash = "sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f"}, + {file = "jsonschema-4.21.1.tar.gz", hash = "sha256:85727c00279f5fa6bedbe6238d2aa6403bedd8b4864ab11207d07df3cc1b2ee5"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "jsonschema-specifications" +version = "2023.12.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, + {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, +] + +[package.dependencies] +referencing = ">=0.31.0" + +[[package]] +name = "multidict" +version = "6.0.5" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, +] + +[[package]] +name = "nodeenv" +version = "1.8.0" +description = "Node.js virtual environment builder" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +files = [ + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, +] + +[package.dependencies] +setuptools = "*" + +[[package]] +name = "packaging" +version = "24.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, + {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, +] + +[[package]] +name = "platformdirs" +version = "4.2.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] + +[[package]] +name = "pluggy" +version = "1.4.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pre-commit" +version = "3.6.2" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.9" +files = [ + {file = "pre_commit-3.6.2-py2.py3-none-any.whl", hash = "sha256:ba637c2d7a670c10daedc059f5c49b5bd0aadbccfcd7ec15592cf9665117532c"}, + {file = "pre_commit-3.6.2.tar.gz", hash = "sha256:c3ef34f463045c88658c5b99f38c1e297abdcc0ff13f98d3370055fbbfabc67e"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + +[[package]] +name = "pyblish-base" +version = "1.8.11" +description = "Plug-in driven automation framework for content" +optional = false +python-versions = "*" +files = [ + {file = "pyblish-base-1.8.11.tar.gz", hash = "sha256:86dfeec0567430eb7eb25f89a18312054147a729ec66f6ac8c7e421fd15b66e1"}, + {file = "pyblish_base-1.8.11-py2.py3-none-any.whl", hash = "sha256:c321be7020c946fe9dfa11941241bd985a572c5009198b4f9810e5afad1f0b4b"}, +] + +[[package]] +name = "pynput" +version = "1.7.6" +description = "Monitor and control user input devices" +optional = false +python-versions = "*" +files = [ + {file = "pynput-1.7.6-py2.py3-none-any.whl", hash = "sha256:19861b2a0c430d646489852f89500e0c9332e295f2c020e7c2775e7046aa2e2f"}, + {file = "pynput-1.7.6.tar.gz", hash = "sha256:3a5726546da54116b687785d38b1db56997ce1d28e53e8d22fc656d8b92e533c"}, +] + +[package.dependencies] +evdev = {version = ">=1.3", markers = "sys_platform in \"linux\""} +pyobjc-framework-ApplicationServices = {version = ">=8.0", markers = "sys_platform == \"darwin\""} +pyobjc-framework-Quartz = {version = ">=8.0", markers = "sys_platform == \"darwin\""} +python-xlib = {version = ">=0.17", markers = "sys_platform in \"linux\""} +six = "*" + +[[package]] +name = "pyobjc-core" +version = "10.2" +description = "Python<->ObjC Interoperability Module" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyobjc-core-10.2.tar.gz", hash = "sha256:0153206e15d0e0d7abd53ee8a7fbaf5606602a032e177a028fc8589516a8771c"}, + {file = "pyobjc_core-10.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b8eab50ce7f17017a0f1d68c3b7e88bb1bb033415fdff62b8e0a9ee4ab72f242"}, + {file = "pyobjc_core-10.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f2115971463073426ab926416e17e5c16de5b90d1a1f2a2d8724637eb1c21308"}, + {file = "pyobjc_core-10.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a70546246177c23acb323c9324330e37638f1a0a3d13664abcba3bb75e43012c"}, + {file = "pyobjc_core-10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a9b5a215080d13bd7526031d21d5eb27a410780878d863f486053a0eba7ca9a5"}, + {file = "pyobjc_core-10.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:eb1ab700a44bcc4ceb125091dfaae0b998b767b49990df5fdc83eb58158d8e3f"}, + {file = "pyobjc_core-10.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9a7163aff9c47d654f835f80361c1b112886ec754800d34e75d1e02ff52c3d7"}, +] + +[[package]] +name = "pyobjc-framework-applicationservices" +version = "10.2" +description = "Wrappers for the framework ApplicationServices on macOS" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyobjc-framework-ApplicationServices-10.2.tar.gz", hash = "sha256:f83d6ed3320afb6648be6defafe0f05bac00d0281fc84ee4766ff977309b659f"}, + {file = "pyobjc_framework_ApplicationServices-10.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2aebfed888f9bcb4f11d93f9ef9a76d561e92848dcb6011da5d5e9d3593371be"}, + {file = "pyobjc_framework_ApplicationServices-10.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:edfd3153e64ee9573bcff7ccaa1fbbbd6964658f187464c461ad34f24552bc85"}, + {file = "pyobjc_framework_ApplicationServices-10.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d2c89b246c19a041221ff36e9121c92e86a4422016f809a40f5ce3d647882d9"}, + {file = "pyobjc_framework_ApplicationServices-10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ee1e69947f31aad5fdec44921ce37f7f921faf50a0ceb27ed40b6d54f4b15d0e"}, + {file = "pyobjc_framework_ApplicationServices-10.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:101f5b09d71e55bd39e6e91f0787433805d422622336b72fde969a7c54528045"}, + {file = "pyobjc_framework_ApplicationServices-10.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a3ef00c9aea09c5ef5840b8749d0753249869bc30e124145b763cd0b4b81155"}, +] + +[package.dependencies] +pyobjc-core = ">=10.2" +pyobjc-framework-Cocoa = ">=10.2" +pyobjc-framework-CoreText = ">=10.2" +pyobjc-framework-Quartz = ">=10.2" + +[[package]] +name = "pyobjc-framework-cocoa" +version = "10.2" +description = "Wrappers for the Cocoa frameworks on macOS" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyobjc-framework-Cocoa-10.2.tar.gz", hash = "sha256:6383141379636b13855dca1b39c032752862b829f93a49d7ddb35046abfdc035"}, + {file = "pyobjc_framework_Cocoa-10.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9227b4f271fda2250f5a88cbc686ff30ae02c0f923bb7854bb47972397496b2"}, + {file = "pyobjc_framework_Cocoa-10.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6a6042b7703bdc33b7491959c715c1e810a3f8c7a560c94b36e00ef321480797"}, + {file = "pyobjc_framework_Cocoa-10.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:18886d5013cd7dc7ecd6e0df5134c767569b5247fc10a5e293c72ee3937b217b"}, + {file = "pyobjc_framework_Cocoa-10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ecf01400ee698d2e0ff4c907bcf9608d9d710e97203fbb97b37d208507a9362"}, + {file = "pyobjc_framework_Cocoa-10.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:0def036a7b24e3ae37a244c77bec96b7c9c8384bf6bb4d33369f0a0c8807a70d"}, + {file = "pyobjc_framework_Cocoa-10.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f47ecc393bc1019c4b47e8653207188df784ac006ad54d8c2eb528906ff7013"}, +] + +[package.dependencies] +pyobjc-core = ">=10.2" + +[[package]] +name = "pyobjc-framework-coretext" +version = "10.2" +description = "Wrappers for the framework CoreText on macOS" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyobjc-framework-CoreText-10.2.tar.gz", hash = "sha256:59ef8ca8d88bb53ce9980dda0b8094daa3e2dabe355847365ba965ff0b49f961"}, + {file = "pyobjc_framework_CoreText-10.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:44052f752f42b62d342fa8aced5d1b8928831e70830eccddc594726d40500d5c"}, + {file = "pyobjc_framework_CoreText-10.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0bc278f509a3fd3eea89124d81e77de11af10167c0df0d0cc15a369f060465a0"}, + {file = "pyobjc_framework_CoreText-10.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7b819119dc859e49c0ce9040ae09d6a3bd66658003793f486ef5a21e46a2d34f"}, + {file = "pyobjc_framework_CoreText-10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2719c57ff08af6e4fdcddd0fa5eda56113808a1690c3325f1c6926740817f9a1"}, + {file = "pyobjc_framework_CoreText-10.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:8239ce92f9496587a60fc1bfd4994136832bad99405bb45572f92d960cbe746e"}, + {file = "pyobjc_framework_CoreText-10.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:80a1d207fcdb2999841daa430c83d760ac1a3f2f65c605949fc5ff789425b1f6"}, +] + +[package.dependencies] +pyobjc-core = ">=10.2" +pyobjc-framework-Cocoa = ">=10.2" +pyobjc-framework-Quartz = ">=10.2" + +[[package]] +name = "pyobjc-framework-quartz" +version = "10.2" +description = "Wrappers for the Quartz frameworks on macOS" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyobjc-framework-Quartz-10.2.tar.gz", hash = "sha256:9b947e081f5bd6cd01c99ab5d62c36500d2d6e8d3b87421c1cbb7f9c885555eb"}, + {file = "pyobjc_framework_Quartz-10.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bc0ab739259a717d9d13a739434991b54eb8963ad7c27f9f6d04d68531fb479b"}, + {file = "pyobjc_framework_Quartz-10.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2a74d00e933c1e1a1820839323dc5cf252bee8bb98e2a298d961f7ae7905ce71"}, + {file = "pyobjc_framework_Quartz-10.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3e8e33246d966c2bd7f5ee2cf3b431582fa434a6ec2b6dbe580045ebf1f55be5"}, + {file = "pyobjc_framework_Quartz-10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c6ca490eff1be0dd8dc7726edde79c97e21ec1afcf55f75962a79e27b4eb2961"}, + {file = "pyobjc_framework_Quartz-10.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d3d54d9fa50de09ee8994248151def58f30b4738eb20755b0bdd5ee1e1f5883d"}, + {file = "pyobjc_framework_Quartz-10.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:520c8031b2389110f80070b078dde1968caaecb10921f8070046c26132ac9286"}, +] + +[package.dependencies] +pyobjc-core = ">=10.2" +pyobjc-framework-Cocoa = ">=10.2" + +[[package]] +name = "pytest" +version = "8.1.1" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"}, + {file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=1.4,<2.0" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-print" +version = "1.0.0" +description = "pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_print-1.0.0-py3-none-any.whl", hash = "sha256:23484f42b906b87e31abd564761efffeb0348a6f83109fb857ee6e8e5df42b69"}, + {file = "pytest_print-1.0.0.tar.gz", hash = "sha256:1fcde9945fba462227a8959271369b10bb7a193be8452162707e63cd60875ca0"}, +] + +[package.dependencies] +pytest = ">=7.4" + +[package.extras] +test = ["covdefaults (>=2.3)", "coverage (>=7.3)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-xlib" +version = "0.33" +description = "Python X Library" +optional = false +python-versions = "*" +files = [ + {file = "python-xlib-0.33.tar.gz", hash = "sha256:55af7906a2c75ce6cb280a584776080602444f75815a7aff4d287bb2d7018b32"}, + {file = "python_xlib-0.33-py2.py3-none-any.whl", hash = "sha256:c3534038d42e0df2f1392a1b30a15a4ff5fdc2b86cfa94f072bf11b10a164398"}, +] + +[package.dependencies] +six = ">=1.10.0" + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "qtawesome" +version = "0.7.3" +description = "FontAwesome icons in PyQt and PySide applications" +optional = false +python-versions = "*" +files = [ + {file = "QtAwesome-0.7.3-py2.py3-none-any.whl", hash = "sha256:ddf4530b4af71cec13b24b88a4cdb56ec85b1e44c43c42d0698804c7137b09b0"}, + {file = "QtAwesome-0.7.3.tar.gz", hash = "sha256:b98b9038d19190e83ab26d91c4d8fc3a36591ee2bc7f5016d4438b8240d097bd"}, +] + +[package.dependencies] +qtpy = "*" +six = "*" + +[[package]] +name = "qtpy" +version = "2.4.1" +description = "Provides an abstraction layer on top of the various Qt bindings (PyQt5/6 and PySide2/6)." +optional = false +python-versions = ">=3.7" +files = [ + {file = "QtPy-2.4.1-py3-none-any.whl", hash = "sha256:1c1d8c4fa2c884ae742b069151b0abe15b3f70491f3972698c683b8e38de839b"}, + {file = "QtPy-2.4.1.tar.gz", hash = "sha256:a5a15ffd519550a1361bdc56ffc07fda56a6af7292f17c7b395d4083af632987"}, +] + +[package.dependencies] +packaging = "*" + +[package.extras] +test = ["pytest (>=6,!=7.0.0,!=7.0.1)", "pytest-cov (>=3.0.0)", "pytest-qt"] + +[[package]] +name = "referencing" +version = "0.34.0" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.34.0-py3-none-any.whl", hash = "sha256:d53ae300ceddd3169f1ffa9caf2cb7b769e92657e4fafb23d34b93679116dfd4"}, + {file = "referencing-0.34.0.tar.gz", hash = "sha256:5773bd84ef41799a5a8ca72dc34590c041eb01bf9aa02632b4a973fb0181a844"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "rpds-py" +version = "0.18.0" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.18.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88"}, + {file = "rpds_py-0.18.0-cp310-none-win32.whl", hash = "sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337"}, + {file = "rpds_py-0.18.0-cp310-none-win_amd64.whl", hash = "sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836"}, + {file = "rpds_py-0.18.0-cp311-none-win32.whl", hash = "sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1"}, + {file = "rpds_py-0.18.0-cp311-none-win_amd64.whl", hash = "sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7"}, + {file = "rpds_py-0.18.0-cp312-none-win32.whl", hash = "sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98"}, + {file = "rpds_py-0.18.0-cp312-none-win_amd64.whl", hash = "sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594"}, + {file = "rpds_py-0.18.0-cp38-none-win32.whl", hash = "sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e"}, + {file = "rpds_py-0.18.0-cp38-none-win_amd64.whl", hash = "sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20"}, + {file = "rpds_py-0.18.0-cp39-none-win32.whl", hash = "sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7"}, + {file = "rpds_py-0.18.0-cp39-none-win_amd64.whl", hash = "sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f"}, + {file = "rpds_py-0.18.0.tar.gz", hash = "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d"}, +] + +[[package]] +name = "ruff" +version = "0.2.2" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0a9efb032855ffb3c21f6405751d5e147b0c6b631e3ca3f6b20f917572b97eb6"}, + {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d450b7fbff85913f866a5384d8912710936e2b96da74541c82c1b458472ddb39"}, + {file = "ruff-0.2.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecd46e3106850a5c26aee114e562c329f9a1fbe9e4821b008c4404f64ff9ce73"}, + {file = "ruff-0.2.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e22676a5b875bd72acd3d11d5fa9075d3a5f53b877fe7b4793e4673499318ba"}, + {file = "ruff-0.2.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1695700d1e25a99d28f7a1636d85bafcc5030bba9d0578c0781ba1790dbcf51c"}, + {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b0c232af3d0bd8f521806223723456ffebf8e323bd1e4e82b0befb20ba18388e"}, + {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f63d96494eeec2fc70d909393bcd76c69f35334cdbd9e20d089fb3f0640216ca"}, + {file = "ruff-0.2.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a61ea0ff048e06de273b2e45bd72629f470f5da8f71daf09fe481278b175001"}, + {file = "ruff-0.2.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1439c8f407e4f356470e54cdecdca1bd5439a0673792dbe34a2b0a551a2fe3"}, + {file = "ruff-0.2.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:940de32dc8853eba0f67f7198b3e79bc6ba95c2edbfdfac2144c8235114d6726"}, + {file = "ruff-0.2.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0c126da55c38dd917621552ab430213bdb3273bb10ddb67bc4b761989210eb6e"}, + {file = "ruff-0.2.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3b65494f7e4bed2e74110dac1f0d17dc8e1f42faaa784e7c58a98e335ec83d7e"}, + {file = "ruff-0.2.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1ec49be4fe6ddac0503833f3ed8930528e26d1e60ad35c2446da372d16651ce9"}, + {file = "ruff-0.2.2-py3-none-win32.whl", hash = "sha256:d920499b576f6c68295bc04e7b17b6544d9d05f196bb3aac4358792ef6f34325"}, + {file = "ruff-0.2.2-py3-none-win_amd64.whl", hash = "sha256:cc9a91ae137d687f43a44c900e5d95e9617cb37d4c989e462980ba27039d239d"}, + {file = "ruff-0.2.2-py3-none-win_arm64.whl", hash = "sha256:c9d15fc41e6054bfc7200478720570078f0b41c9ae4f010bcc16bd6f4d1aacdd"}, + {file = "ruff-0.2.2.tar.gz", hash = "sha256:e62ed7f36b3068a30ba39193a14274cd706bc486fad521276458022f7bccb31d"}, +] + +[[package]] +name = "setuptools" +version = "69.2.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-69.2.0-py3-none-any.whl", hash = "sha256:c21c49fb1042386df081cb5d86759792ab89efca84cf114889191cd09aacc80c"}, + {file = "setuptools-69.2.0.tar.gz", hash = "sha256:0ff4183f8f42cd8fa3acea16c45205521a4ef28f73c6391d8a25e92893134f2e"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "speedcopy" +version = "2.1.5" +description = "Replacement or alternative for python copyfile() utilizing server side copy on network shares for faster copying." +optional = false +python-versions = "*" +files = [ + {file = "speedcopy-2.1.5-py3-none-any.whl", hash = "sha256:903d0b466c2bef7c07dfac17493cdfbc09aadd70e947199c81caa6c6da2c095f"}, + {file = "speedcopy-2.1.5.tar.gz", hash = "sha256:9d6c482300791f02462ad451730ae247901978eae9e25290ca352de964698c82"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "types-python-dateutil" +version = "2.9.0.20240316" +description = "Typing stubs for python-dateutil" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-python-dateutil-2.9.0.20240316.tar.gz", hash = "sha256:5d2f2e240b86905e40944dd787db6da9263f0deabef1076ddaed797351ec0202"}, + {file = "types_python_dateutil-2.9.0.20240316-py3-none-any.whl", hash = "sha256:6b8cb66d960771ce5ff974e9dd45e38facb81718cc1e208b10b1baccbfdbee3b"}, +] + +[[package]] +name = "unidecode" +version = "1.3.8" +description = "ASCII transliterations of Unicode text" +optional = false +python-versions = ">=3.5" +files = [ + {file = "Unidecode-1.3.8-py3-none-any.whl", hash = "sha256:d130a61ce6696f8148a3bd8fe779c99adeb4b870584eeb9526584e9aa091fd39"}, + {file = "Unidecode-1.3.8.tar.gz", hash = "sha256:cfdb349d46ed3873ece4586b96aa75258726e2fa8ec21d6f00a591d98806c2f4"}, +] + +[[package]] +name = "urllib3" +version = "2.2.1" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "virtualenv" +version = "20.25.1" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.25.1-py3-none-any.whl", hash = "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a"}, + {file = "virtualenv-20.25.1.tar.gz", hash = "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + +[[package]] +name = "wsrpc-aiohttp" +version = "3.2.0" +description = "WSRPC is the RPC over WebSocket for aiohttp" +optional = false +python-versions = ">3.5.*, <4" +files = [ + {file = "wsrpc-aiohttp-3.2.0.tar.gz", hash = "sha256:f467abc51bcdc760fc5aeb7041abdeef46eeca3928dc43dd6e7fa7a533563818"}, + {file = "wsrpc_aiohttp-3.2.0-py3-none-any.whl", hash = "sha256:fa9b0bf5cb056898cb5c9f64cbc5eacb8a5dd18ab1b7f0cd4a2208b4a7fde282"}, +] + +[package.dependencies] +aiohttp = "<4" +yarl = "*" + +[package.extras] +develop = ["Sphinx", "async-timeout", "coverage (!=4.3)", "coveralls", "pytest", "pytest-aiohttp", "pytest-cov", "sphinxcontrib-plantuml", "tox (>=2.4)"] +testing = ["async-timeout", "coverage (!=4.3)", "coveralls", "pytest", "pytest-aiohttp", "pytest-cov"] +ujson = ["ujson"] + +[[package]] +name = "yarl" +version = "1.9.4" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, + {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, + {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, + {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, + {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, + {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, + {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, + {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, + {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, + {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, + {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, + {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, + {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, + {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, + {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, + {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + +[metadata] +lock-version = "2.0" +python-versions = ">=3.9.1,<3.10" +content-hash = "9904c684f7885d871c560a189ff074527231d44f7bf4b221290ae646102f00f1" From 0e6c050618322244f37fea0ccb0cc688f9dd003b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Mon, 18 Mar 2024 15:28:33 +0100 Subject: [PATCH 06/60] :recycle: update ruff and fix python version --- poetry.lock | 38 +++++++++++++++++++------------------- pyproject.toml | 4 ++-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/poetry.lock b/poetry.lock index adfa083e82..d2476400f7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1207,28 +1207,28 @@ files = [ [[package]] name = "ruff" -version = "0.2.2" +version = "0.3.3" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0a9efb032855ffb3c21f6405751d5e147b0c6b631e3ca3f6b20f917572b97eb6"}, - {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d450b7fbff85913f866a5384d8912710936e2b96da74541c82c1b458472ddb39"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecd46e3106850a5c26aee114e562c329f9a1fbe9e4821b008c4404f64ff9ce73"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e22676a5b875bd72acd3d11d5fa9075d3a5f53b877fe7b4793e4673499318ba"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1695700d1e25a99d28f7a1636d85bafcc5030bba9d0578c0781ba1790dbcf51c"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b0c232af3d0bd8f521806223723456ffebf8e323bd1e4e82b0befb20ba18388e"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f63d96494eeec2fc70d909393bcd76c69f35334cdbd9e20d089fb3f0640216ca"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a61ea0ff048e06de273b2e45bd72629f470f5da8f71daf09fe481278b175001"}, - {file = "ruff-0.2.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1439c8f407e4f356470e54cdecdca1bd5439a0673792dbe34a2b0a551a2fe3"}, - {file = "ruff-0.2.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:940de32dc8853eba0f67f7198b3e79bc6ba95c2edbfdfac2144c8235114d6726"}, - {file = "ruff-0.2.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0c126da55c38dd917621552ab430213bdb3273bb10ddb67bc4b761989210eb6e"}, - {file = "ruff-0.2.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3b65494f7e4bed2e74110dac1f0d17dc8e1f42faaa784e7c58a98e335ec83d7e"}, - {file = "ruff-0.2.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1ec49be4fe6ddac0503833f3ed8930528e26d1e60ad35c2446da372d16651ce9"}, - {file = "ruff-0.2.2-py3-none-win32.whl", hash = "sha256:d920499b576f6c68295bc04e7b17b6544d9d05f196bb3aac4358792ef6f34325"}, - {file = "ruff-0.2.2-py3-none-win_amd64.whl", hash = "sha256:cc9a91ae137d687f43a44c900e5d95e9617cb37d4c989e462980ba27039d239d"}, - {file = "ruff-0.2.2-py3-none-win_arm64.whl", hash = "sha256:c9d15fc41e6054bfc7200478720570078f0b41c9ae4f010bcc16bd6f4d1aacdd"}, - {file = "ruff-0.2.2.tar.gz", hash = "sha256:e62ed7f36b3068a30ba39193a14274cd706bc486fad521276458022f7bccb31d"}, + {file = "ruff-0.3.3-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:973a0e388b7bc2e9148c7f9be8b8c6ae7471b9be37e1cc732f8f44a6f6d7720d"}, + {file = "ruff-0.3.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:cfa60d23269d6e2031129b053fdb4e5a7b0637fc6c9c0586737b962b2f834493"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1eca7ff7a47043cf6ce5c7f45f603b09121a7cc047447744b029d1b719278eb5"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7d3f6762217c1da954de24b4a1a70515630d29f71e268ec5000afe81377642d"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b24c19e8598916d9c6f5a5437671f55ee93c212a2c4c569605dc3842b6820386"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5a6cbf216b69c7090f0fe4669501a27326c34e119068c1494f35aaf4cc683778"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:352e95ead6964974b234e16ba8a66dad102ec7bf8ac064a23f95371d8b198aab"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d6ab88c81c4040a817aa432484e838aaddf8bfd7ca70e4e615482757acb64f8"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79bca3a03a759cc773fca69e0bdeac8abd1c13c31b798d5bb3c9da4a03144a9f"}, + {file = "ruff-0.3.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:2700a804d5336bcffe063fd789ca2c7b02b552d2e323a336700abb8ae9e6a3f8"}, + {file = "ruff-0.3.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fd66469f1a18fdb9d32e22b79f486223052ddf057dc56dea0caaf1a47bdfaf4e"}, + {file = "ruff-0.3.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:45817af234605525cdf6317005923bf532514e1ea3d9270acf61ca2440691376"}, + {file = "ruff-0.3.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0da458989ce0159555ef224d5b7c24d3d2e4bf4c300b85467b08c3261c6bc6a8"}, + {file = "ruff-0.3.3-py3-none-win32.whl", hash = "sha256:f2831ec6a580a97f1ea82ea1eda0401c3cdf512cf2045fa3c85e8ef109e87de0"}, + {file = "ruff-0.3.3-py3-none-win_amd64.whl", hash = "sha256:be90bcae57c24d9f9d023b12d627e958eb55f595428bafcb7fec0791ad25ddfc"}, + {file = "ruff-0.3.3-py3-none-win_arm64.whl", hash = "sha256:0171aab5fecdc54383993389710a3d1227f2da124d76a2784a7098e818f92d61"}, + {file = "ruff-0.3.3.tar.gz", hash = "sha256:38671be06f57a2f8aba957d9f701ea889aa5736be806f18c0cd03d6ff0cbca8d"}, ] [[package]] @@ -1465,4 +1465,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.9.1,<3.10" -content-hash = "9904c684f7885d871c560a189ff074527231d44f7bf4b221290ae646102f00f1" +content-hash = "8a62cc31c960aff7e5df7bfdc5b65790e57bf0e7a87fedd16a68ababa49268c8" diff --git a/pyproject.toml b/pyproject.toml index f9c0f4602c..29213281af 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ pytest = "^8.0" pytest-print = "^1.0" ayon-python-api = "^1.0" arrow = "^1.3.0" -ruff = "^0.2.2" +ruff = "^0.3.3" [tool.ruff] @@ -67,7 +67,7 @@ exclude = [ line-length = 79 indent-width = 4 -# Assume Python 3.8 +# Assume Python 3.9 target-version = "py39" [tool.ruff.lint] From ab71411d122220ecd2edf4d5bde4ebe04f1a889e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Tue, 19 Mar 2024 11:37:15 +0100 Subject: [PATCH 07/60] :recycle: remove unneeded dependencies --- poetry.lock | 906 +------------------------------------------------ pyproject.toml | 18 +- 2 files changed, 5 insertions(+), 919 deletions(-) diff --git a/poetry.lock b/poetry.lock index d2476400f7..be5a3b2c2c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,145 +1,5 @@ # This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. -[[package]] -name = "aiohttp" -version = "3.9.3" -description = "Async http client/server framework (asyncio)" -optional = false -python-versions = ">=3.8" -files = [ - {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"}, - {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"}, - {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"}, - {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"}, - {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"}, - {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"}, - {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"}, - {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"}, - {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"}, - {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"}, - {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"}, - {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"}, - {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"}, - {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"}, - {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"}, - {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"}, - {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"}, - {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"}, - {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"}, - {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"}, - {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"}, - {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"}, - {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"}, - {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"}, - {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"}, - {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"}, - {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"}, - {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"}, - {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"}, - {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"}, - {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"}, - {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"}, - {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"}, - {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"}, - {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"}, - {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"}, - {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"}, - {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"}, - {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"}, - {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"}, - {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"}, - {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"}, - {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"}, - {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"}, - {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"}, - {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"}, - {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"}, - {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"}, - {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"}, - {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"}, - {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"}, - {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"}, - {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"}, - {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"}, - {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"}, - {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"}, - {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"}, - {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"}, - {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"}, - {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"}, - {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"}, - {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"}, - {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"}, - {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"}, - {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"}, - {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"}, - {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"}, - {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"}, - {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"}, - {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"}, - {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"}, - {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"}, - {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"}, - {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"}, - {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"}, - {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"}, -] - -[package.dependencies] -aiosignal = ">=1.1.2" -async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} -attrs = ">=17.3.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -yarl = ">=1.0,<2.0" - -[package.extras] -speedups = ["Brotli", "aiodns", "brotlicffi"] - -[[package]] -name = "aiohttp-json-rpc" -version = "0.13.3" -description = "Implementation JSON-RPC 2.0 server and client using aiohttp on top of websockets transport" -optional = false -python-versions = ">=3.5" -files = [ - {file = "aiohttp-json-rpc-0.13.3.tar.gz", hash = "sha256:6237a104478c22c6ef96c7227a01d6832597b414e4b79a52d85593356a169e99"}, - {file = "aiohttp_json_rpc-0.13.3-py3-none-any.whl", hash = "sha256:4fbd197aced61bd2df7ae3237ead7d3e08833c2ccf48b8581e1828c95ebee680"}, -] - -[package.dependencies] -aiohttp = ">=3,<4" - -[[package]] -name = "aiohttp-middlewares" -version = "2.3.0" -description = "Collection of useful middlewares for aiohttp applications." -optional = false -python-versions = ">=3.8,<4.0" -files = [ - {file = "aiohttp_middlewares-2.3.0-py3-none-any.whl", hash = "sha256:4424b136a351b67b4c93da7d7505b56a342addaa324be30793f6cba463d18ac8"}, - {file = "aiohttp_middlewares-2.3.0.tar.gz", hash = "sha256:b2564c1dfa8dbcf7d2e101a6a03dcaad45464744531c269e8e582cb2dc551d08"}, -] - -[package.dependencies] -aiohttp = ">=3.8.1,<4.0.0" -async-timeout = ">=4.0.2,<5.0.0" -yarl = ">=1.5.1,<2.0.0" - -[[package]] -name = "aiosignal" -version = "1.3.1" -description = "aiosignal: a list of registered asynchronous callbacks" -optional = false -python-versions = ">=3.7" -files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, -] - -[package.dependencies] -frozenlist = ">=1.1.0" - [[package]] name = "appdirs" version = "1.4.4" @@ -151,55 +11,6 @@ files = [ {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] -[[package]] -name = "arrow" -version = "1.3.0" -description = "Better dates & times for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80"}, - {file = "arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85"}, -] - -[package.dependencies] -python-dateutil = ">=2.7.0" -types-python-dateutil = ">=2.8.10" - -[package.extras] -doc = ["doc8", "sphinx (>=7.0.0)", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx_rtd_theme (>=1.3.0)"] -test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (==3.*)"] - -[[package]] -name = "async-timeout" -version = "4.0.3" -description = "Timeout context manager for asyncio programs" -optional = false -python-versions = ">=3.7" -files = [ - {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, - {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, -] - -[[package]] -name = "attrs" -version = "23.2.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.7" -files = [ - {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, - {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, -] - -[package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] -tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] - [[package]] name = "ayon-python-api" version = "1.0.1" @@ -338,36 +149,6 @@ files = [ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "clique" -version = "1.6.1" -description = "Manage collections with common numerical component" -optional = false -python-versions = ">=2.7, <4.0" -files = [ - {file = "clique-1.6.1-py2.py3-none-any.whl", hash = "sha256:8619774fa035661928dd8c93cd805acf2d42533ccea1b536c09815ed426c9858"}, - {file = "clique-1.6.1.tar.gz", hash = "sha256:90165c1cf162d4dd1baef83ceaa1afc886b453e379094fa5b60ea470d1733e66"}, -] - -[package.extras] -dev = ["lowdown (>=0.2.0,<1)", "pytest (>=2.3.5,<5)", "pytest-cov (>=2,<3)", "pytest-runner (>=2.7,<3)", "sphinx (>=2,<4)", "sphinx-rtd-theme (>=0.1.6,<1)"] -doc = ["lowdown (>=0.2.0,<1)", "sphinx (>=2,<4)", "sphinx-rtd-theme (>=0.1.6,<1)"] -test = ["pytest (>=2.3.5,<5)", "pytest-cov (>=2,<3)", "pytest-runner (>=2.7,<3)"] - [[package]] name = "codespell" version = "2.2.6" @@ -407,16 +188,6 @@ files = [ {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, ] -[[package]] -name = "evdev" -version = "1.7.0" -description = "Bindings to the Linux input handling subsystem" -optional = false -python-versions = ">=3.6" -files = [ - {file = "evdev-1.7.0.tar.gz", hash = "sha256:95bd2a1e0c6ce2cd7a2ecc6e6cd9736ff794b3ad5cb54d81d8cbc2e414d0b870"}, -] - [[package]] name = "exceptiongroup" version = "1.2.0" @@ -447,92 +218,6 @@ docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1 testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] -[[package]] -name = "frozenlist" -version = "1.4.1" -description = "A list-like structure which implements collections.abc.MutableSequence" -optional = false -python-versions = ">=3.8" -files = [ - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, - {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, - {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, - {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, - {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, - {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, - {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, - {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, - {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, - {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, - {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, - {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, - {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, -] - [[package]] name = "identify" version = "2.5.35" @@ -569,140 +254,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "jsonschema" -version = "4.21.1" -description = "An implementation of JSON Schema validation for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jsonschema-4.21.1-py3-none-any.whl", hash = "sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f"}, - {file = "jsonschema-4.21.1.tar.gz", hash = "sha256:85727c00279f5fa6bedbe6238d2aa6403bedd8b4864ab11207d07df3cc1b2ee5"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -jsonschema-specifications = ">=2023.03.6" -referencing = ">=0.28.4" -rpds-py = ">=0.7.1" - -[package.extras] -format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] - -[[package]] -name = "jsonschema-specifications" -version = "2023.12.1" -description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, - {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, -] - -[package.dependencies] -referencing = ">=0.31.0" - -[[package]] -name = "multidict" -version = "6.0.5" -description = "multidict implementation" -optional = false -python-versions = ">=3.7" -files = [ - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, - {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, - {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, - {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, - {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, - {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, - {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, - {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, - {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, - {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, - {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, - {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, - {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, - {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, - {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, - {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, -] - [[package]] name = "nodeenv" version = "1.8.0" @@ -776,133 +327,6 @@ nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" -[[package]] -name = "pyblish-base" -version = "1.8.11" -description = "Plug-in driven automation framework for content" -optional = false -python-versions = "*" -files = [ - {file = "pyblish-base-1.8.11.tar.gz", hash = "sha256:86dfeec0567430eb7eb25f89a18312054147a729ec66f6ac8c7e421fd15b66e1"}, - {file = "pyblish_base-1.8.11-py2.py3-none-any.whl", hash = "sha256:c321be7020c946fe9dfa11941241bd985a572c5009198b4f9810e5afad1f0b4b"}, -] - -[[package]] -name = "pynput" -version = "1.7.6" -description = "Monitor and control user input devices" -optional = false -python-versions = "*" -files = [ - {file = "pynput-1.7.6-py2.py3-none-any.whl", hash = "sha256:19861b2a0c430d646489852f89500e0c9332e295f2c020e7c2775e7046aa2e2f"}, - {file = "pynput-1.7.6.tar.gz", hash = "sha256:3a5726546da54116b687785d38b1db56997ce1d28e53e8d22fc656d8b92e533c"}, -] - -[package.dependencies] -evdev = {version = ">=1.3", markers = "sys_platform in \"linux\""} -pyobjc-framework-ApplicationServices = {version = ">=8.0", markers = "sys_platform == \"darwin\""} -pyobjc-framework-Quartz = {version = ">=8.0", markers = "sys_platform == \"darwin\""} -python-xlib = {version = ">=0.17", markers = "sys_platform in \"linux\""} -six = "*" - -[[package]] -name = "pyobjc-core" -version = "10.2" -description = "Python<->ObjC Interoperability Module" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyobjc-core-10.2.tar.gz", hash = "sha256:0153206e15d0e0d7abd53ee8a7fbaf5606602a032e177a028fc8589516a8771c"}, - {file = "pyobjc_core-10.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b8eab50ce7f17017a0f1d68c3b7e88bb1bb033415fdff62b8e0a9ee4ab72f242"}, - {file = "pyobjc_core-10.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f2115971463073426ab926416e17e5c16de5b90d1a1f2a2d8724637eb1c21308"}, - {file = "pyobjc_core-10.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a70546246177c23acb323c9324330e37638f1a0a3d13664abcba3bb75e43012c"}, - {file = "pyobjc_core-10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a9b5a215080d13bd7526031d21d5eb27a410780878d863f486053a0eba7ca9a5"}, - {file = "pyobjc_core-10.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:eb1ab700a44bcc4ceb125091dfaae0b998b767b49990df5fdc83eb58158d8e3f"}, - {file = "pyobjc_core-10.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9a7163aff9c47d654f835f80361c1b112886ec754800d34e75d1e02ff52c3d7"}, -] - -[[package]] -name = "pyobjc-framework-applicationservices" -version = "10.2" -description = "Wrappers for the framework ApplicationServices on macOS" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyobjc-framework-ApplicationServices-10.2.tar.gz", hash = "sha256:f83d6ed3320afb6648be6defafe0f05bac00d0281fc84ee4766ff977309b659f"}, - {file = "pyobjc_framework_ApplicationServices-10.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2aebfed888f9bcb4f11d93f9ef9a76d561e92848dcb6011da5d5e9d3593371be"}, - {file = "pyobjc_framework_ApplicationServices-10.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:edfd3153e64ee9573bcff7ccaa1fbbbd6964658f187464c461ad34f24552bc85"}, - {file = "pyobjc_framework_ApplicationServices-10.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d2c89b246c19a041221ff36e9121c92e86a4422016f809a40f5ce3d647882d9"}, - {file = "pyobjc_framework_ApplicationServices-10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ee1e69947f31aad5fdec44921ce37f7f921faf50a0ceb27ed40b6d54f4b15d0e"}, - {file = "pyobjc_framework_ApplicationServices-10.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:101f5b09d71e55bd39e6e91f0787433805d422622336b72fde969a7c54528045"}, - {file = "pyobjc_framework_ApplicationServices-10.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a3ef00c9aea09c5ef5840b8749d0753249869bc30e124145b763cd0b4b81155"}, -] - -[package.dependencies] -pyobjc-core = ">=10.2" -pyobjc-framework-Cocoa = ">=10.2" -pyobjc-framework-CoreText = ">=10.2" -pyobjc-framework-Quartz = ">=10.2" - -[[package]] -name = "pyobjc-framework-cocoa" -version = "10.2" -description = "Wrappers for the Cocoa frameworks on macOS" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyobjc-framework-Cocoa-10.2.tar.gz", hash = "sha256:6383141379636b13855dca1b39c032752862b829f93a49d7ddb35046abfdc035"}, - {file = "pyobjc_framework_Cocoa-10.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9227b4f271fda2250f5a88cbc686ff30ae02c0f923bb7854bb47972397496b2"}, - {file = "pyobjc_framework_Cocoa-10.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6a6042b7703bdc33b7491959c715c1e810a3f8c7a560c94b36e00ef321480797"}, - {file = "pyobjc_framework_Cocoa-10.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:18886d5013cd7dc7ecd6e0df5134c767569b5247fc10a5e293c72ee3937b217b"}, - {file = "pyobjc_framework_Cocoa-10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ecf01400ee698d2e0ff4c907bcf9608d9d710e97203fbb97b37d208507a9362"}, - {file = "pyobjc_framework_Cocoa-10.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:0def036a7b24e3ae37a244c77bec96b7c9c8384bf6bb4d33369f0a0c8807a70d"}, - {file = "pyobjc_framework_Cocoa-10.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f47ecc393bc1019c4b47e8653207188df784ac006ad54d8c2eb528906ff7013"}, -] - -[package.dependencies] -pyobjc-core = ">=10.2" - -[[package]] -name = "pyobjc-framework-coretext" -version = "10.2" -description = "Wrappers for the framework CoreText on macOS" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyobjc-framework-CoreText-10.2.tar.gz", hash = "sha256:59ef8ca8d88bb53ce9980dda0b8094daa3e2dabe355847365ba965ff0b49f961"}, - {file = "pyobjc_framework_CoreText-10.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:44052f752f42b62d342fa8aced5d1b8928831e70830eccddc594726d40500d5c"}, - {file = "pyobjc_framework_CoreText-10.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0bc278f509a3fd3eea89124d81e77de11af10167c0df0d0cc15a369f060465a0"}, - {file = "pyobjc_framework_CoreText-10.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7b819119dc859e49c0ce9040ae09d6a3bd66658003793f486ef5a21e46a2d34f"}, - {file = "pyobjc_framework_CoreText-10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2719c57ff08af6e4fdcddd0fa5eda56113808a1690c3325f1c6926740817f9a1"}, - {file = "pyobjc_framework_CoreText-10.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:8239ce92f9496587a60fc1bfd4994136832bad99405bb45572f92d960cbe746e"}, - {file = "pyobjc_framework_CoreText-10.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:80a1d207fcdb2999841daa430c83d760ac1a3f2f65c605949fc5ff789425b1f6"}, -] - -[package.dependencies] -pyobjc-core = ">=10.2" -pyobjc-framework-Cocoa = ">=10.2" -pyobjc-framework-Quartz = ">=10.2" - -[[package]] -name = "pyobjc-framework-quartz" -version = "10.2" -description = "Wrappers for the Quartz frameworks on macOS" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyobjc-framework-Quartz-10.2.tar.gz", hash = "sha256:9b947e081f5bd6cd01c99ab5d62c36500d2d6e8d3b87421c1cbb7f9c885555eb"}, - {file = "pyobjc_framework_Quartz-10.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bc0ab739259a717d9d13a739434991b54eb8963ad7c27f9f6d04d68531fb479b"}, - {file = "pyobjc_framework_Quartz-10.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2a74d00e933c1e1a1820839323dc5cf252bee8bb98e2a298d961f7ae7905ce71"}, - {file = "pyobjc_framework_Quartz-10.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3e8e33246d966c2bd7f5ee2cf3b431582fa434a6ec2b6dbe580045ebf1f55be5"}, - {file = "pyobjc_framework_Quartz-10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c6ca490eff1be0dd8dc7726edde79c97e21ec1afcf55f75962a79e27b4eb2961"}, - {file = "pyobjc_framework_Quartz-10.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d3d54d9fa50de09ee8994248151def58f30b4738eb20755b0bdd5ee1e1f5883d"}, - {file = "pyobjc_framework_Quartz-10.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:520c8031b2389110f80070b078dde1968caaecb10921f8070046c26132ac9286"}, -] - -[package.dependencies] -pyobjc-core = ">=10.2" -pyobjc-framework-Cocoa = ">=10.2" - [[package]] name = "pytest" version = "8.1.1" @@ -942,34 +366,6 @@ pytest = ">=7.4" [package.extras] test = ["covdefaults (>=2.3)", "coverage (>=7.3)", "pytest-mock (>=3.11.1)"] -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "python-xlib" -version = "0.33" -description = "Python X Library" -optional = false -python-versions = "*" -files = [ - {file = "python-xlib-0.33.tar.gz", hash = "sha256:55af7906a2c75ce6cb280a584776080602444f75815a7aff4d287bb2d7018b32"}, - {file = "python_xlib-0.33-py2.py3-none-any.whl", hash = "sha256:c3534038d42e0df2f1392a1b30a15a4ff5fdc2b86cfa94f072bf11b10a164398"}, -] - -[package.dependencies] -six = ">=1.10.0" - [[package]] name = "pyyaml" version = "6.0.1" @@ -1029,53 +425,6 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] -[[package]] -name = "qtawesome" -version = "0.7.3" -description = "FontAwesome icons in PyQt and PySide applications" -optional = false -python-versions = "*" -files = [ - {file = "QtAwesome-0.7.3-py2.py3-none-any.whl", hash = "sha256:ddf4530b4af71cec13b24b88a4cdb56ec85b1e44c43c42d0698804c7137b09b0"}, - {file = "QtAwesome-0.7.3.tar.gz", hash = "sha256:b98b9038d19190e83ab26d91c4d8fc3a36591ee2bc7f5016d4438b8240d097bd"}, -] - -[package.dependencies] -qtpy = "*" -six = "*" - -[[package]] -name = "qtpy" -version = "2.4.1" -description = "Provides an abstraction layer on top of the various Qt bindings (PyQt5/6 and PySide2/6)." -optional = false -python-versions = ">=3.7" -files = [ - {file = "QtPy-2.4.1-py3-none-any.whl", hash = "sha256:1c1d8c4fa2c884ae742b069151b0abe15b3f70491f3972698c683b8e38de839b"}, - {file = "QtPy-2.4.1.tar.gz", hash = "sha256:a5a15ffd519550a1361bdc56ffc07fda56a6af7292f17c7b395d4083af632987"}, -] - -[package.dependencies] -packaging = "*" - -[package.extras] -test = ["pytest (>=6,!=7.0.0,!=7.0.1)", "pytest-cov (>=3.0.0)", "pytest-qt"] - -[[package]] -name = "referencing" -version = "0.34.0" -description = "JSON Referencing + Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "referencing-0.34.0-py3-none-any.whl", hash = "sha256:d53ae300ceddd3169f1ffa9caf2cb7b769e92657e4fafb23d34b93679116dfd4"}, - {file = "referencing-0.34.0.tar.gz", hash = "sha256:5773bd84ef41799a5a8ca72dc34590c041eb01bf9aa02632b4a973fb0181a844"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -rpds-py = ">=0.7.0" - [[package]] name = "requests" version = "2.31.0" @@ -1097,114 +446,6 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] -[[package]] -name = "rpds-py" -version = "0.18.0" -description = "Python bindings to Rust's persistent data structures (rpds)" -optional = false -python-versions = ">=3.8" -files = [ - {file = "rpds_py-0.18.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e"}, - {file = "rpds_py-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7"}, - {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f"}, - {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51"}, - {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40"}, - {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da"}, - {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1"}, - {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434"}, - {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3"}, - {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e"}, - {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88"}, - {file = "rpds_py-0.18.0-cp310-none-win32.whl", hash = "sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337"}, - {file = "rpds_py-0.18.0-cp310-none-win_amd64.whl", hash = "sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66"}, - {file = "rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4"}, - {file = "rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6"}, - {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58"}, - {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf"}, - {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c"}, - {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1"}, - {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5"}, - {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6"}, - {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688"}, - {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b"}, - {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836"}, - {file = "rpds_py-0.18.0-cp311-none-win32.whl", hash = "sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1"}, - {file = "rpds_py-0.18.0-cp311-none-win_amd64.whl", hash = "sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa"}, - {file = "rpds_py-0.18.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0"}, - {file = "rpds_py-0.18.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8"}, - {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475"}, - {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f"}, - {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c"}, - {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9"}, - {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3"}, - {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157"}, - {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496"}, - {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f"}, - {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7"}, - {file = "rpds_py-0.18.0-cp312-none-win32.whl", hash = "sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98"}, - {file = "rpds_py-0.18.0-cp312-none-win_amd64.whl", hash = "sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec"}, - {file = "rpds_py-0.18.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e"}, - {file = "rpds_py-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58"}, - {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb"}, - {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861"}, - {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73"}, - {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07"}, - {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d"}, - {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c"}, - {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f"}, - {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c"}, - {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594"}, - {file = "rpds_py-0.18.0-cp38-none-win32.whl", hash = "sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e"}, - {file = "rpds_py-0.18.0-cp38-none-win_amd64.whl", hash = "sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1"}, - {file = "rpds_py-0.18.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33"}, - {file = "rpds_py-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467"}, - {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab"}, - {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40"}, - {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1"}, - {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022"}, - {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9"}, - {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f"}, - {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e"}, - {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024"}, - {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20"}, - {file = "rpds_py-0.18.0-cp39-none-win32.whl", hash = "sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7"}, - {file = "rpds_py-0.18.0-cp39-none-win_amd64.whl", hash = "sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294"}, - {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f"}, - {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e"}, - {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca"}, - {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7"}, - {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641"}, - {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948"}, - {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795"}, - {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18"}, - {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1"}, - {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984"}, - {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124"}, - {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb"}, - {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461"}, - {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd"}, - {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863"}, - {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05"}, - {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e"}, - {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3"}, - {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880"}, - {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80"}, - {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da"}, - {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd"}, - {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307"}, - {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d"}, - {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4"}, - {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76"}, - {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c"}, - {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17"}, - {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66"}, - {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24"}, - {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1"}, - {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432"}, - {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f"}, - {file = "rpds_py-0.18.0.tar.gz", hash = "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d"}, -] - [[package]] name = "ruff" version = "0.3.3" @@ -1258,17 +499,6 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] -[[package]] -name = "speedcopy" -version = "2.1.5" -description = "Replacement or alternative for python copyfile() utilizing server side copy on network shares for faster copying." -optional = false -python-versions = "*" -files = [ - {file = "speedcopy-2.1.5-py3-none-any.whl", hash = "sha256:903d0b466c2bef7c07dfac17493cdfbc09aadd70e947199c81caa6c6da2c095f"}, - {file = "speedcopy-2.1.5.tar.gz", hash = "sha256:9d6c482300791f02462ad451730ae247901978eae9e25290ca352de964698c82"}, -] - [[package]] name = "tomli" version = "2.0.1" @@ -1280,17 +510,6 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] -[[package]] -name = "types-python-dateutil" -version = "2.9.0.20240316" -description = "Typing stubs for python-dateutil" -optional = false -python-versions = ">=3.8" -files = [ - {file = "types-python-dateutil-2.9.0.20240316.tar.gz", hash = "sha256:5d2f2e240b86905e40944dd787db6da9263f0deabef1076ddaed797351ec0202"}, - {file = "types_python_dateutil-2.9.0.20240316-py3-none-any.whl", hash = "sha256:6b8cb66d960771ce5ff974e9dd45e38facb81718cc1e208b10b1baccbfdbee3b"}, -] - [[package]] name = "unidecode" version = "1.3.8" @@ -1339,130 +558,7 @@ platformdirs = ">=3.9.1,<5" docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] -[[package]] -name = "wsrpc-aiohttp" -version = "3.2.0" -description = "WSRPC is the RPC over WebSocket for aiohttp" -optional = false -python-versions = ">3.5.*, <4" -files = [ - {file = "wsrpc-aiohttp-3.2.0.tar.gz", hash = "sha256:f467abc51bcdc760fc5aeb7041abdeef46eeca3928dc43dd6e7fa7a533563818"}, - {file = "wsrpc_aiohttp-3.2.0-py3-none-any.whl", hash = "sha256:fa9b0bf5cb056898cb5c9f64cbc5eacb8a5dd18ab1b7f0cd4a2208b4a7fde282"}, -] - -[package.dependencies] -aiohttp = "<4" -yarl = "*" - -[package.extras] -develop = ["Sphinx", "async-timeout", "coverage (!=4.3)", "coveralls", "pytest", "pytest-aiohttp", "pytest-cov", "sphinxcontrib-plantuml", "tox (>=2.4)"] -testing = ["async-timeout", "coverage (!=4.3)", "coveralls", "pytest", "pytest-aiohttp", "pytest-cov"] -ujson = ["ujson"] - -[[package]] -name = "yarl" -version = "1.9.4" -description = "Yet another URL library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, - {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, - {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, - {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, - {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, - {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, - {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, - {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, - {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, - {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, - {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, - {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, - {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, - {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, - {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, - {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" - [metadata] lock-version = "2.0" python-versions = ">=3.9.1,<3.10" -content-hash = "8a62cc31c960aff7e5df7bfdc5b65790e57bf0e7a87fedd16a68ababa49268c8" +content-hash = "1bb724694792fbc2b3c05e3355e6c25305d9f4034eb7b1b4b1791ee95427f8d2" diff --git a/pyproject.toml b/pyproject.toml index 29213281af..2740e9307e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,27 +7,17 @@ readme = "README.md" [tool.poetry.dependencies] python = ">=3.9.1,<3.10" -aiohttp_json_rpc = "*" # TVPaint server -aiohttp-middlewares = "^2.0.0" -wsrpc_aiohttp = "^3.1.1" # websocket server -Click = "^8" -clique = "1.6.*" -jsonschema = "^4" -pyblish-base = "^1.8.11" -pynput = "^1.7.2" # Timers manager - TODO remove -speedcopy = "^2.1" -six = "^1.15" -qtawesome = "0.7.3" -pre-commit = "^3.6.2" -codespell = "^2.2.6" [tool.poetry.dev-dependencies] +# test dependencies pytest = "^8.0" pytest-print = "^1.0" ayon-python-api = "^1.0" -arrow = "^1.3.0" +# linting dependencies ruff = "^0.3.3" +pre-commit = "^3.6.2" +codespell = "^2.2.6" [tool.ruff] From 38c8cf2e3bdf8a5210eb64ceed369d00aa0f2cb8 Mon Sep 17 00:00:00 2001 From: moonyuet Date: Tue, 19 Mar 2024 14:48:46 +0100 Subject: [PATCH 08/60] add zbrush being part of application.json --- .../applications/server/applications.json | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/server_addon/applications/server/applications.json b/server_addon/applications/server/applications.json index b72d117225..85bf6f1dda 100644 --- a/server_addon/applications/server/applications.json +++ b/server_addon/applications/server/applications.json @@ -1225,6 +1225,32 @@ } ] }, + "zbrush": { + "enabled": true, + "label": "Zbrush", + "icon": "{}/app_icons/zbrush.png", + "host_name": "zbrush", + "environment": "{\n \"ZBRUSH_PLUGIN_PATH\": [\n \"{ZBRUSH_PLUGIN_PATH}\",\n \"{OPENPYPE_STUDIO_PLUGINS}/zbrush/api/zscripts\"\n ]\n}", + "variants": [ + { + "name": "2024", + "use_python_2": false, + "executables": { + "windows": [ + "C:\\Program Files\\Maxon ZBrush 2024\\ZBrush.exe" + ], + "darwin": [], + "linux": [] + }, + "arguments": { + "windows": [], + "darwin": [], + "linux": [] + }, + "environment": "{}" + } + ] + }, "additional_apps": [] } } From 0477e1775c043c199a244e2c15e00ac06e47b473 Mon Sep 17 00:00:00 2001 From: moonyuet Date: Tue, 19 Mar 2024 14:55:10 +0100 Subject: [PATCH 09/60] add icon --- .../ayon_core/resources/app_icons/zbrush.png | Bin 0 -> 287255 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 client/ayon_core/resources/app_icons/zbrush.png diff --git a/client/ayon_core/resources/app_icons/zbrush.png b/client/ayon_core/resources/app_icons/zbrush.png new file mode 100644 index 0000000000000000000000000000000000000000..4b0662580c907e797d68ed61041c23f8134fea53 GIT binary patch literal 287255 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 literal 0 HcmV?d00001 From 42219e11184df511c48d2f0d812498c33e9b03a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Tue, 19 Mar 2024 15:09:34 +0100 Subject: [PATCH 10/60] :memo: update readme --- README.md | 24 ++++++++++++++++++------ pyproject.toml | 5 +++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e2aa98bb16..11a660e643 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -AYON Core addon -======== +AYON Core Addon +=============== -AYON core provides the base building blocks for all other AYON addons and integrations and is responsible for discovery and initialization of other addons. +AYON core provides the base building blocks for all other AYON addons and integrations and is responsible for discovery and initialization of other addons. - Some of its key functions include: - It is used as the main command line handler in [ayon-launcher](https://github.com/ynput/ayon-launcher) application. @@ -13,8 +13,20 @@ AYON core provides the base building blocks for all other AYON addons and integr - Defines pipeline API used by other integrations - Provides all graphical tools for artists - Defines AYON QT styling -- A bunch more things +- A bunch more things -Together with [ayon-launcher](https://github.com/ynput/ayon-launcher) , they form the base of AYON pipeline and is one of few compulsory addons for AYON pipeline to be useful in a meaningful way. +Together with [ayon-launcher](https://github.com/ynput/ayon-launcher) , they form the base of AYON pipeline and is one of few compulsory addons for AYON pipeline to be useful in a meaningful way. -AYON-core is a successor to OpenPype repository (minus all the addons) and still in the process of cleaning up of all references. Please bear with us during this transitional phase. +AYON-core is a successor to [OpenPype repository](https://github.com/ynput/OpenPype) (minus all the addons) and still in the process of cleaning up of all references. Please bear with us during this transitional phase. + +Development and testing notes +----------------------------- +There is `pyproject.toml` file in the root of the repository. This file is used to define the development environment and is used by `poetry` to create a virtual environment. +This virtual environment is used to run tests and to develop the code, to help with +linting and formatting. Dependencies defined here are not used in actual addon +deployment - for that you need to edit `./client/pyproject.toml` file. That file +will be then processed [ayon-dependencies-tool](https://github.com/ynput/ayon-dependencies-tool) +to create dependency package. + +Right now, this file needs to by synced with dependencies manually, but in the future +we plan to automate process of development environment creation. diff --git a/pyproject.toml b/pyproject.toml index 2740e9307e..ee124ddc2d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,8 @@ +# WARNING: This file is used only for development done on this addon. +# Be aware that dependencies used here might not match the ones used by +# the specific addon bundle set up on the AYON server. This file should +# be used only for local development and CI/CD purposes. + [tool.poetry] name = "ayon-core" version = "0.3.0" From 17176fd41330b51681a4cfbf6f74b4dd88c15fe8 Mon Sep 17 00:00:00 2001 From: moonyuet Date: Tue, 19 Mar 2024 15:43:50 +0100 Subject: [PATCH 11/60] add missing code for adding application for zbrush --- server_addon/applications/server/settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server_addon/applications/server/settings.py b/server_addon/applications/server/settings.py index a49175d488..5743e9f471 100644 --- a/server_addon/applications/server/settings.py +++ b/server_addon/applications/server/settings.py @@ -188,6 +188,8 @@ class ApplicationsSettings(BaseSettingsModel): default_factory=AppGroupWithPython, title="Wrap") openrv: AppGroup = SettingsField( default_factory=AppGroupWithPython, title="OpenRV") + zbrush: AppGroup = SettingsField( + default_factory=AppGroupWithPython, title="Zbrush") additional_apps: list[AdditionalAppGroup] = SettingsField( default_factory=list, title="Additional Applications") From 58d63af8848e4a45868d17168cbb2c7fde68c00b Mon Sep 17 00:00:00 2001 From: moonyuet Date: Tue, 19 Mar 2024 15:44:16 +0100 Subject: [PATCH 12/60] upversioning --- server_addon/applications/server/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/applications/server/version.py b/server_addon/applications/server/version.py index f1380eede2..9cb17e7976 100644 --- a/server_addon/applications/server/version.py +++ b/server_addon/applications/server/version.py @@ -1 +1 @@ -__version__ = "0.1.7" +__version__ = "0.1.8" From b1f8a1c9b4649507b211715b44cad27cd1e7937f Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 20 Mar 2024 00:19:41 +0100 Subject: [PATCH 13/60] Fix argument name --- .../ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py index eaa7ff1ae3..004b85f420 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py @@ -64,7 +64,7 @@ class LoadVDBtoArnold(load.LoaderPlugin): path = self.filepath_from_context(context) self._set_path(grid_node, path=path, - representation=context["representation"]) + repre_entity=context["representation"]) # Lock the shape node so the user can't delete the transform/shape # as if it was referenced @@ -94,7 +94,7 @@ class LoadVDBtoArnold(load.LoaderPlugin): assert len(grid_nodes) == 1, "This is a bug" # Update the VRayVolumeGrid - self._set_path(grid_nodes[0], path=path, representation=repre_entity) + self._set_path(grid_nodes[0], path=path, repre_entity=repre_entity) # Update container representation cmds.setAttr(container["objectName"] + ".representation", From 87a0c7555c823c29cc54af9cd8b747dc9b92e6a1 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 20 Mar 2024 00:35:41 +0100 Subject: [PATCH 14/60] Fix indentations --- .../plugins/publish/collect_karma_rop.py | 28 +++--- .../plugins/publish/collect_mantra_rop.py | 92 +++++++++---------- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/client/ayon_core/hosts/houdini/plugins/publish/collect_karma_rop.py b/client/ayon_core/hosts/houdini/plugins/publish/collect_karma_rop.py index 85100bc2c6..78651b0c69 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/collect_karma_rop.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/collect_karma_rop.py @@ -41,23 +41,23 @@ class CollectKarmaROPRenderProducts(pyblish.api.InstancePlugin): instance.data["chunkSize"] = chunk_size self.log.debug("Chunk Size: %s" % chunk_size) - default_prefix = evalParmNoFrame(rop, "picture") - render_products = [] + default_prefix = evalParmNoFrame(rop, "picture") + render_products = [] - # Default beauty AOV - beauty_product = self.get_render_product_name( - prefix=default_prefix, suffix=None - ) - render_products.append(beauty_product) + # Default beauty AOV + beauty_product = self.get_render_product_name( + prefix=default_prefix, suffix=None + ) + render_products.append(beauty_product) - files_by_aov = { - "beauty": self.generate_expected_files(instance, - beauty_product) - } + files_by_aov = { + "beauty": self.generate_expected_files(instance, + beauty_product) + } - filenames = list(render_products) - instance.data["files"] = filenames - instance.data["renderProducts"] = colorspace.ARenderProduct() + filenames = list(render_products) + instance.data["files"] = filenames + instance.data["renderProducts"] = colorspace.ARenderProduct() for product in render_products: self.log.debug("Found render product: %s" % product) diff --git a/client/ayon_core/hosts/houdini/plugins/publish/collect_mantra_rop.py b/client/ayon_core/hosts/houdini/plugins/publish/collect_mantra_rop.py index d46476c2ce..df9acc4b61 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/collect_mantra_rop.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/collect_mantra_rop.py @@ -41,57 +41,57 @@ class CollectMantraROPRenderProducts(pyblish.api.InstancePlugin): instance.data["chunkSize"] = chunk_size self.log.debug("Chunk Size: %s" % chunk_size) - default_prefix = evalParmNoFrame(rop, "vm_picture") - render_products = [] + default_prefix = evalParmNoFrame(rop, "vm_picture") + render_products = [] - # Store whether we are splitting the render job (export + render) - split_render = bool(rop.parm("soho_outputmode").eval()) - instance.data["splitRender"] = split_render - export_prefix = None - export_products = [] - if split_render: - export_prefix = evalParmNoFrame( - rop, "soho_diskfile", pad_character="0" - ) - beauty_export_product = self.get_render_product_name( - prefix=export_prefix, - suffix=None) - export_products.append(beauty_export_product) - self.log.debug( - "Found export product: {}".format(beauty_export_product) - ) - instance.data["ifdFile"] = beauty_export_product - instance.data["exportFiles"] = list(export_products) - - # Default beauty AOV - beauty_product = self.get_render_product_name( - prefix=default_prefix, suffix=None + # Store whether we are splitting the render job (export + render) + split_render = bool(rop.parm("soho_outputmode").eval()) + instance.data["splitRender"] = split_render + export_prefix = None + export_products = [] + if split_render: + export_prefix = evalParmNoFrame( + rop, "soho_diskfile", pad_character="0" ) - render_products.append(beauty_product) + beauty_export_product = self.get_render_product_name( + prefix=export_prefix, + suffix=None) + export_products.append(beauty_export_product) + self.log.debug( + "Found export product: {}".format(beauty_export_product) + ) + instance.data["ifdFile"] = beauty_export_product + instance.data["exportFiles"] = list(export_products) - files_by_aov = { - "beauty": self.generate_expected_files(instance, - beauty_product) - } + # Default beauty AOV + beauty_product = self.get_render_product_name( + prefix=default_prefix, suffix=None + ) + render_products.append(beauty_product) - aov_numbers = rop.evalParm("vm_numaux") - if aov_numbers > 0: - # get the filenames of the AOVs - for i in range(1, aov_numbers + 1): - var = rop.evalParm("vm_variable_plane%d" % i) - if var: - aov_name = "vm_filename_plane%d" % i - aov_boolean = "vm_usefile_plane%d" % i - aov_enabled = rop.evalParm(aov_boolean) - has_aov_path = rop.evalParm(aov_name) - if has_aov_path and aov_enabled == 1: - aov_prefix = evalParmNoFrame(rop, aov_name) - aov_product = self.get_render_product_name( - prefix=aov_prefix, suffix=None - ) - render_products.append(aov_product) + files_by_aov = { + "beauty": self.generate_expected_files(instance, + beauty_product) + } - files_by_aov[var] = self.generate_expected_files(instance, aov_product) # noqa + aov_numbers = rop.evalParm("vm_numaux") + if aov_numbers > 0: + # get the filenames of the AOVs + for i in range(1, aov_numbers + 1): + var = rop.evalParm("vm_variable_plane%d" % i) + if var: + aov_name = "vm_filename_plane%d" % i + aov_boolean = "vm_usefile_plane%d" % i + aov_enabled = rop.evalParm(aov_boolean) + has_aov_path = rop.evalParm(aov_name) + if has_aov_path and aov_enabled == 1: + aov_prefix = evalParmNoFrame(rop, aov_name) + aov_product = self.get_render_product_name( + prefix=aov_prefix, suffix=None + ) + render_products.append(aov_product) + + files_by_aov[var] = self.generate_expected_files(instance, aov_product) # noqa for product in render_products: self.log.debug("Found render product: %s" % product) From 16096e8407e87a071d38b4f3cee107f6cc11d8d8 Mon Sep 17 00:00:00 2001 From: Jacob Danell Date: Sat, 23 Mar 2024 21:29:37 +0100 Subject: [PATCH 15/60] Re-add outputName to _rename_in_representation --- client/ayon_core/plugins/publish/extract_color_transcode.py | 1 + 1 file changed, 1 insertion(+) diff --git a/client/ayon_core/plugins/publish/extract_color_transcode.py b/client/ayon_core/plugins/publish/extract_color_transcode.py index b5ddebe05b..1130c575a3 100644 --- a/client/ayon_core/plugins/publish/extract_color_transcode.py +++ b/client/ayon_core/plugins/publish/extract_color_transcode.py @@ -257,6 +257,7 @@ class ExtractOIIOTranscode(publish.Extractor): return new_repre["ext"] = output_extension + new_repre["outputName"] = output_name renamed_files = [] for file_name in files_to_convert: From 7f0098f92fae0d29c4808e17a00ed9f2233fa65c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 24 Mar 2024 11:48:51 +0100 Subject: [PATCH 16/60] Houdini: Add generic filepath loader --- .../houdini/plugins/load/load_filepath.py | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 client/ayon_core/hosts/houdini/plugins/load/load_filepath.py diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_filepath.py b/client/ayon_core/hosts/houdini/plugins/load/load_filepath.py new file mode 100644 index 0000000000..515ffa6027 --- /dev/null +++ b/client/ayon_core/hosts/houdini/plugins/load/load_filepath.py @@ -0,0 +1,129 @@ +import os +import re + +from ayon_core.pipeline import load +from openpype.hosts.houdini.api import pipeline + +import hou + + +class FilePathLoader(load.LoaderPlugin): + """Load a managed filepath to a null node. + + This is useful if for a particular workflow there is no existing loader + yet. A Houdini artists can load as the generic filepath loader and then + reference the relevant Houdini parm to use the exact value. The benefit + is that this filepath will be managed and can be updated as usual. + + """ + + label = "Load filepath to node" + order = 9 + icon = "link" + color = "white" + product_types = {"*"} + representations = ["*"] + + def load(self, context, name=None, namespace=None, data=None): + + # Get the root node + obj = hou.node("/obj") + + # Define node name + namespace = namespace if namespace else context["folder"]["name"] + node_name = "{}_{}".format(namespace, name) if namespace else name + + # Create a null node + container = obj.createNode("null", node_name=node_name) + + # Destroy any children + for node in container.children(): + node.destroy() + + # Add filepath attribute, set value as default value + filepath = self.format_path( + path=self.filepath_from_context(context), + representation=context["representation"] + ) + parm_template_group = container.parmTemplateGroup() + attr_folder = hou.FolderParmTemplate("attributes_folder", "Attributes") + parm = hou.StringParmTemplate(name="filepath", + label="Filepath", + num_components=1, + default_value=(filepath,)) + attr_folder.addParmTemplate(parm) + parm_template_group.append(attr_folder) + + # Hide some default labels + for folder_label in ["Transform", "Render", "Misc", "Redshift OBJ"]: + folder = parm_template_group.findFolder(folder_label) + if not folder: + continue + parm_template_group.hideFolder(folder_label, True) + + container.setParmTemplateGroup(parm_template_group) + + container.setDisplayFlag(False) + container.setSelectableInViewport(False) + container.useXray(False) + + nodes = [container] + + self[:] = nodes + + return pipeline.containerise( + node_name, + namespace, + nodes, + context, + self.__class__.__name__, + suffix="", + ) + + def update(self, container, context): + + # Update the file path + representation_entity = context["representation"] + file_path = self.format_path( + path=self.filepath_from_context(context), + representation=representation_entity + ) + + node = container["node"] + node.setParms({ + "filepath": file_path, + "representation": str(representation_entity["id"]) + }) + + # Update the parameter default value (cosmetics) + parm_template_group = node.parmTemplateGroup() + parm = parm_template_group.find("filepath") + parm.setDefaultValue((file_path,)) + parm_template_group.replace(parm_template_group.find("filepath"), + parm) + node.setParmTemplateGroup(parm_template_group) + + def switch(self, container, representation): + self.update(container, representation) + + def remove(self, container): + + node = container["node"] + node.destroy() + + @staticmethod + def format_path(path: str, representation: dict) -> str: + """Format file path for sequence with $F.""" + if not os.path.exists(path): + raise RuntimeError("Path does not exist: %s" % path) + + # The path is either a single file or sequence in a folder. + frame = representation["context"].get("frame") + if frame is not None: + # Substitute frame number in sequence with $F with padding + ext = representation.get("ext", representation["name"]) + token = "$F{}".format(len(frame)) # e.g. $F4 + pattern = r"\.(\d+)\.{ext}$".format(ext=re.escape(ext)) + path = re.sub(pattern, ".{}.{}".format(token, ext), path) + + return os.path.normpath(path).replace("\\", "/") From 3888ce8486bc4910557e8eab33484a227beb0206 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 24 Mar 2024 11:52:38 +0100 Subject: [PATCH 17/60] Houdini: Implement `switch` method for Camera Loader --- client/ayon_core/hosts/houdini/plugins/load/load_camera.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_camera.py b/client/ayon_core/hosts/houdini/plugins/load/load_camera.py index 605e5724e6..c57b14043a 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_camera.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_camera.py @@ -167,6 +167,9 @@ class CameraLoader(load.LoaderPlugin): temp_camera.destroy() + def switch(self, container, context): + self.update(container, context) + def remove(self, container): node = container["node"] From 4f3391eb8a7d99aa97ea527b176fad2299d0704d Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 24 Mar 2024 11:52:58 +0100 Subject: [PATCH 18/60] Remove redundant commented print --- client/ayon_core/hosts/houdini/plugins/load/load_camera.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_camera.py b/client/ayon_core/hosts/houdini/plugins/load/load_camera.py index c57b14043a..7cb4542d0c 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_camera.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_camera.py @@ -198,7 +198,6 @@ class CameraLoader(load.LoaderPlugin): def _match_maya_render_mask(self, camera): """Workaround to match Maya render mask in Houdini""" - # print("Setting match maya render mask ") parm = camera.parm("aperture") expression = parm.expression() expression = expression.replace("return ", "aperture = ") From bfd6325d18232c11069078fe8b07c85fb0ffb362 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 24 Mar 2024 12:54:24 +0100 Subject: [PATCH 19/60] Houdini: Allow loading any alembic file by .abc extension, regardless of representation name --- client/ayon_core/hosts/houdini/plugins/load/load_alembic.py | 3 ++- .../hosts/houdini/plugins/load/load_alembic_archive.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_alembic.py b/client/ayon_core/hosts/houdini/plugins/load/load_alembic.py index 3398920e87..a77d06d409 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_alembic.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_alembic.py @@ -11,7 +11,8 @@ class AbcLoader(load.LoaderPlugin): product_types = {"model", "animation", "pointcache", "gpuCache"} label = "Load Alembic" - representations = ["abc"] + representations = ["*"] + extensions = {"abc"} order = -10 icon = "code-fork" color = "orange" diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_alembic_archive.py b/client/ayon_core/hosts/houdini/plugins/load/load_alembic_archive.py index 8d3becb973..39928fd952 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_alembic_archive.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_alembic_archive.py @@ -11,7 +11,8 @@ class AbcArchiveLoader(load.LoaderPlugin): product_types = {"model", "animation", "pointcache", "gpuCache"} label = "Load Alembic as Archive" - representations = ["abc"] + representations = ["*"] + extensions = {"abc"} order = -5 icon = "code-fork" color = "orange" From e4c8cf2f7e5745a7d703f391c3b1537b90322c36 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 13:04:15 +0100 Subject: [PATCH 20/60] Resolve: Allow to minimize the menu --- client/ayon_core/hosts/resolve/api/menu.py | 1 + 1 file changed, 1 insertion(+) diff --git a/client/ayon_core/hosts/resolve/api/menu.py b/client/ayon_core/hosts/resolve/api/menu.py index 59eba14d83..3324295615 100644 --- a/client/ayon_core/hosts/resolve/api/menu.py +++ b/client/ayon_core/hosts/resolve/api/menu.py @@ -48,6 +48,7 @@ class OpenPypeMenu(QtWidgets.QWidget): QtCore.Qt.Window | QtCore.Qt.CustomizeWindowHint | QtCore.Qt.WindowTitleHint + | QtCore.Qt.WindowMinimizeButtonHint | QtCore.Qt.WindowCloseButtonHint | QtCore.Qt.WindowStaysOnTopHint ) From d2396140106182cc4b8de4a175fa2f6fc2d9cd43 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 13:27:26 +0100 Subject: [PATCH 21/60] Refactor `OpenPype` to `AYON` --- client/ayon_core/hosts/resolve/api/menu.py | 10 +++++----- client/ayon_core/hosts/resolve/api/menu_style.qss | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/ayon_core/hosts/resolve/api/menu.py b/client/ayon_core/hosts/resolve/api/menu.py index 3324295615..7f3a669ecb 100644 --- a/client/ayon_core/hosts/resolve/api/menu.py +++ b/client/ayon_core/hosts/resolve/api/menu.py @@ -38,9 +38,9 @@ class Spacer(QtWidgets.QWidget): self.setLayout(layout) -class OpenPypeMenu(QtWidgets.QWidget): +class AYONMenu(QtWidgets.QWidget): def __init__(self, *args, **kwargs): - super(OpenPypeMenu, self).__init__(*args, **kwargs) + super(AYONMenu, self).__init__(*args, **kwargs) self.setObjectName(f"{MENU_LABEL}Menu") @@ -174,11 +174,11 @@ class OpenPypeMenu(QtWidgets.QWidget): def launch_pype_menu(): app = QtWidgets.QApplication(sys.argv) - pype_menu = OpenPypeMenu() + ayon_menu = AYONMenu() stylesheet = load_stylesheet() - pype_menu.setStyleSheet(stylesheet) + ayon_menu.setStyleSheet(stylesheet) - pype_menu.show() + ayon_menu.show() sys.exit(app.exec_()) diff --git a/client/ayon_core/hosts/resolve/api/menu_style.qss b/client/ayon_core/hosts/resolve/api/menu_style.qss index 3d51c7139f..ad8932d881 100644 --- a/client/ayon_core/hosts/resolve/api/menu_style.qss +++ b/client/ayon_core/hosts/resolve/api/menu_style.qss @@ -51,7 +51,7 @@ QLineEdit { qproperty-alignment: AlignCenter; } -#OpenPypeMenu { +#AYONMenu { qproperty-alignment: AlignLeft; min-width: 10em; border: 1px solid #fef9ef; From 3c23f6cc3f833ff085ef1c146511595ef5e16dc7 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 14:00:57 +0100 Subject: [PATCH 22/60] Houdini: Improve load image - Support setting OCIO colorspace - Support single frame file versus sequence - Support 'switch' folder functionality - Allow loading more product types --- .../hosts/houdini/plugins/load/load_image.py | 96 ++++++++++++++----- 1 file changed, 73 insertions(+), 23 deletions(-) diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_image.py b/client/ayon_core/hosts/houdini/plugins/load/load_image.py index b77e4f662a..72bb873eff 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_image.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_image.py @@ -1,4 +1,5 @@ import os +import re from ayon_core.pipeline import ( load, @@ -44,7 +45,14 @@ def get_image_avalon_container(): class ImageLoader(load.LoaderPlugin): """Load images into COP2""" - product_types = {"imagesequence"} + product_types = { + "imagesequence", + "review", + "render", + "plate", + "image", + "online", + } label = "Load Image (COP2)" representations = ["*"] order = -10 @@ -55,10 +63,8 @@ class ImageLoader(load.LoaderPlugin): def load(self, context, name=None, namespace=None, data=None): # Format file name, Houdini only wants forward slashes - file_path = self.filepath_from_context(context) - file_path = os.path.normpath(file_path) - file_path = file_path.replace("\\", "/") - file_path = self._get_file_sequence(file_path) + path = self.filepath_from_context(context) + path = self.format_path(path, representation=context["representation"]) # Get the root node parent = get_image_avalon_container() @@ -70,7 +76,10 @@ class ImageLoader(load.LoaderPlugin): node = parent.createNode("file", node_name=node_name) node.moveToGoodPosition() - node.setParms({"filename1": file_path}) + parms = {"filename1": path} + parms.update(self.get_colorspace_parms(context["representation"])) + + node.setParms(parms) # Imprint it manually data = { @@ -93,16 +102,17 @@ class ImageLoader(load.LoaderPlugin): # Update the file path file_path = get_representation_path(repre_entity) - file_path = file_path.replace("\\", "/") - file_path = self._get_file_sequence(file_path) + file_path = self.format_path(file_path, repre_entity) + + parms = { + "filename1": file_path, + "representation": repre_entity["id"], + } + + parms.update(self.get_colorspace_parms(repre_entity)) # Update attributes - node.setParms( - { - "filename1": file_path, - "representation": repre_entity["id"], - } - ) + node.setParms(parms) def remove(self, container): @@ -119,14 +129,54 @@ class ImageLoader(load.LoaderPlugin): if not parent.children(): parent.destroy() - def _get_file_sequence(self, file_path): - root = os.path.dirname(file_path) - files = sorted(os.listdir(root)) + @staticmethod + def format_path(path, representation): + """Format file path correctly for single image or sequence.""" + if not os.path.exists(path): + raise RuntimeError("Path does not exist: %s" % path) - first_fname = files[0] - prefix, padding, suffix = first_fname.rsplit(".", 2) - fname = ".".join([prefix, "$F{}".format(len(padding)), suffix]) - return os.path.join(root, fname).replace("\\", "/") + ext = os.path.splitext(path)[-1] - def switch(self, container, context): - self.update(container, context) + is_sequence = bool(representation["context"].get("frame")) + # The path is either a single file or sequence in a folder. + if not is_sequence: + filename = path + else: + filename = re.sub(r"(.*)\.(\d+){}$".format(re.escape(ext)), + "\\1.$F4{}".format(ext), + path) + + filename = os.path.join(path, filename) + + filename = os.path.normpath(filename) + filename = filename.replace("\\", "/") + + return filename + + def get_colorspace_parms(self, representation: dict) -> dict: + """Return the color space parameters. + + Returns the values for the colorspace parameters on the node if there + is colorspace data on the representation. + + Arguments: + representation (dict): The representation entity. + + Returns: + dict: Parm to value mapping if colorspace data is defined. + + """ + + data = representation.get("data", {}).get("colorspaceData", {}) + if not data: + return {} + + colorspace = data["colorspace"] + if colorspace: + return { + "colorspace": 3, # Use OpenColorIO + "ocio_space": colorspace + } + + def switch(self, container, representation): + self.update(container, representation) From 44ed77a9f655c03ed585596b08eafc2e6dd2a402 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 14:20:14 +0100 Subject: [PATCH 23/60] Houdini: Implement USD loader to SOPs via `usdimport` --- .../houdini/plugins/load/load_usd_sop.py | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py b/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py new file mode 100644 index 0000000000..b32210e399 --- /dev/null +++ b/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py @@ -0,0 +1,91 @@ +import os + +from ayon_core.pipeline import load +from ayon_core.hosts.houdini.api import pipeline + + +class SopUsdImportLoader(load.LoaderPlugin): + """Load USD to SOPs via `usdimport`""" + + label = "Load USD to SOPs" + product_types = {"*"} + representations = ["usd"] + order = -6 + icon = "code-fork" + color = "orange" + + def load(self, context, name=None, namespace=None, data=None): + import hou + + # Format file name, Houdini only wants forward slashes + file_path = self.filepath_from_context(context) + file_path = os.path.normpath(file_path) + file_path = file_path.replace("\\", "/") + + # Get the root node + obj = hou.node("/obj") + + # Define node name + namespace = namespace if namespace else context["folder"]["name"] + node_name = "{}_{}".format(namespace, name) if namespace else name + + # Create a new geo node + container = obj.createNode("geo", node_name=node_name) + + # Remove the file node, it only loads static meshes + # Houdini 17 has removed the file node from the geo node + file_node = container.node("file1") + if file_node: + file_node.destroy() + + # Create a usdimport node + usdimport = container.createNode("usdimport", node_name=node_name) + usdimport.setParms({"filepath1": file_path}) + + # Ensure display flag is on the first input node and not on the OUT + # node to optimize "debug" displaying in the viewport. + usdimport.setDisplayFlag(True) + + # Set new position for unpack node else it gets cluttered + nodes = [container, usdimport] + for nr, node in enumerate(nodes): + node.setPosition([0, (0 - nr)]) + + self[:] = nodes + + return pipeline.containerise( + node_name, + namespace, + nodes, + context, + self.__class__.__name__, + suffix="", + ) + + def update(self, container, context): + + node = container["node"] + try: + usdimport_node = next( + n for n in node.children() if n.type().name() == "usdimport" + ) + except StopIteration: + self.log.error("Could not find node of type `usdimport`") + return + + # Update the file path + file_path = self.filepath_from_context(context) + file_path = file_path.replace("\\", "/") + + usdimport_node.setParms({"filepath1": file_path}) + + # Update attribute + node.setParms({"representation": context["representation"]["id"]}) + + def remove(self, container): + + node = container["node"] + node.destroy() + + def switch(self, container, representation): + self.update(container, representation) From 24d87bf92a8be56fe837013860c2bb944f7520f6 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 14:22:27 +0100 Subject: [PATCH 24/60] Remove redundant logic --- .../hosts/houdini/plugins/load/load_usd_sop.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py b/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py index b32210e399..3607987e15 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py @@ -32,24 +32,12 @@ class SopUsdImportLoader(load.LoaderPlugin): # Create a new geo node container = obj.createNode("geo", node_name=node_name) - # Remove the file node, it only loads static meshes - # Houdini 17 has removed the file node from the geo node - file_node = container.node("file1") - if file_node: - file_node.destroy() - # Create a usdimport node usdimport = container.createNode("usdimport", node_name=node_name) usdimport.setParms({"filepath1": file_path}) - # Ensure display flag is on the first input node and not on the OUT - # node to optimize "debug" displaying in the viewport. - usdimport.setDisplayFlag(True) - # Set new position for unpack node else it gets cluttered nodes = [container, usdimport] - for nr, node in enumerate(nodes): - node.setPosition([0, (0 - nr)]) self[:] = nodes From 135dd15870feb230231ce888949f5a4c56ce8749 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 14:26:18 +0100 Subject: [PATCH 25/60] Remove redundant assignment to `self[:]` --- client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py b/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py index 3607987e15..5b7e022e73 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_usd_sop.py @@ -39,8 +39,6 @@ class SopUsdImportLoader(load.LoaderPlugin): # Set new position for unpack node else it gets cluttered nodes = [container, usdimport] - self[:] = nodes - return pipeline.containerise( node_name, namespace, From c18103710db402d0923e28b41fdea9d66130583a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 14:28:07 +0100 Subject: [PATCH 26/60] Remove legacy collect instances --- .../plugins/publish/collect_instances.py | 100 ------------------ 1 file changed, 100 deletions(-) delete mode 100644 client/ayon_core/hosts/houdini/plugins/publish/collect_instances.py diff --git a/client/ayon_core/hosts/houdini/plugins/publish/collect_instances.py b/client/ayon_core/hosts/houdini/plugins/publish/collect_instances.py deleted file mode 100644 index 63537811cd..0000000000 --- a/client/ayon_core/hosts/houdini/plugins/publish/collect_instances.py +++ /dev/null @@ -1,100 +0,0 @@ -import hou - -import pyblish.api - -from ayon_core.pipeline import AYON_INSTANCE_ID, AVALON_INSTANCE_ID -from ayon_core.hosts.houdini.api import lib - - -class CollectInstances(pyblish.api.ContextPlugin): - """Gather instances by all node in out graph and pre-defined attributes - - This collector takes into account folders that are associated with - an specific node and marked with a unique identifier; - - Identifier: - id (str): "ayon.create.instance" - - Specific node: - The specific node is important because it dictates in which way the - product is being exported. - - alembic: will export Alembic file which supports cascading attributes - like 'cbId' and 'path' - geometry: Can export a wide range of file types, default out - - """ - - order = pyblish.api.CollectorOrder - 0.01 - label = "Collect Instances" - hosts = ["houdini"] - - def process(self, context): - - nodes = hou.node("/out").children() - nodes += hou.node("/obj").children() - - # Include instances in USD stage only when it exists so it - # remains backwards compatible with version before houdini 18 - stage = hou.node("/stage") - if stage: - nodes += stage.recursiveGlob("*", filter=hou.nodeTypeFilter.Rop) - - for node in nodes: - - if not node.parm("id"): - continue - - if node.evalParm("id") not in { - AYON_INSTANCE_ID, AVALON_INSTANCE_ID - }: - continue - - # instance was created by new creator code, skip it as - # it is already collected. - if node.parm("creator_identifier"): - continue - - has_family = node.evalParm("family") - assert has_family, "'%s' is missing 'family'" % node.name() - - self.log.info( - "Processing legacy instance node {}".format(node.path()) - ) - - data = lib.read(node) - # Check bypass state and reverse - if hasattr(node, "isBypassed"): - data.update({"active": not node.isBypassed()}) - - # temporarily translation of `active` to `publish` till issue has - # been resolved. - # https://github.com/pyblish/pyblish-base/issues/307 - if "active" in data: - data["publish"] = data["active"] - - # Create nice name if the instance has a frame range. - label = data.get("name", node.name()) - label += " (%s)" % data["folderPath"] # include folder in name - - instance = context.create_instance(label) - - # Include `families` using `family` data - product_type = data["family"] - data["productType"] = product_type - instance.data["families"] = [product_type] - - instance[:] = [node] - instance.data["instance_node"] = node.path() - instance.data.update(data) - - def sort_by_family(instance): - """Sort by family""" - return instance.data.get( - "families", instance.data.get("productType") - ) - - # Sort/grouped by family (preserving local index) - context[:] = sorted(context, key=sort_by_family) - - return context From 54db9178a3d8ad33630eda59aa9e5a5692f88a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Mon, 25 Mar 2024 15:20:51 +0100 Subject: [PATCH 27/60] :recycle: create manage script --- poetry.toml | 1 + scripts/setup_env.ps1 | 67 ---------- tools/manage.ps1 | 283 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 284 insertions(+), 67 deletions(-) delete mode 100644 scripts/setup_env.ps1 create mode 100644 tools/manage.ps1 diff --git a/poetry.toml b/poetry.toml index ab1033bd37..62e2dff2a2 100644 --- a/poetry.toml +++ b/poetry.toml @@ -1,2 +1,3 @@ [virtualenvs] in-project = true +create = true diff --git a/scripts/setup_env.ps1 b/scripts/setup_env.ps1 deleted file mode 100644 index 82ff515bc6..0000000000 --- a/scripts/setup_env.ps1 +++ /dev/null @@ -1,67 +0,0 @@ -$current_dir = Get-Location -$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent -$repo_root = (Get-Item $script_dir).parent.FullName -& git submodule update --init --recursive - - -function Exit-WithCode($exitcode) { - # Only exit this host process if it's a child of another PowerShell parent process... - $parentPID = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$PID" | Select-Object -Property ParentProcessId).ParentProcessId - $parentProcName = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$parentPID" | Select-Object -Property Name).Name - if ('powershell.exe' -eq $parentProcName) { $host.SetShouldExit($exitcode) } - - exit $exitcode - } - - -function Install-Poetry() { - Write-Host ">>> Installing Poetry ... " - $python = "python" - if (Get-Command "pyenv" -ErrorAction SilentlyContinue) { - if (-not (Test-Path -PathType Leaf -Path "$($repo_root)\.python-version")) { - $result = & pyenv global - if ($result -eq "no global version configured") { - Write-Host "!!! Using pyenv but having no local or global version of Python set." -Color Red, Yellow - Exit-WithCode 1 - } - } - $python = & pyenv which python - - } - - $env:POETRY_HOME="$repo_root\.poetry" - (Invoke-WebRequest -Uri https://install.python-poetry.org/ -UseBasicParsing).Content | & $($python) - -} - -Write-Host ">>> Reading Poetry ... " -NoNewline -if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) { - Write-Host "NOT FOUND" - Install-Poetry - Write-Host "INSTALLED" -} else { - Write-Host "OK" -} - -if (-not (Test-Path -PathType Leaf -Path "$($repo_root)\poetry.lock")) { - Write-Host ">>> Installing virtual environment and creating lock." -} else { - Write-Host ">>> Installing virtual environment from lock." -} -$startTime = [int][double]::Parse((Get-Date -UFormat %s)) -& "$env:POETRY_HOME\bin\poetry" install --no-root $poetry_verbosity --ansi -if ($LASTEXITCODE -ne 0) { - Write-Host "!!! ", "Poetry command failed." - Set-Location -Path $current_dir - Exit-WithCode 1 -} -Write-Host ">>> Installing pre-commit hooks ..." -& "$env:POETRY_HOME\bin\poetry" run pre-commit install -if ($LASTEXITCODE -ne 0) { - Write-Host "!!! Installation of pre-commit hooks failed." - Set-Location -Path $current_dir - Exit-WithCode 1 -} - -$endTime = [int][double]::Parse((Get-Date -UFormat %s)) -Set-Location -Path $current_dir -Write-Host ">>> Done in $( $endTime - $startTime ) secs." diff --git a/tools/manage.ps1 b/tools/manage.ps1 new file mode 100644 index 0000000000..b2187cbaa2 --- /dev/null +++ b/tools/manage.ps1 @@ -0,0 +1,283 @@ +<# +.SYNOPSIS + Helper script to run various tasks on ayon-core addon repository. + +.DESCRIPTION + This script will detect Python installation, and build OpenPype to `build` + directory using existing virtual environment created by Poetry (or + by running `/tools/create_venv.ps1`). It will then shuffle dependencies in + build folder to optimize for different Python versions (2/3) in Python host. + +.EXAMPLE + +PS> .\tools\manage.ps1 + +.EXAMPLE + +To create virtual environment using Poetry: +PS> .\tools\manage.ps1 create-env + +.EXAMPLE + +To run Ruff check: +PS> .\tools\manage.ps1 ruff-check + +.LINK +https://github.com/ynput/ayon-core + +#> + +# Settings and gitmodule init +$CurrentDir = Get-Location +$ScriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +$RepoRoot = (Get-Item $ScriptDir).parent.FullName +& git submodule update --init --recursive +$env:PSModulePath = $env:PSModulePath + ";$($openpype_root)\tools\modules\powershell" + +$FunctionName=$ARGS[0] +$Arguments=@() +if ($ARGS.Length -gt 1) { + $Arguments = $ARGS[1..($ARGS.Length - 1)] +} + +function Exit-WithCode($exitcode) { + # Only exit this host process if it's a child of another PowerShell parent process... + $parentPID = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$PID" | Select-Object -Property ParentProcessId).ParentProcessId + $parentProcName = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$parentPID" | Select-Object -Property Name).Name + if ('powershell.exe' -eq $parentProcName) { $host.SetShouldExit($exitcode) } + + exit $exitcode +} + +function Test-CommandExists { + param ( + [Parameter(Mandatory=$true)] + [string]$command + ) + + $commandExists = $null -ne (Get-Command $command -ErrorAction SilentlyContinue) + return $commandExists +} + +function Write-Info { + <# + .SYNOPSIS + Write-Info function to write information messages. + + It uses Write-Color if that is available, otherwise falls back to Write-Host. + + #> + [CmdletBinding()] + param ( + [alias ('T')] [String[]]$Text, + [alias ('C', 'ForegroundColor', 'FGC')] [ConsoleColor[]]$Color = [ConsoleColor]::White, + [alias ('B', 'BGC')] [ConsoleColor[]]$BackGroundColor = $null, + [alias ('Indent')][int] $StartTab = 0, + [int] $LinesBefore = 0, + [int] $LinesAfter = 0, + [int] $StartSpaces = 0, + [alias ('L')] [string] $LogFile = '', + [Alias('DateFormat', 'TimeFormat')][string] $DateTimeFormat = 'yyyy-MM-dd HH:mm:ss', + [alias ('LogTimeStamp')][bool] $LogTime = $true, + [int] $LogRetry = 2, + [ValidateSet('unknown', 'string', 'unicode', 'bigendianunicode', 'utf8', 'utf7', 'utf32', 'ascii', 'default', 'oem')][string]$Encoding = 'Unicode', + [switch] $ShowTime, + [switch] $NoNewLine + ) + if (Test-CommandExists "Write-Color") { + Write-Color -Text $Text -Color $Color -BackGroundColor $BackGroundColor -StartTab $StartTab -LinesBefore $LinesBefore -LinesAfter $LinesAfter -StartSpaces $StartSpaces -LogFile $LogFile -DateTimeFormat $DateTimeFormat -LogTime $LogTime -LogRetry $LogRetry -Encoding $Encoding -ShowTime $ShowTime -NoNewLine $NoNewLine + } else { + $message = $Text -join ' ' + if ($NoNewLine) + { + Write-Host $message -NoNewline + } + else + { + Write-Host $message + } + } +} + +$art = @" + + ▄██▄ + ▄███▄ ▀██▄ ▀██▀ ▄██▀ ▄██▀▀▀██▄ ▀███▄ █▄ + ▄▄ ▀██▄ ▀██▄ ▄██▀ ██▀ ▀██▄ ▄ ▀██▄ ███ + ▄██▀ ██▄ ▀ ▄▄ ▀ ██ ▄██ ███ ▀██▄ ███ + ▄██▀ ▀██▄ ██ ▀██▄ ▄██▀ ███ ▀██ ▀█▀ + ▄██▀ ▀██▄ ▀█ ▀██▄▄▄▄██▀ █▀ ▀██▄ + + · · - =[ by YNPUT ]:[ http://ayon.ynput.io ]= - · · + +"@ + +function Write-AsciiArt() { + Write-Host $art -ForegroundColor DarkGreen +} + +function Show-PSWarning() { + if ($PSVersionTable.PSVersion.Major -lt 7) { + Write-Info -Text "!!! ", "You are using old version of PowerShell - ", "$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)" -Color Red, Yellow, White + Write-Info -Text " Please update to at least 7.0 - ", "https://github.com/PowerShell/PowerShell/releases" -Color Yellow, White + Exit-WithCode 1 + } +} + +function Install-Poetry() { + Write-Info -Text ">>> ", "Installing Poetry ... " -Color Green, Gray + $python = "python" + if (Get-Command "pyenv" -ErrorAction SilentlyContinue) { + if (-not (Test-Path -PathType Leaf -Path "$($RepoRoot)\.python-version")) { + $result = & pyenv global + if ($result -eq "no global version configured") { + Write-Info "!!! Using pyenv but having no local or global version of Python set." -Color Red, Yellow + Exit-WithCode 1 + } + } + $python = & pyenv which python + + } + + $env:POETRY_HOME="$RepoRoot\.poetry" + (Invoke-WebRequest -Uri https://install.python-poetry.org/ -UseBasicParsing).Content | & $($python) - +} + +function Set-Cwd() { + Set-Location -Path $RepoRoot +} + +function Restore-Cwd() { + $tmp_current_dir = Get-Location + if ("$tmp_current_dir" -ne "$CurrentDir") { + Write-Info -Text ">>> ", "Restoring current directory" -Color Green, Gray + Set-Location -Path $CurrentDir + } +} + +function Initialize-Environment { + Write-Info -Text ">>> ", "Reading Poetry ... " -Color Green, Gray -NoNewline + if (-not(Test-Path -PathType Container -Path "$( $env:POETRY_HOME )\bin")) + { + Write-Info -Text "NOT FOUND" -Color Yellow + Install-Poetry + Write-Info -Text "INSTALLED" -Color Cyan + } + else + { + Write-Info -Text "OK" -Color Green + } + + if (-not(Test-Path -PathType Leaf -Path "$( $repo_root )\poetry.lock")) + { + Write-Info -Text ">>> ", "Installing virtual environment and creating lock." -Color Green, Gray + } + else + { + Write-Info -Text ">>> ", "Installing virtual environment from lock." -Color Green, Gray + } + $startTime = [int][double]::Parse((Get-Date -UFormat %s)) + & "$env:POETRY_HOME\bin\poetry" config virtualenvs.in-project true --local + & "$env:POETRY_HOME\bin\poetry" config virtualenvs.create true --local + & "$env:POETRY_HOME\bin\poetry" install --no-root $poetry_verbosity --ansi + if ($LASTEXITCODE -ne 0) + { + Write-Info -Text "!!! ", "Poetry command failed." -Color Red, Yellow + Restore-Cwd + Exit-WithCode 1 + } + if (Test-Path -PathType Container -Path "$( $repo_root )\.git") + { + Write-Info -Text ">>> ", "Installing pre-commit hooks ..." -Color Green, White + & "$env:POETRY_HOME\bin\poetry" run pre-commit install + if ($LASTEXITCODE -ne 0) + { + Write-Info -Text "!!! ", "Installation of pre-commit hooks failed." -Color Red, Yellow + } + } + $endTime = [int][double]::Parse((Get-Date -UFormat %s)) + Restore-Cwd + try + { + if (Test-CommandExists "New-BurntToastNotification") + { + $app_logo = "$repo_root\tools\icons\ayon.ico" + New-BurntToastNotification -AppLogo "$app_logo" -Text "AYON", "Virtual environment created.", "All done in $( $endTime - $startTime ) secs." + } + } + catch {} + Write-Info -Text ">>> ", "Virtual environment created." -Color Green, White +} + +function Invoke-Ruff { + param ( + [switch] $Fix + ) + $Poetry = "$RepoRoot\.poetry\bin\poetry.exe" + $RuffArgs = @( "run", "ruff", "check" ) + if ($Fix) { + $RuffArgs += "--fix" + } + & $Poetry $RuffArgs +} + +function Invoke-Codespell { + param ( + [switch] $Fix + ) + $Poetry = "$RepoRoot\.poetry\bin\poetry.exe" + $CodespellArgs = @( "run", "codespell" ) + if ($Fix) { + $CodespellArgs += "--fix" + } + & $Poetry $CodespellArgs +} + +function Write-Help { + <# + .SYNOPSIS + Write-Help function to write help messages. + #> + Write-Host "" + Write-Host "AYON Addon management script" + Write-Host "" + Write-Info -Text "Usage: ", "./manage.ps1 ", "[command]" -Color Gray, White, Cyan + Write-Host "" + Write-Host "Runtime targets:" + Write-Info -Text " create-env ", "Install Poetry and update venv by lock file" -Color White, Cyan + Write-Info -Text " ruff-check ", "Run Ruff check for the repository" -Color White, Cyan + Write-Info -Text " ruff-fix ", "Run Ruff fix for the repository" -Color White, Cyan + Write-Info -Text " codespell ", "Run codespell check for the repository" -Color White, Cyan + Write-Host "" +} + +function Resolve-Function { + if ($null -eq $FunctionName) { + Write-Help + return + } + $FunctionName = $FunctionName.ToLower() -replace "\W" + if ($FunctionName -eq "createenv") { + Set-Cwd + Initialize-Environment + } elseif ($FunctionName -eq "ruffcheck") { + Set-Cwd + Invoke-Ruff + } elseif ($FunctionName -eq "rufffix") { + Set-Cwd + Invoke-Ruff -Fix + } elseif ($FunctionName -eq "codespell") { + Set-Cwd + Invoke-CodeSpell + } else { + Write-Host "Unknown function ""$FunctionName""" + Write-Help + } +} + +# ----------------------------------------------------- + +Show-PSWarning +Write-AsciiArt + +Resolve-Function From a046c0145649c0b21cbf0bb057529bd88c3e073d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Mon, 25 Mar 2024 15:42:02 +0100 Subject: [PATCH 28/60] :pencil2: fix text --- tools/manage.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/manage.ps1 b/tools/manage.ps1 index b2187cbaa2..23c52d57be 100644 --- a/tools/manage.ps1 +++ b/tools/manage.ps1 @@ -243,7 +243,7 @@ function Write-Help { Write-Host "" Write-Info -Text "Usage: ", "./manage.ps1 ", "[command]" -Color Gray, White, Cyan Write-Host "" - Write-Host "Runtime targets:" + Write-Host "Commands:" Write-Info -Text " create-env ", "Install Poetry and update venv by lock file" -Color White, Cyan Write-Info -Text " ruff-check ", "Run Ruff check for the repository" -Color White, Cyan Write-Info -Text " ruff-fix ", "Run Ruff fix for the repository" -Color White, Cyan From 26b411b2d1f2d06d902cc4efb36428e2343f4b4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Mon, 25 Mar 2024 15:42:24 +0100 Subject: [PATCH 29/60] :recycle: add linux script --- scripts/setup_env.sh => tools/manage.sh | 122 +++++++++++++++++++++--- 1 file changed, 110 insertions(+), 12 deletions(-) rename scripts/setup_env.sh => tools/manage.sh (55%) diff --git a/scripts/setup_env.sh b/tools/manage.sh similarity index 55% rename from scripts/setup_env.sh rename to tools/manage.sh index 16298cb8bc..f40df80790 100644 --- a/scripts/setup_env.sh +++ b/tools/manage.sh @@ -83,16 +83,19 @@ realpath () { echo $(cd $(dirname "$1"); pwd)/$(basename "$1") } -main () { - detect_python || return 1 - +############################################################################## +# Create Virtual Environment +# Globals: +# repo_root +# POETRY_HOME +# poetry_verbosity +# Arguments: +# Path to resolve +# Returns: +# None +############################################################################### +create_env () { # Directories - repo_root=$(realpath $(dirname $(dirname "${BASH_SOURCE[0]}"))) - - if [[ -z $POETRY_HOME ]]; then - export POETRY_HOME="$repo_root/.poetry" - fi - pushd "$repo_root" > /dev/null || return > /dev/null echo -e "${BIGreen}>>>${RST} Reading Poetry ... \c" @@ -115,10 +118,105 @@ main () { return 1 fi - echo -e "${BIGreen}>>>${RST} Installing pre-commit hooks ..." - "$POETRY_HOME/bin/poetry" run pre-commit install + echo -e "${BIGreen}>>>${RST} Cleaning cache files ..." + clean_pyc + + "$POETRY_HOME/bin/poetry" run python -m pip install --disable-pip-version-check --force-reinstall pip + + if [ -d "$repo_root/.git" ]; then + echo -e "${BIGreen}>>>${RST} Installing pre-commit hooks ..." + "$POETRY_HOME/bin/poetry" run pre-commit install + fi +} + +print_art() { + echo -e "${BGreen}" + cat <<-EOF + + ▄██▄ + ▄███▄ ▀██▄ ▀██▀ ▄██▀ ▄██▀▀▀██▄ ▀███▄ █▄ + ▄▄ ▀██▄ ▀██▄ ▄██▀ ██▀ ▀██▄ ▄ ▀██▄ ███ + ▄██▀ ██▄ ▀ ▄▄ ▀ ██ ▄██ ███ ▀██▄ ███ + ▄██▀ ▀██▄ ██ ▀██▄ ▄██▀ ███ ▀██ ▀█▀ + ▄██▀ ▀██▄ ▀█ ▀██▄▄▄▄██▀ █▀ ▀██▄ + + · · - =[ by YNPUT ]:[ http://ayon.ynput.io ]= - · · + +EOF + echo -e "${RST}" +} + +default_help() { + print_art + echo -e "${BWhite}AYON Addon management script${RST}" + echo "" + echo -e "Usage: ${BWhite}./manage.sh${RST} ${BICyan}[command]${RST}" + echo "" + echo "${BWhite}Commands:${RST}" + echo " ${BWhite}create-env${RST} ${BCyan}Install Poetry and update venv by lock file${RST}" + echo " ${BWhite}ruff-check${RST} ${BCyan}Run Ruff check for the repository${RST}" + echo " ${BWhite}ruff-fix${RST} ${BCyan}Run Ruff fix for the repository${RST}" + echo " ${BWhite}codespell${RST} ${BCyan}Run codespell check for the repository${RST}" + echo "" +} + +run_ruff () { + echo -e "${BIGreen}>>>${RST} Running Ruff check ..." + "$POETRY_HOME/bin/poetry" run ruff +} + +run_ruff_check () { + echo -e "${BIGreen}>>>${RST} Running Ruff fix ..." + "$POETRY_HOME/bin/poetry" run ruff --fix +} + +run_codespell () { + echo -e "${BIGreen}>>>${RST} Running codespell check ..." + "$POETRY_HOME/bin/poetry" run codespell +} + +main () { + detect_python || return 1 + + # Directories + repo_root=$(realpath $(dirname $(dirname "${BASH_SOURCE[0]}"))) + + if [[ -z $POETRY_HOME ]]; then + export POETRY_HOME="$repo_root/.poetry" + fi + + pushd "$repo_root" > /dev/null || return > /dev/null + + # Use first argument, lower and keep only characters + function_name="$(echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z]*//g')" + + case $function_name in + "createenv") + create_env || return_code=$? + exit $return_code + ;; + "ruffcheck") + run_ruff || return_code=$? + exit $return_code + ;; + "rufffix") + run_ruff_check || return_code=$? + exit $return_code + ;; + "codespell") + run_codespell || return_code=$? + exit $return_code + ;; + esac + + if [ "$function_name" != "" ]; then + echo -e "${BIRed}!!!${RST} Unknown function name: $function_name" + fi + + default_help + exit $return_code } return_code=0 -main || return_code=$? +main "$@" || return_code=$? exit $return_code From 2b1e31001c74a6dd263236e0f7a5c0600c372249 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 15:52:11 +0100 Subject: [PATCH 30/60] duplicated non python host launch script for photoshop --- .../hosts/photoshop/api/launch_script.py | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 client/ayon_core/hosts/photoshop/api/launch_script.py diff --git a/client/ayon_core/hosts/photoshop/api/launch_script.py b/client/ayon_core/hosts/photoshop/api/launch_script.py new file mode 100644 index 0000000000..c036b63c46 --- /dev/null +++ b/client/ayon_core/hosts/photoshop/api/launch_script.py @@ -0,0 +1,93 @@ +"""Script wraps launch mechanism of Photoshop implementations. + +Arguments passed to the script are passed to launch function in host +implementation. In all cases requires host app executable and may contain +workfile or others. +""" + +import os +import sys + +from ayon_core.hosts.photoshop.api.lib import main + +# Get current file to locate start point of sys.argv +CURRENT_FILE = os.path.abspath(__file__) + + +def show_error_messagebox(title, message, detail_message=None): + """Function will show message and process ends after closing it.""" + from qtpy import QtWidgets, QtCore + from ayon_core import style + + app = QtWidgets.QApplication([]) + app.setStyleSheet(style.load_stylesheet()) + + msgbox = QtWidgets.QMessageBox() + msgbox.setWindowTitle(title) + msgbox.setText(message) + + if detail_message: + msgbox.setDetailedText(detail_message) + + msgbox.setWindowModality(QtCore.Qt.ApplicationModal) + msgbox.show() + + sys.exit(app.exec_()) + + +def on_invalid_args(script_not_found): + """Show to user message box saying that something went wrong. + + Tell user that arguments to launch implementation are invalid with + arguments details. + + Args: + script_not_found (bool): Use different message based on this value. + """ + + title = "Invalid arguments" + joined_args = ", ".join("\"{}\"".format(arg) for arg in sys.argv) + if script_not_found: + submsg = "Where couldn't find script path:\n\"{}\"" + else: + submsg = "Expected Host executable after script path:\n\"{}\"" + + message = "BUG: Got invalid arguments so can't launch Host application." + detail_message = "Process was launched with arguments:\n{}\n\n{}".format( + joined_args, + submsg.format(CURRENT_FILE) + ) + + show_error_messagebox(title, message, detail_message) + + +def main(argv): + # Modify current file path to find match in sys.argv which may be different + # on windows (different letter cases and slashes). + modified_current_file = CURRENT_FILE.replace("\\", "/").lower() + + # Create a copy of sys argv + sys_args = list(argv) + after_script_idx = None + # Find script path in sys.argv to know index of argv where host + # executable should be. + for idx, item in enumerate(sys_args): + if item.replace("\\", "/").lower() == modified_current_file: + after_script_idx = idx + 1 + break + + # Validate that there is at least one argument after script path + launch_args = None + if after_script_idx is not None: + launch_args = sys_args[after_script_idx:] + + if launch_args: + # Launch host implementation + main(*launch_args) + else: + # Show message box + on_invalid_args(after_script_idx is None) + + +if __name__ == "__main__": + main(sys.argv) From fee6a9b4485de958af128c9db0f7da8f4dbfbfa6 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 15:52:52 +0100 Subject: [PATCH 31/60] renamed 'PHOTOSHOP_HOST_DIR' to 'PHOTOSHOP_ADDON_ROOT' --- client/ayon_core/hosts/photoshop/__init__.py | 4 ++-- client/ayon_core/hosts/photoshop/addon.py | 2 +- client/ayon_core/hosts/photoshop/api/pipeline.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/ayon_core/hosts/photoshop/__init__.py b/client/ayon_core/hosts/photoshop/__init__.py index 773f73d624..0c79afaab8 100644 --- a/client/ayon_core/hosts/photoshop/__init__.py +++ b/client/ayon_core/hosts/photoshop/__init__.py @@ -1,10 +1,10 @@ from .addon import ( + PHOTOSHOP_ADDON_ROOT, PhotoshopAddon, - PHOTOSHOP_HOST_DIR, ) __all__ = ( + "PHOTOSHOP_ADDON_ROOT", "PhotoshopAddon", - "PHOTOSHOP_HOST_DIR", ) diff --git a/client/ayon_core/hosts/photoshop/addon.py b/client/ayon_core/hosts/photoshop/addon.py index 3016912960..28833121c4 100644 --- a/client/ayon_core/hosts/photoshop/addon.py +++ b/client/ayon_core/hosts/photoshop/addon.py @@ -1,7 +1,7 @@ import os from ayon_core.addon import AYONAddon, IHostAddon -PHOTOSHOP_HOST_DIR = os.path.dirname(os.path.abspath(__file__)) +PHOTOSHOP_ADDON_ROOT = os.path.dirname(os.path.abspath(__file__)) class PhotoshopAddon(AYONAddon, IHostAddon): diff --git a/client/ayon_core/hosts/photoshop/api/pipeline.py b/client/ayon_core/hosts/photoshop/api/pipeline.py index 32f66cf7fb..27cfa5a7b5 100644 --- a/client/ayon_core/hosts/photoshop/api/pipeline.py +++ b/client/ayon_core/hosts/photoshop/api/pipeline.py @@ -21,14 +21,14 @@ from ayon_core.host import ( ) from ayon_core.pipeline.load import any_outdated_containers -from ayon_core.hosts.photoshop import PHOTOSHOP_HOST_DIR +from ayon_core.hosts.photoshop import PHOTOSHOP_ADDON_ROOT from ayon_core.tools.utils import get_ayon_qt_app from . import lib log = Logger.get_logger(__name__) -PLUGINS_DIR = os.path.join(PHOTOSHOP_HOST_DIR, "plugins") +PLUGINS_DIR = os.path.join(PHOTOSHOP_ADDON_ROOT, "plugins") PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish") LOAD_PATH = os.path.join(PLUGINS_DIR, "load") CREATE_PATH = os.path.join(PLUGINS_DIR, "create") From aaea1e14859799dd8c443c832dce2ffa75be8e3f Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 15:53:17 +0100 Subject: [PATCH 32/60] photoshop has own prelaunch hook to modify launch arguments --- .../hooks/pre_non_python_host_launch.py | 2 +- client/ayon_core/hosts/photoshop/__init__.py | 2 + client/ayon_core/hosts/photoshop/addon.py | 14 +++ .../hosts/photoshop/hooks/pre_launch_args.py | 95 +++++++++++++++++++ 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py diff --git a/client/ayon_core/hooks/pre_non_python_host_launch.py b/client/ayon_core/hooks/pre_non_python_host_launch.py index fed4c99447..3d3c24b308 100644 --- a/client/ayon_core/hooks/pre_non_python_host_launch.py +++ b/client/ayon_core/hooks/pre_non_python_host_launch.py @@ -17,7 +17,7 @@ class NonPythonHostHook(PreLaunchHook): python script which launch the host. For these cases it is necessary to prepend python (or ayon) executable and script path before application's. """ - app_groups = {"harmony", "photoshop", "aftereffects"} + app_groups = {"harmony", "aftereffects"} order = 20 launch_types = {LaunchTypes.local} diff --git a/client/ayon_core/hosts/photoshop/__init__.py b/client/ayon_core/hosts/photoshop/__init__.py index 0c79afaab8..cf21b7df75 100644 --- a/client/ayon_core/hosts/photoshop/__init__.py +++ b/client/ayon_core/hosts/photoshop/__init__.py @@ -1,10 +1,12 @@ from .addon import ( PHOTOSHOP_ADDON_ROOT, PhotoshopAddon, + get_launch_script_path, ) __all__ = ( "PHOTOSHOP_ADDON_ROOT", "PhotoshopAddon", + "get_launch_script_path", ) diff --git a/client/ayon_core/hosts/photoshop/addon.py b/client/ayon_core/hosts/photoshop/addon.py index 28833121c4..65fe6a7cd1 100644 --- a/client/ayon_core/hosts/photoshop/addon.py +++ b/client/ayon_core/hosts/photoshop/addon.py @@ -20,3 +20,17 @@ class PhotoshopAddon(AYONAddon, IHostAddon): def get_workfile_extensions(self): return [".psd", ".psb"] + + def get_launch_hook_paths(self, app): + if app.host_name != self.host_name: + return [] + return [ + os.path.join(PHOTOSHOP_ADDON_ROOT, "hooks") + ] + + +def get_launch_script_path(): + return os.path.join( + PHOTOSHOP_ADDON_ROOT, "api", "launch_script.py" + ) + diff --git a/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py b/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py new file mode 100644 index 0000000000..0689a6c2f0 --- /dev/null +++ b/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py @@ -0,0 +1,95 @@ +import os +import platform +import subprocess + +from ayon_core.lib import get_ayon_launcher_args +from ayon_core.lib.applications import ( + PreLaunchHook, + LaunchTypes, +) +from ayon_core.hosts.photoshop import get_launch_script_path + + +def get_launch_kwargs(kwargs): + """Explicit setting of kwargs for Popen for Photoshop. + + Expected behavior + - ayon_console opens window with logs + - ayon has stdout/stderr available for capturing + + Args: + kwargs (Union[dict, None]): Current kwargs or None. + + """ + if kwargs is None: + kwargs = {} + + if platform.system().lower() != "windows": + return kwargs + + executable_path = os.environ.get("AYON_EXECUTABLE") + + executable_filename = "" + if executable_path: + executable_filename = os.path.basename(executable_path) + + is_gui_executable = "ayon_console" not in executable_filename + if is_gui_executable: + kwargs.update({ + "creationflags": subprocess.CREATE_NO_WINDOW, + "stdout": subprocess.DEVNULL, + "stderr": subprocess.DEVNULL + }) + else: + kwargs.update({ + "creationflags": subprocess.CREATE_NEW_CONSOLE + }) + return kwargs + + +class PhotoshopPrelaunchHook(PreLaunchHook): + """Launch arguments preparation. + + Hook add python executable and script path to Photoshop implementation + before Photoshop executable and add last workfile path to launch arguments. + + Existence of last workfile is checked. If workfile does not exists tries + to copy templated workfile from predefined path. + """ + app_groups = {"photoshop"} + + order = 20 + launch_types = {LaunchTypes.local} + + def execute(self): + # Pop executable + executable_path = self.launch_context.launch_args.pop(0) + + # Pop rest of launch arguments - There should not be other arguments! + remainders = [] + while self.launch_context.launch_args: + remainders.append(self.launch_context.launch_args.pop(0)) + + script_path = get_launch_script_path() + + new_launch_args = get_ayon_launcher_args( + "run", script_path, executable_path + ) + # Add workfile path if exists + workfile_path = self.data["last_workfile_path"] + if ( + self.data.get("start_last_workfile") + and workfile_path + and os.path.exists(workfile_path) + ): + new_launch_args.append(workfile_path) + + # Append as whole list as these arguments should not be separated + self.launch_context.launch_args.append(new_launch_args) + + if remainders: + self.launch_context.launch_args.extend(remainders) + + self.launch_context.kwargs = get_launch_kwargs( + self.launch_context.kwargs + ) From 0d75102d8a255237b5d8fa180e13d0febe250c31 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 15:53:54 +0100 Subject: [PATCH 33/60] aftereffects have own launch script --- .../hosts/aftereffects/api/launch_script.py | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 client/ayon_core/hosts/aftereffects/api/launch_script.py diff --git a/client/ayon_core/hosts/aftereffects/api/launch_script.py b/client/ayon_core/hosts/aftereffects/api/launch_script.py new file mode 100644 index 0000000000..ad4e779bd0 --- /dev/null +++ b/client/ayon_core/hosts/aftereffects/api/launch_script.py @@ -0,0 +1,93 @@ +"""Script wraps launch mechanism of AfterEffects implementations. + +Arguments passed to the script are passed to launch function in host +implementation. In all cases requires host app executable and may contain +workfile or others. +""" + +import os +import sys + +from ayon_core.hosts.aftereffects.api.launch_logic import main + +# Get current file to locate start point of sys.argv +CURRENT_FILE = os.path.abspath(__file__) + + +def show_error_messagebox(title, message, detail_message=None): + """Function will show message and process ends after closing it.""" + from qtpy import QtWidgets, QtCore + from ayon_core import style + + app = QtWidgets.QApplication([]) + app.setStyleSheet(style.load_stylesheet()) + + msgbox = QtWidgets.QMessageBox() + msgbox.setWindowTitle(title) + msgbox.setText(message) + + if detail_message: + msgbox.setDetailedText(detail_message) + + msgbox.setWindowModality(QtCore.Qt.ApplicationModal) + msgbox.show() + + sys.exit(app.exec_()) + + +def on_invalid_args(script_not_found): + """Show to user message box saying that something went wrong. + + Tell user that arguments to launch implementation are invalid with + arguments details. + + Args: + script_not_found (bool): Use different message based on this value. + """ + + title = "Invalid arguments" + joined_args = ", ".join("\"{}\"".format(arg) for arg in sys.argv) + if script_not_found: + submsg = "Where couldn't find script path:\n\"{}\"" + else: + submsg = "Expected Host executable after script path:\n\"{}\"" + + message = "BUG: Got invalid arguments so can't launch Host application." + detail_message = "Process was launched with arguments:\n{}\n\n{}".format( + joined_args, + submsg.format(CURRENT_FILE) + ) + + show_error_messagebox(title, message, detail_message) + + +def main(argv): + # Modify current file path to find match in sys.argv which may be different + # on windows (different letter cases and slashes). + modified_current_file = CURRENT_FILE.replace("\\", "/").lower() + + # Create a copy of sys argv + sys_args = list(argv) + after_script_idx = None + # Find script path in sys.argv to know index of argv where host + # executable should be. + for idx, item in enumerate(sys_args): + if item.replace("\\", "/").lower() == modified_current_file: + after_script_idx = idx + 1 + break + + # Validate that there is at least one argument after script path + launch_args = None + if after_script_idx is not None: + launch_args = sys_args[after_script_idx:] + + if launch_args: + # Launch host implementation + main(*launch_args) + else: + # Show message box + on_invalid_args(after_script_idx is None) + + +if __name__ == "__main__": + main(sys.argv) From 720de823cf973dab3d75bede890cf49dc7fb7efc Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 15:54:36 +0100 Subject: [PATCH 34/60] aftereffects has own prelaunch hook to modify launch arguments --- .../hooks/pre_non_python_host_launch.py | 2 +- .../ayon_core/hosts/aftereffects/__init__.py | 8 +- client/ayon_core/hosts/aftereffects/addon.py | 17 ++++ .../hosts/aftereffects/api/launch_logic.py | 1 - .../aftereffects/hooks/pre_launch_args.py | 95 +++++++++++++++++++ 5 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py diff --git a/client/ayon_core/hooks/pre_non_python_host_launch.py b/client/ayon_core/hooks/pre_non_python_host_launch.py index 3d3c24b308..a65e0ecba4 100644 --- a/client/ayon_core/hooks/pre_non_python_host_launch.py +++ b/client/ayon_core/hooks/pre_non_python_host_launch.py @@ -17,7 +17,7 @@ class NonPythonHostHook(PreLaunchHook): python script which launch the host. For these cases it is necessary to prepend python (or ayon) executable and script path before application's. """ - app_groups = {"harmony", "aftereffects"} + app_groups = {"harmony"} order = 20 launch_types = {LaunchTypes.local} diff --git a/client/ayon_core/hosts/aftereffects/__init__.py b/client/ayon_core/hosts/aftereffects/__init__.py index ae750d05b6..02ab287629 100644 --- a/client/ayon_core/hosts/aftereffects/__init__.py +++ b/client/ayon_core/hosts/aftereffects/__init__.py @@ -1,6 +1,12 @@ -from .addon import AfterEffectsAddon +from .addon import ( + AFTEREFFECTS_ADDON_ROOT, + AfterEffectsAddon, + get_launch_script_path, +) __all__ = ( + "AFTEREFFECTS_ADDON_ROOT", "AfterEffectsAddon", + "get_launch_script_path", ) diff --git a/client/ayon_core/hosts/aftereffects/addon.py b/client/ayon_core/hosts/aftereffects/addon.py index 46d0818247..fc54043c1d 100644 --- a/client/ayon_core/hosts/aftereffects/addon.py +++ b/client/ayon_core/hosts/aftereffects/addon.py @@ -1,5 +1,9 @@ +import os + from ayon_core.addon import AYONAddon, IHostAddon +AFTEREFFECTS_ADDON_ROOT = os.path.dirname(os.path.abspath(__file__)) + class AfterEffectsAddon(AYONAddon, IHostAddon): name = "aftereffects" @@ -17,3 +21,16 @@ class AfterEffectsAddon(AYONAddon, IHostAddon): def get_workfile_extensions(self): return [".aep"] + + def get_launch_hook_paths(self, app): + if app.host_name != self.host_name: + return [] + return [ + os.path.join(AFTEREFFECTS_ADDON_ROOT, "hooks") + ] + + +def get_launch_script_path(): + return os.path.join( + AFTEREFFECTS_ADDON_ROOT, "api", "launch_script.py" + ) diff --git a/client/ayon_core/hosts/aftereffects/api/launch_logic.py b/client/ayon_core/hosts/aftereffects/api/launch_logic.py index d0e4e8beae..5a23f2cb35 100644 --- a/client/ayon_core/hosts/aftereffects/api/launch_logic.py +++ b/client/ayon_core/hosts/aftereffects/api/launch_logic.py @@ -7,7 +7,6 @@ import asyncio import functools import traceback - from wsrpc_aiohttp import ( WebSocketRoute, WebSocketAsync diff --git a/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py b/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py new file mode 100644 index 0000000000..2c5baa3b68 --- /dev/null +++ b/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py @@ -0,0 +1,95 @@ +import os +import platform +import subprocess + +from ayon_core.lib import get_ayon_launcher_args +from ayon_core.lib.applications import ( + PreLaunchHook, + LaunchTypes, +) +from ayon_core.hosts.aftereffects import get_launch_script_path + + +def get_launch_kwargs(kwargs): + """Explicit setting of kwargs for Popen for AfterEffects. + + Expected behavior + - ayon_console opens window with logs + - ayon has stdout/stderr available for capturing + + Args: + kwargs (Union[dict, None]): Current kwargs or None. + + """ + if kwargs is None: + kwargs = {} + + if platform.system().lower() != "windows": + return kwargs + + executable_path = os.environ.get("AYON_EXECUTABLE") + + executable_filename = "" + if executable_path: + executable_filename = os.path.basename(executable_path) + + is_in_ui_launcher = "ayon_console" not in executable_filename + if is_in_ui_launcher: + kwargs.update({ + "creationflags": subprocess.CREATE_NO_WINDOW, + "stdout": subprocess.DEVNULL, + "stderr": subprocess.DEVNULL + }) + else: + kwargs.update({ + "creationflags": subprocess.CREATE_NEW_CONSOLE + }) + return kwargs + + +class AEPrelaunchHook(PreLaunchHook): + """Launch arguments preparation. + + Hook add python executable and script path to AE implementation before + AE executable and add last workfile path to launch arguments. + + Existence of last workfile is checked. If workfile does not exists tries + to copy templated workfile from predefined path. + """ + app_groups = {"aftereffects"} + + order = 20 + launch_types = {LaunchTypes.local} + + def execute(self): + # Pop executable + executable_path = self.launch_context.launch_args.pop(0) + + # Pop rest of launch arguments - There should not be other arguments! + remainders = [] + while self.launch_context.launch_args: + remainders.append(self.launch_context.launch_args.pop(0)) + + script_path = get_launch_script_path() + + new_launch_args = get_ayon_launcher_args( + "run", script_path, executable_path + ) + # Add workfile path if exists + workfile_path = self.data["last_workfile_path"] + if ( + self.data.get("start_last_workfile") + and workfile_path + and os.path.exists(workfile_path) + ): + new_launch_args.append(workfile_path) + + # Append as whole list as these arguments should not be separated + self.launch_context.launch_args.append(new_launch_args) + + if remainders: + self.launch_context.launch_args.extend(remainders) + + self.launch_context.kwargs = get_launch_kwargs( + self.launch_context.kwargs + ) From afd2e3518c36353f3ed206ffc4f9456c7b64ba03 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Mon, 25 Mar 2024 16:20:41 +0100 Subject: [PATCH 35/60] :recycle: fix linux version --- .hound.yml | 6 +++--- tools/manage.ps1 | 0 tools/manage.sh | 14 +++++++------- 3 files changed, 10 insertions(+), 10 deletions(-) mode change 100644 => 100755 tools/manage.ps1 mode change 100644 => 100755 tools/manage.sh diff --git a/.hound.yml b/.hound.yml index df9cdab64a..de5adb3154 100644 --- a/.hound.yml +++ b/.hound.yml @@ -1,3 +1,3 @@ -flake8: - enabled: true - config_file: setup.cfg +flake8: + enabled: true + config_file: setup.cfg diff --git a/tools/manage.ps1 b/tools/manage.ps1 old mode 100644 new mode 100755 diff --git a/tools/manage.sh b/tools/manage.sh old mode 100644 new mode 100755 index f40df80790..923953bf96 --- a/tools/manage.sh +++ b/tools/manage.sh @@ -152,22 +152,22 @@ default_help() { echo "" echo -e "Usage: ${BWhite}./manage.sh${RST} ${BICyan}[command]${RST}" echo "" - echo "${BWhite}Commands:${RST}" - echo " ${BWhite}create-env${RST} ${BCyan}Install Poetry and update venv by lock file${RST}" - echo " ${BWhite}ruff-check${RST} ${BCyan}Run Ruff check for the repository${RST}" - echo " ${BWhite}ruff-fix${RST} ${BCyan}Run Ruff fix for the repository${RST}" - echo " ${BWhite}codespell${RST} ${BCyan}Run codespell check for the repository${RST}" + echo -e "${BWhite}Commands:${RST}" + echo -e " ${BWhite}create-env${RST} ${BCyan}Install Poetry and update venv by lock file${RST}" + echo -e " ${BWhite}ruff-check${RST} ${BCyan}Run Ruff check for the repository${RST}" + echo -e " ${BWhite}ruff-fix${RST} ${BCyan}Run Ruff fix for the repository${RST}" + echo -e " ${BWhite}codespell${RST} ${BCyan}Run codespell check for the repository${RST}" echo "" } run_ruff () { echo -e "${BIGreen}>>>${RST} Running Ruff check ..." - "$POETRY_HOME/bin/poetry" run ruff + "$POETRY_HOME/bin/poetry" run ruff check } run_ruff_check () { echo -e "${BIGreen}>>>${RST} Running Ruff fix ..." - "$POETRY_HOME/bin/poetry" run ruff --fix + "$POETRY_HOME/bin/poetry" run ruff check --fix } run_codespell () { From 96aac985c2545b5e8e5bf74a96e448a3b667463c Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 16:23:23 +0100 Subject: [PATCH 36/60] copied non python launch script to harmony --- .../hosts/harmony/api/launch_script.py | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 client/ayon_core/hosts/harmony/api/launch_script.py diff --git a/client/ayon_core/hosts/harmony/api/launch_script.py b/client/ayon_core/hosts/harmony/api/launch_script.py new file mode 100644 index 0000000000..1f2c36b7e6 --- /dev/null +++ b/client/ayon_core/hosts/harmony/api/launch_script.py @@ -0,0 +1,93 @@ +"""Script wraps launch mechanism of Harmony implementations. + +Arguments passed to the script are passed to launch function in host +implementation. In all cases requires host app executable and may contain +workfile or others. +""" + +import os +import sys + +from ayon_core.hosts.harmony.api.lib import main + +# Get current file to locate start point of sys.argv +CURRENT_FILE = os.path.abspath(__file__) + + +def show_error_messagebox(title, message, detail_message=None): + """Function will show message and process ends after closing it.""" + from qtpy import QtWidgets, QtCore + from ayon_core import style + + app = QtWidgets.QApplication([]) + app.setStyleSheet(style.load_stylesheet()) + + msgbox = QtWidgets.QMessageBox() + msgbox.setWindowTitle(title) + msgbox.setText(message) + + if detail_message: + msgbox.setDetailedText(detail_message) + + msgbox.setWindowModality(QtCore.Qt.ApplicationModal) + msgbox.show() + + sys.exit(app.exec_()) + + +def on_invalid_args(script_not_found): + """Show to user message box saying that something went wrong. + + Tell user that arguments to launch implementation are invalid with + arguments details. + + Args: + script_not_found (bool): Use different message based on this value. + """ + + title = "Invalid arguments" + joined_args = ", ".join("\"{}\"".format(arg) for arg in sys.argv) + if script_not_found: + submsg = "Where couldn't find script path:\n\"{}\"" + else: + submsg = "Expected Host executable after script path:\n\"{}\"" + + message = "BUG: Got invalid arguments so can't launch Host application." + detail_message = "Process was launched with arguments:\n{}\n\n{}".format( + joined_args, + submsg.format(CURRENT_FILE) + ) + + show_error_messagebox(title, message, detail_message) + + +def main(argv): + # Modify current file path to find match in sys.argv which may be different + # on windows (different letter cases and slashes). + modified_current_file = CURRENT_FILE.replace("\\", "/").lower() + + # Create a copy of sys argv + sys_args = list(argv) + after_script_idx = None + # Find script path in sys.argv to know index of argv where host + # executable should be. + for idx, item in enumerate(sys_args): + if item.replace("\\", "/").lower() == modified_current_file: + after_script_idx = idx + 1 + break + + # Validate that there is at least one argument after script path + launch_args = None + if after_script_idx is not None: + launch_args = sys_args[after_script_idx:] + + if launch_args: + # Launch host implementation + main(*launch_args) + else: + # Show message box + on_invalid_args(after_script_idx is None) + + +if __name__ == "__main__": + main(sys.argv) From da395ae5305cb63cd19140cc2b48296facc94809 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 16:23:57 +0100 Subject: [PATCH 37/60] renamed 'HARMONY_HOST_DIR' to 'HARMONY_ADDON_ROOT' --- client/ayon_core/hosts/harmony/__init__.py | 4 ++-- client/ayon_core/hosts/harmony/addon.py | 4 ++-- client/ayon_core/hosts/harmony/api/pipeline.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/ayon_core/hosts/harmony/__init__.py b/client/ayon_core/hosts/harmony/__init__.py index 9177eaa285..449bb96a4f 100644 --- a/client/ayon_core/hosts/harmony/__init__.py +++ b/client/ayon_core/hosts/harmony/__init__.py @@ -1,10 +1,10 @@ from .addon import ( - HARMONY_HOST_DIR, + HARMONY_ADDON_ROOT, HarmonyAddon, ) __all__ = ( - "HARMONY_HOST_DIR", + "HARMONY_ADDON_ROOT", "HarmonyAddon", ) diff --git a/client/ayon_core/hosts/harmony/addon.py b/client/ayon_core/hosts/harmony/addon.py index 476d569415..7f8776cd74 100644 --- a/client/ayon_core/hosts/harmony/addon.py +++ b/client/ayon_core/hosts/harmony/addon.py @@ -1,7 +1,7 @@ import os from ayon_core.addon import AYONAddon, IHostAddon -HARMONY_HOST_DIR = os.path.dirname(os.path.abspath(__file__)) +HARMONY_ADDON_ROOT = os.path.dirname(os.path.abspath(__file__)) class HarmonyAddon(AYONAddon, IHostAddon): @@ -11,7 +11,7 @@ class HarmonyAddon(AYONAddon, IHostAddon): def add_implementation_envs(self, env, _app): """Modify environments to contain all required for implementation.""" openharmony_path = os.path.join( - HARMONY_HOST_DIR, "vendor", "OpenHarmony" + HARMONY_ADDON_ROOT, "vendor", "OpenHarmony" ) # TODO check if is already set? What to do if is already set? env["LIB_OPENHARMONY_PATH"] = openharmony_path diff --git a/client/ayon_core/hosts/harmony/api/pipeline.py b/client/ayon_core/hosts/harmony/api/pipeline.py index a753a32ebb..d842ccd414 100644 --- a/client/ayon_core/hosts/harmony/api/pipeline.py +++ b/client/ayon_core/hosts/harmony/api/pipeline.py @@ -15,13 +15,13 @@ from ayon_core.pipeline import ( from ayon_core.pipeline.load import get_outdated_containers from ayon_core.pipeline.context_tools import get_current_project_folder -from ayon_core.hosts.harmony import HARMONY_HOST_DIR +from ayon_core.hosts.harmony import HARMONY_ADDON_ROOT import ayon_core.hosts.harmony.api as harmony log = logging.getLogger("ayon_core.hosts.harmony") -PLUGINS_DIR = os.path.join(HARMONY_HOST_DIR, "plugins") +PLUGINS_DIR = os.path.join(HARMONY_ADDON_ROOT, "plugins") PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish") LOAD_PATH = os.path.join(PLUGINS_DIR, "load") CREATE_PATH = os.path.join(PLUGINS_DIR, "create") From 2119e735828c44ea23fc4a9d463382e474f7367a Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 16:25:14 +0100 Subject: [PATCH 38/60] harmony has own prelaunch hook --- .../hooks/pre_non_python_host_launch.py | 58 ----------- client/ayon_core/hosts/harmony/__init__.py | 2 + client/ayon_core/hosts/harmony/addon.py | 13 +++ .../hosts/harmony/hooks/pre_launch_args.py | 95 +++++++++++++++++++ 4 files changed, 110 insertions(+), 58 deletions(-) delete mode 100644 client/ayon_core/hooks/pre_non_python_host_launch.py create mode 100644 client/ayon_core/hosts/harmony/hooks/pre_launch_args.py diff --git a/client/ayon_core/hooks/pre_non_python_host_launch.py b/client/ayon_core/hooks/pre_non_python_host_launch.py deleted file mode 100644 index a65e0ecba4..0000000000 --- a/client/ayon_core/hooks/pre_non_python_host_launch.py +++ /dev/null @@ -1,58 +0,0 @@ -import os - -from ayon_core.lib import get_ayon_launcher_args -from ayon_core.lib.applications import ( - get_non_python_host_kwargs, - PreLaunchHook, - LaunchTypes, -) - -from ayon_core import AYON_CORE_ROOT - - -class NonPythonHostHook(PreLaunchHook): - """Launch arguments preparation. - - Non python host implementation do not launch host directly but use - python script which launch the host. For these cases it is necessary to - prepend python (or ayon) executable and script path before application's. - """ - app_groups = {"harmony"} - - order = 20 - launch_types = {LaunchTypes.local} - - def execute(self): - # Pop executable - executable_path = self.launch_context.launch_args.pop(0) - - # Pop rest of launch arguments - There should not be other arguments! - remainders = [] - while self.launch_context.launch_args: - remainders.append(self.launch_context.launch_args.pop(0)) - - script_path = os.path.join( - AYON_CORE_ROOT, - "scripts", - "non_python_host_launch.py" - ) - - new_launch_args = get_ayon_launcher_args( - "run", script_path, executable_path - ) - # Add workfile path if exists - workfile_path = self.data["last_workfile_path"] - if ( - self.data.get("start_last_workfile") - and workfile_path - and os.path.exists(workfile_path)): - new_launch_args.append(workfile_path) - - # Append as whole list as these areguments should not be separated - self.launch_context.launch_args.append(new_launch_args) - - if remainders: - self.launch_context.launch_args.extend(remainders) - - self.launch_context.kwargs = \ - get_non_python_host_kwargs(self.launch_context.kwargs) diff --git a/client/ayon_core/hosts/harmony/__init__.py b/client/ayon_core/hosts/harmony/__init__.py index 449bb96a4f..6454d6f9d7 100644 --- a/client/ayon_core/hosts/harmony/__init__.py +++ b/client/ayon_core/hosts/harmony/__init__.py @@ -1,10 +1,12 @@ from .addon import ( HARMONY_ADDON_ROOT, HarmonyAddon, + get_launch_script_path, ) __all__ = ( "HARMONY_ADDON_ROOT", "HarmonyAddon", + "get_launch_script_path", ) diff --git a/client/ayon_core/hosts/harmony/addon.py b/client/ayon_core/hosts/harmony/addon.py index 7f8776cd74..1915a7eb6f 100644 --- a/client/ayon_core/hosts/harmony/addon.py +++ b/client/ayon_core/hosts/harmony/addon.py @@ -18,3 +18,16 @@ class HarmonyAddon(AYONAddon, IHostAddon): def get_workfile_extensions(self): return [".zip"] + + def get_launch_hook_paths(self, app): + if app.host_name != self.host_name: + return [] + return [ + os.path.join(HARMONY_ADDON_ROOT, "hooks") + ] + + +def get_launch_script_path(): + return os.path.join( + HARMONY_ADDON_ROOT, "api", "launch_script.py" + ) diff --git a/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py b/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py new file mode 100644 index 0000000000..1a36c890a7 --- /dev/null +++ b/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py @@ -0,0 +1,95 @@ +import os +import platform +import subprocess + +from ayon_core.lib import get_ayon_launcher_args +from ayon_core.lib.applications import ( + PreLaunchHook, + LaunchTypes, +) +from ayon_core.hosts.harmony import get_launch_script_path + + +def get_launch_kwargs(kwargs): + """Explicit setting of kwargs for Popen for Harmony. + + Expected behavior + - ayon_console opens window with logs + - ayon has stdout/stderr available for capturing + + Args: + kwargs (Union[dict, None]): Current kwargs or None. + + """ + if kwargs is None: + kwargs = {} + + if platform.system().lower() != "windows": + return kwargs + + executable_path = os.environ.get("AYON_EXECUTABLE") + + executable_filename = "" + if executable_path: + executable_filename = os.path.basename(executable_path) + + is_gui_executable = "ayon_console" not in executable_filename + if is_gui_executable: + kwargs.update({ + "creationflags": subprocess.CREATE_NO_WINDOW, + "stdout": subprocess.DEVNULL, + "stderr": subprocess.DEVNULL + }) + else: + kwargs.update({ + "creationflags": subprocess.CREATE_NEW_CONSOLE + }) + return kwargs + + +class HarmonyPrelaunchHook(PreLaunchHook): + """Launch arguments preparation. + + Hook add python executable and script path to Harmony implementation + before Harmony executable and add last workfile path to launch arguments. + + Existence of last workfile is checked. If workfile does not exists tries + to copy templated workfile from predefined path. + """ + app_groups = {"harmony"} + + order = 20 + launch_types = {LaunchTypes.local} + + def execute(self): + # Pop executable + executable_path = self.launch_context.launch_args.pop(0) + + # Pop rest of launch arguments - There should not be other arguments! + remainders = [] + while self.launch_context.launch_args: + remainders.append(self.launch_context.launch_args.pop(0)) + + script_path = get_launch_script_path() + + new_launch_args = get_ayon_launcher_args( + "run", script_path, executable_path + ) + # Add workfile path if exists + workfile_path = self.data["last_workfile_path"] + if ( + self.data.get("start_last_workfile") + and workfile_path + and os.path.exists(workfile_path) + ): + new_launch_args.append(workfile_path) + + # Append as whole list as these arguments should not be separated + self.launch_context.launch_args.append(new_launch_args) + + if remainders: + self.launch_context.launch_args.extend(remainders) + + self.launch_context.kwargs = get_launch_kwargs( + self.launch_context.kwargs + ) From 4fb898615bff67a20925622e297859b369db6477 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 16:28:59 +0100 Subject: [PATCH 39/60] remove unused global script --- .../scripts/non_python_host_launch.py | 108 ------------------ 1 file changed, 108 deletions(-) delete mode 100644 client/ayon_core/scripts/non_python_host_launch.py diff --git a/client/ayon_core/scripts/non_python_host_launch.py b/client/ayon_core/scripts/non_python_host_launch.py deleted file mode 100644 index 4c18fd0ccc..0000000000 --- a/client/ayon_core/scripts/non_python_host_launch.py +++ /dev/null @@ -1,108 +0,0 @@ -"""Script wraps launch mechanism of non python host implementations. - -Arguments passed to the script are passed to launch function in host -implementation. In all cases requires host app executable and may contain -workfile or others. -""" - -import os -import sys - -# Get current file to locate start point of sys.argv -CURRENT_FILE = os.path.abspath(__file__) - - -def show_error_messagebox(title, message, detail_message=None): - """Function will show message and process ends after closing it.""" - from qtpy import QtWidgets, QtCore - from ayon_core import style - - app = QtWidgets.QApplication([]) - app.setStyleSheet(style.load_stylesheet()) - - msgbox = QtWidgets.QMessageBox() - msgbox.setWindowTitle(title) - msgbox.setText(message) - - if detail_message: - msgbox.setDetailedText(detail_message) - - msgbox.setWindowModality(QtCore.Qt.ApplicationModal) - msgbox.show() - - sys.exit(app.exec_()) - - -def on_invalid_args(script_not_found): - """Show to user message box saying that something went wrong. - - Tell user that arguments to launch implementation are invalid with - arguments details. - - Args: - script_not_found (bool): Use different message based on this value. - """ - - title = "Invalid arguments" - joined_args = ", ".join("\"{}\"".format(arg) for arg in sys.argv) - if script_not_found: - submsg = "Where couldn't find script path:\n\"{}\"" - else: - submsg = "Expected Host executable after script path:\n\"{}\"" - - message = "BUG: Got invalid arguments so can't launch Host application." - detail_message = "Process was launched with arguments:\n{}\n\n{}".format( - joined_args, - submsg.format(CURRENT_FILE) - ) - - show_error_messagebox(title, message, detail_message) - - -def main(argv): - # Modify current file path to find match in sys.argv which may be different - # on windows (different letter cases and slashes). - modified_current_file = CURRENT_FILE.replace("\\", "/").lower() - - # Create a copy of sys argv - sys_args = list(argv) - after_script_idx = None - # Find script path in sys.argv to know index of argv where host - # executable should be. - for idx, item in enumerate(sys_args): - if item.replace("\\", "/").lower() == modified_current_file: - after_script_idx = idx + 1 - break - - # Validate that there is at least one argument after script path - launch_args = None - if after_script_idx is not None: - launch_args = sys_args[after_script_idx:] - - host_name = os.environ["AYON_HOST_NAME"].lower() - if host_name == "photoshop": - # TODO refactor launch logic according to AE - from ayon_core.hosts.photoshop.api.lib import main - elif host_name == "aftereffects": - from ayon_core.hosts.aftereffects.api.launch_logic import main - elif host_name == "harmony": - from ayon_core.hosts.harmony.api.lib import main - else: - title = "Unknown host name" - message = ( - "BUG: Environment variable AYON_HOST_NAME contains unknown" - " host name \"{}\"" - ).format(host_name) - show_error_messagebox(title, message) - return - - if launch_args: - # Launch host implementation - main(*launch_args) - else: - # Show message box - on_invalid_args(after_script_idx is None) - - -if __name__ == "__main__": - main(sys.argv) From 2c07fb45032d28162c32661cd977c36f20058aec Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 16:29:16 +0100 Subject: [PATCH 40/60] removed unused 'get_non_python_host_kwargs' --- client/ayon_core/lib/applications.py | 39 ---------------------------- 1 file changed, 39 deletions(-) diff --git a/client/ayon_core/lib/applications.py b/client/ayon_core/lib/applications.py index 4bf0c31d93..68fc3ea201 100644 --- a/client/ayon_core/lib/applications.py +++ b/client/ayon_core/lib/applications.py @@ -1985,42 +1985,3 @@ def should_workfile_tool_start( if output is None: return default_output return output - - -def get_non_python_host_kwargs(kwargs, allow_console=True): - """Explicit setting of kwargs for Popen for AE/PS/Harmony. - - Expected behavior - - ayon_console opens window with logs - - ayon has stdout/stderr available for capturing - - Args: - kwargs (dict) or None - allow_console (bool): use False for inner Popen opening app itself or - it will open additional console (at least for Harmony) - """ - - if kwargs is None: - kwargs = {} - - if platform.system().lower() != "windows": - return kwargs - - executable_path = os.environ.get("AYON_EXECUTABLE") - - executable_filename = "" - if executable_path: - executable_filename = os.path.basename(executable_path) - - is_gui_executable = "ayon_console" not in executable_filename - if is_gui_executable: - kwargs.update({ - "creationflags": subprocess.CREATE_NO_WINDOW, - "stdout": subprocess.DEVNULL, - "stderr": subprocess.DEVNULL - }) - elif allow_console: - kwargs.update({ - "creationflags": subprocess.CREATE_NEW_CONSOLE - }) - return kwargs From ca39fc429130942c85883d471dd5604efad235dd Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 16:31:11 +0100 Subject: [PATCH 41/60] don't use 'get_non_python_host_kwargs' when launching harmony --- client/ayon_core/hosts/harmony/api/lib.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/harmony/api/lib.py b/client/ayon_core/hosts/harmony/api/lib.py index bc73e19066..34cb14636d 100644 --- a/client/ayon_core/hosts/harmony/api/lib.py +++ b/client/ayon_core/hosts/harmony/api/lib.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- """Utility functions used for Avalon - Harmony integration.""" +import platform import subprocess import threading import os @@ -22,7 +23,6 @@ from .server import Server from ayon_core.tools.stdout_broker.app import StdOutBroker from ayon_core.tools.utils import host_tools from ayon_core import style -from ayon_core.lib.applications import get_non_python_host_kwargs # Setup logging. log = logging.getLogger(__name__) @@ -324,7 +324,18 @@ def launch_zip_file(filepath): return print("Launching {}".format(scene_path)) - kwargs = get_non_python_host_kwargs({}, False) + kwargs = {} + if platform.system().lower() == "windows": + executable_filename = os.path.basename( + os.getenv("AYON_EXECUTABLE", "") + ) + if "ayon_console" not in executable_filename: + kwargs.update({ + "creationflags": subprocess.CREATE_NO_WINDOW, + "stdout": subprocess.DEVNULL, + "stderr": subprocess.DEVNULL + }) + process = subprocess.Popen( [ProcessContext.application_path, scene_path], **kwargs From 508d4b559e7ed8db2da14c3e1959b403efb33b43 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 16:32:17 +0100 Subject: [PATCH 42/60] added comment with question --- client/ayon_core/hosts/harmony/api/lib.py | 1 + 1 file changed, 1 insertion(+) diff --git a/client/ayon_core/hosts/harmony/api/lib.py b/client/ayon_core/hosts/harmony/api/lib.py index 34cb14636d..b78fe468b5 100644 --- a/client/ayon_core/hosts/harmony/api/lib.py +++ b/client/ayon_core/hosts/harmony/api/lib.py @@ -324,6 +324,7 @@ def launch_zip_file(filepath): return print("Launching {}".format(scene_path)) + # QUESTION Could we use 'run_detached_process' from 'ayon_core.lib'? kwargs = {} if platform.system().lower() == "windows": executable_filename = os.path.basename( From 562730fa65384e89fe1c72cd981c0e997200641a Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 16:33:02 +0100 Subject: [PATCH 43/60] added helper function to determine if ui executable is used --- .../aftereffects/hooks/pre_launch_args.py | 14 +++----- client/ayon_core/hosts/harmony/api/lib.py | 25 +++++++------- .../hosts/harmony/hooks/pre_launch_args.py | 14 +++----- .../hosts/photoshop/hooks/pre_launch_args.py | 14 +++----- client/ayon_core/lib/__init__.py | 2 ++ client/ayon_core/lib/ayon_info.py | 34 ++++++++++++++++++- 6 files changed, 63 insertions(+), 40 deletions(-) diff --git a/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py b/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py index 2c5baa3b68..76ccd2bd4f 100644 --- a/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py +++ b/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py @@ -2,7 +2,10 @@ import os import platform import subprocess -from ayon_core.lib import get_ayon_launcher_args +from ayon_core.lib import ( + get_ayon_launcher_args, + is_using_ui_executable, +) from ayon_core.lib.applications import ( PreLaunchHook, LaunchTypes, @@ -27,14 +30,7 @@ def get_launch_kwargs(kwargs): if platform.system().lower() != "windows": return kwargs - executable_path = os.environ.get("AYON_EXECUTABLE") - - executable_filename = "" - if executable_path: - executable_filename = os.path.basename(executable_path) - - is_in_ui_launcher = "ayon_console" not in executable_filename - if is_in_ui_launcher: + if is_using_ui_executable(): kwargs.update({ "creationflags": subprocess.CREATE_NO_WINDOW, "stdout": subprocess.DEVNULL, diff --git a/client/ayon_core/hosts/harmony/api/lib.py b/client/ayon_core/hosts/harmony/api/lib.py index b78fe468b5..828ee3863e 100644 --- a/client/ayon_core/hosts/harmony/api/lib.py +++ b/client/ayon_core/hosts/harmony/api/lib.py @@ -15,15 +15,17 @@ import json import signal import time from uuid import uuid4 -from qtpy import QtWidgets, QtCore, QtGui import collections -from .server import Server +from qtpy import QtWidgets, QtCore, QtGui +from ayon_core.lib import is_using_ui_executable from ayon_core.tools.stdout_broker.app import StdOutBroker from ayon_core.tools.utils import host_tools from ayon_core import style +from .server import Server + # Setup logging. log = logging.getLogger(__name__) log.setLevel(logging.DEBUG) @@ -326,16 +328,15 @@ def launch_zip_file(filepath): print("Launching {}".format(scene_path)) # QUESTION Could we use 'run_detached_process' from 'ayon_core.lib'? kwargs = {} - if platform.system().lower() == "windows": - executable_filename = os.path.basename( - os.getenv("AYON_EXECUTABLE", "") - ) - if "ayon_console" not in executable_filename: - kwargs.update({ - "creationflags": subprocess.CREATE_NO_WINDOW, - "stdout": subprocess.DEVNULL, - "stderr": subprocess.DEVNULL - }) + if ( + platform.system().lower() == "windows" + and is_using_ui_executable() + ): + kwargs.update({ + "creationflags": subprocess.CREATE_NO_WINDOW, + "stdout": subprocess.DEVNULL, + "stderr": subprocess.DEVNULL + }) process = subprocess.Popen( [ProcessContext.application_path, scene_path], diff --git a/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py b/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py index 1a36c890a7..c2c667c1d8 100644 --- a/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py +++ b/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py @@ -2,7 +2,10 @@ import os import platform import subprocess -from ayon_core.lib import get_ayon_launcher_args +from ayon_core.lib import ( + get_ayon_launcher_args, + is_using_ui_executable, +) from ayon_core.lib.applications import ( PreLaunchHook, LaunchTypes, @@ -27,14 +30,7 @@ def get_launch_kwargs(kwargs): if platform.system().lower() != "windows": return kwargs - executable_path = os.environ.get("AYON_EXECUTABLE") - - executable_filename = "" - if executable_path: - executable_filename = os.path.basename(executable_path) - - is_gui_executable = "ayon_console" not in executable_filename - if is_gui_executable: + if is_using_ui_executable(): kwargs.update({ "creationflags": subprocess.CREATE_NO_WINDOW, "stdout": subprocess.DEVNULL, diff --git a/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py b/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py index 0689a6c2f0..228413e1ea 100644 --- a/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py +++ b/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py @@ -2,7 +2,10 @@ import os import platform import subprocess -from ayon_core.lib import get_ayon_launcher_args +from ayon_core.lib import ( + get_ayon_launcher_args, + is_using_ui_executable, +) from ayon_core.lib.applications import ( PreLaunchHook, LaunchTypes, @@ -27,14 +30,7 @@ def get_launch_kwargs(kwargs): if platform.system().lower() != "windows": return kwargs - executable_path = os.environ.get("AYON_EXECUTABLE") - - executable_filename = "" - if executable_path: - executable_filename = os.path.basename(executable_path) - - is_gui_executable = "ayon_console" not in executable_filename - if is_gui_executable: + if is_using_ui_executable(): kwargs.update({ "creationflags": subprocess.CREATE_NO_WINDOW, "stdout": subprocess.DEVNULL, diff --git a/client/ayon_core/lib/__init__.py b/client/ayon_core/lib/__init__.py index f69fd10b07..d82fb0de0e 100644 --- a/client/ayon_core/lib/__init__.py +++ b/client/ayon_core/lib/__init__.py @@ -155,6 +155,7 @@ from .path_tools import ( from .ayon_info import ( is_running_from_build, + is_using_ui_executable, is_staging_enabled, is_dev_mode_enabled, is_in_tests, @@ -275,6 +276,7 @@ __all__ = [ "Logger", "is_running_from_build", + "is_using_ui_executable", "is_staging_enabled", "is_dev_mode_enabled", "is_in_tests", diff --git a/client/ayon_core/lib/ayon_info.py b/client/ayon_core/lib/ayon_info.py index ec37d735d8..3d4c38c99a 100644 --- a/client/ayon_core/lib/ayon_info.py +++ b/client/ayon_core/lib/ayon_info.py @@ -10,6 +10,12 @@ from .local_settings import get_local_site_id def get_ayon_launcher_version(): + """Get AYON launcher version. + + Returns: + str: Version string. + + """ version_filepath = os.path.join(os.environ["AYON_ROOT"], "version.py") if not os.path.exists(version_filepath): return None @@ -24,8 +30,8 @@ def is_running_from_build(): Returns: bool: True if running from build. - """ + """ executable_path = os.environ["AYON_EXECUTABLE"] executable_filename = os.path.basename(executable_path) if "python" in executable_filename.lower(): @@ -33,6 +39,32 @@ def is_running_from_build(): return True +def is_using_ui_executable(): + """AYON launcher UI windows executable is used. + + This function make sense only on Windows platform. For other platforms + always returns False. False is also returned if process is running from + code. + + AYON launcher on windows has 2 executable files. First 'ayon_console.exe' + works as 'python.exe' executable, the second 'ayon.exe' works as + 'pythonw.exe' executable. The difference is way how stdout/stderr is + handled (especially when calling subprocess). + + Returns: + bool: True if UI executable is used. + + """ + if ( + platform.system().lower() != "windows" + or is_running_from_build() + ): + return False + executable_path = os.environ["AYON_EXECUTABLE"] + executable_filename = os.path.basename(executable_path) + return "ayon_console" not in executable_filename + + def is_staging_enabled(): return os.getenv("AYON_USE_STAGING") == "1" From 5cb07274d1fea5818c0e431c99aa0b3c36a7918c Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 16:45:27 +0100 Subject: [PATCH 44/60] renamed 'is_using_ui_executable' to 'is_using_ayon_console' --- client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py | 4 ++-- client/ayon_core/hosts/harmony/api/lib.py | 4 ++-- client/ayon_core/hosts/harmony/hooks/pre_launch_args.py | 4 ++-- client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py | 4 ++-- client/ayon_core/lib/__init__.py | 4 ++-- client/ayon_core/lib/ayon_info.py | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py b/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py index 76ccd2bd4f..959df0eb39 100644 --- a/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py +++ b/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py @@ -4,7 +4,7 @@ import subprocess from ayon_core.lib import ( get_ayon_launcher_args, - is_using_ui_executable, + is_using_ayon_console, ) from ayon_core.lib.applications import ( PreLaunchHook, @@ -30,7 +30,7 @@ def get_launch_kwargs(kwargs): if platform.system().lower() != "windows": return kwargs - if is_using_ui_executable(): + if is_using_ayon_console(): kwargs.update({ "creationflags": subprocess.CREATE_NO_WINDOW, "stdout": subprocess.DEVNULL, diff --git a/client/ayon_core/hosts/harmony/api/lib.py b/client/ayon_core/hosts/harmony/api/lib.py index 828ee3863e..d9c17c6214 100644 --- a/client/ayon_core/hosts/harmony/api/lib.py +++ b/client/ayon_core/hosts/harmony/api/lib.py @@ -19,7 +19,7 @@ import collections from qtpy import QtWidgets, QtCore, QtGui -from ayon_core.lib import is_using_ui_executable +from ayon_core.lib import is_using_ayon_console from ayon_core.tools.stdout_broker.app import StdOutBroker from ayon_core.tools.utils import host_tools from ayon_core import style @@ -330,7 +330,7 @@ def launch_zip_file(filepath): kwargs = {} if ( platform.system().lower() == "windows" - and is_using_ui_executable() + and is_using_ayon_console() ): kwargs.update({ "creationflags": subprocess.CREATE_NO_WINDOW, diff --git a/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py b/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py index c2c667c1d8..66bc0a80d8 100644 --- a/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py +++ b/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py @@ -4,7 +4,7 @@ import subprocess from ayon_core.lib import ( get_ayon_launcher_args, - is_using_ui_executable, + is_using_ayon_console, ) from ayon_core.lib.applications import ( PreLaunchHook, @@ -30,7 +30,7 @@ def get_launch_kwargs(kwargs): if platform.system().lower() != "windows": return kwargs - if is_using_ui_executable(): + if is_using_ayon_console(): kwargs.update({ "creationflags": subprocess.CREATE_NO_WINDOW, "stdout": subprocess.DEVNULL, diff --git a/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py b/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py index 228413e1ea..7fe6e7437f 100644 --- a/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py +++ b/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py @@ -4,7 +4,7 @@ import subprocess from ayon_core.lib import ( get_ayon_launcher_args, - is_using_ui_executable, + is_using_ayon_console, ) from ayon_core.lib.applications import ( PreLaunchHook, @@ -30,7 +30,7 @@ def get_launch_kwargs(kwargs): if platform.system().lower() != "windows": return kwargs - if is_using_ui_executable(): + if is_using_ayon_console(): kwargs.update({ "creationflags": subprocess.CREATE_NO_WINDOW, "stdout": subprocess.DEVNULL, diff --git a/client/ayon_core/lib/__init__.py b/client/ayon_core/lib/__init__.py index d82fb0de0e..10e290360d 100644 --- a/client/ayon_core/lib/__init__.py +++ b/client/ayon_core/lib/__init__.py @@ -155,7 +155,7 @@ from .path_tools import ( from .ayon_info import ( is_running_from_build, - is_using_ui_executable, + is_using_ayon_console, is_staging_enabled, is_dev_mode_enabled, is_in_tests, @@ -276,7 +276,7 @@ __all__ = [ "Logger", "is_running_from_build", - "is_using_ui_executable", + "is_using_ayon_console", "is_staging_enabled", "is_dev_mode_enabled", "is_in_tests", diff --git a/client/ayon_core/lib/ayon_info.py b/client/ayon_core/lib/ayon_info.py index 3d4c38c99a..c3bda70834 100644 --- a/client/ayon_core/lib/ayon_info.py +++ b/client/ayon_core/lib/ayon_info.py @@ -39,7 +39,7 @@ def is_running_from_build(): return True -def is_using_ui_executable(): +def is_using_ayon_console(): """AYON launcher UI windows executable is used. This function make sense only on Windows platform. For other platforms From e15460d851dd56869cbcdbec52dde1d72aef25bb Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 16:51:03 +0100 Subject: [PATCH 45/60] fix the reversed logic --- .../hosts/aftereffects/hooks/pre_launch_args.py | 8 ++++---- client/ayon_core/hosts/harmony/api/lib.py | 2 +- .../ayon_core/hosts/harmony/hooks/pre_launch_args.py | 8 ++++---- .../ayon_core/hosts/photoshop/hooks/pre_launch_args.py | 10 +++++----- client/ayon_core/lib/ayon_info.py | 10 +++++----- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py b/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py index 959df0eb39..979d9ff3e5 100644 --- a/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py +++ b/client/ayon_core/hosts/aftereffects/hooks/pre_launch_args.py @@ -32,13 +32,13 @@ def get_launch_kwargs(kwargs): if is_using_ayon_console(): kwargs.update({ - "creationflags": subprocess.CREATE_NO_WINDOW, - "stdout": subprocess.DEVNULL, - "stderr": subprocess.DEVNULL + "creationflags": subprocess.CREATE_NEW_CONSOLE }) else: kwargs.update({ - "creationflags": subprocess.CREATE_NEW_CONSOLE + "creationflags": subprocess.CREATE_NO_WINDOW, + "stdout": subprocess.DEVNULL, + "stderr": subprocess.DEVNULL }) return kwargs diff --git a/client/ayon_core/hosts/harmony/api/lib.py b/client/ayon_core/hosts/harmony/api/lib.py index d9c17c6214..3c833c7b69 100644 --- a/client/ayon_core/hosts/harmony/api/lib.py +++ b/client/ayon_core/hosts/harmony/api/lib.py @@ -330,7 +330,7 @@ def launch_zip_file(filepath): kwargs = {} if ( platform.system().lower() == "windows" - and is_using_ayon_console() + and not is_using_ayon_console() ): kwargs.update({ "creationflags": subprocess.CREATE_NO_WINDOW, diff --git a/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py b/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py index 66bc0a80d8..bbad14084a 100644 --- a/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py +++ b/client/ayon_core/hosts/harmony/hooks/pre_launch_args.py @@ -32,13 +32,13 @@ def get_launch_kwargs(kwargs): if is_using_ayon_console(): kwargs.update({ - "creationflags": subprocess.CREATE_NO_WINDOW, - "stdout": subprocess.DEVNULL, - "stderr": subprocess.DEVNULL + "creationflags": subprocess.CREATE_NEW_CONSOLE }) else: kwargs.update({ - "creationflags": subprocess.CREATE_NEW_CONSOLE + "creationflags": subprocess.CREATE_NO_WINDOW, + "stdout": subprocess.DEVNULL, + "stderr": subprocess.DEVNULL }) return kwargs diff --git a/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py b/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py index 7fe6e7437f..8358c11ca1 100644 --- a/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py +++ b/client/ayon_core/hosts/photoshop/hooks/pre_launch_args.py @@ -30,16 +30,16 @@ def get_launch_kwargs(kwargs): if platform.system().lower() != "windows": return kwargs - if is_using_ayon_console(): + if not is_using_ayon_console(): + kwargs.update({ + "creationflags": subprocess.CREATE_NEW_CONSOLE + }) + else: kwargs.update({ "creationflags": subprocess.CREATE_NO_WINDOW, "stdout": subprocess.DEVNULL, "stderr": subprocess.DEVNULL }) - else: - kwargs.update({ - "creationflags": subprocess.CREATE_NEW_CONSOLE - }) return kwargs diff --git a/client/ayon_core/lib/ayon_info.py b/client/ayon_core/lib/ayon_info.py index c3bda70834..adb3c1befc 100644 --- a/client/ayon_core/lib/ayon_info.py +++ b/client/ayon_core/lib/ayon_info.py @@ -40,10 +40,10 @@ def is_running_from_build(): def is_using_ayon_console(): - """AYON launcher UI windows executable is used. + """AYON launcher console executable is used. This function make sense only on Windows platform. For other platforms - always returns False. False is also returned if process is running from + always returns True. True is also returned if process is running from code. AYON launcher on windows has 2 executable files. First 'ayon_console.exe' @@ -52,17 +52,17 @@ def is_using_ayon_console(): handled (especially when calling subprocess). Returns: - bool: True if UI executable is used. + bool: True if console executable is used. """ if ( platform.system().lower() != "windows" or is_running_from_build() ): - return False + return True executable_path = os.environ["AYON_EXECUTABLE"] executable_filename = os.path.basename(executable_path) - return "ayon_console" not in executable_filename + return "ayon_console" in executable_filename def is_staging_enabled(): From 553407a4bd828d043bf7e3fe2f43689a40616c42 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 25 Mar 2024 18:45:48 +0100 Subject: [PATCH 46/60] move workfile utils functions to workfile pipeline code --- client/ayon_core/lib/applications.py | 108 +--------------- .../ayon_core/pipeline/workfile/__init__.py | 8 ++ client/ayon_core/pipeline/workfile/utils.py | 121 ++++++++++++++++++ .../tools/launcher/models/actions.py | 5 +- 4 files changed, 137 insertions(+), 105 deletions(-) create mode 100644 client/ayon_core/pipeline/workfile/utils.py diff --git a/client/ayon_core/lib/applications.py b/client/ayon_core/lib/applications.py index 444a4cf67e..3a6039357c 100644 --- a/client/ayon_core/lib/applications.py +++ b/client/ayon_core/lib/applications.py @@ -1789,6 +1789,10 @@ def _prepare_last_workfile(data, workdir, addons_manager): from ayon_core.addon import AddonsManager from ayon_core.pipeline import HOST_WORKFILE_EXTENSIONS + from ayon_core.pipeline.workfile import ( + should_use_last_workfile_on_launch, + should_open_workfiles_tool_on_launch, + ) if not addons_manager: addons_manager = AddonsManager() @@ -1811,7 +1815,7 @@ def _prepare_last_workfile(data, workdir, addons_manager): start_last_workfile = data.get("start_last_workfile") if start_last_workfile is None: - start_last_workfile = should_start_last_workfile( + start_last_workfile = should_use_last_workfile_on_launch( project_name, app.host_name, task_name, task_type ) else: @@ -1819,7 +1823,7 @@ def _prepare_last_workfile(data, workdir, addons_manager): data["start_last_workfile"] = start_last_workfile - workfile_startup = should_workfile_tool_start( + workfile_startup = should_open_workfiles_tool_on_launch( project_name, app.host_name, task_name, task_type ) data["workfile_startup"] = workfile_startup @@ -1889,106 +1893,6 @@ def _prepare_last_workfile(data, workdir, addons_manager): data["last_workfile_path"] = last_workfile_path -def should_start_last_workfile( - project_name, host_name, task_name, task_type, default_output=False -): - """Define if host should start last version workfile if possible. - - Default output is `False`. Can be overridden with environment variable - `AYON_OPEN_LAST_WORKFILE`, valid values without case sensitivity are - `"0", "1", "true", "false", "yes", "no"`. - - Args: - project_name (str): Project name. - host_name (str): Host name. - task_name (str): Task name. - task_type (str): Task type. - default_output (Optional[bool]): Default output if no profile is - found. - - Returns: - bool: True if host should start workfile. - - """ - - project_settings = get_project_settings(project_name) - profiles = ( - project_settings - ["core"] - ["tools"] - ["Workfiles"] - ["last_workfile_on_startup"] - ) - - if not profiles: - return default_output - - filter_data = { - "tasks": task_name, - "task_types": task_type, - "hosts": host_name - } - matching_item = filter_profiles(profiles, filter_data) - - output = None - if matching_item: - output = matching_item.get("enabled") - - if output is None: - return default_output - return output - - -def should_workfile_tool_start( - project_name, host_name, task_name, task_type, default_output=False -): - """Define if host should start workfile tool at host launch. - - Default output is `False`. Can be overridden with environment variable - `AYON_WORKFILE_TOOL_ON_START`, valid values without case sensitivity are - `"0", "1", "true", "false", "yes", "no"`. - - Args: - project_name (str): Project name. - host_name (str): Host name. - task_name (str): Task name. - task_type (str): Task type. - default_output (Optional[bool]): Default output if no profile is - found. - - Returns: - bool: True if host should start workfile. - - """ - - project_settings = get_project_settings(project_name) - profiles = ( - project_settings - ["core"] - ["tools"] - ["Workfiles"] - ["open_workfile_tool_on_startup"] - ) - - if not profiles: - return default_output - - filter_data = { - "tasks": task_name, - "task_types": task_type, - "hosts": host_name - } - matching_item = filter_profiles(profiles, filter_data) - - output = None - if matching_item: - output = matching_item.get("enabled") - - if output is None: - return default_output - return output - - def get_non_python_host_kwargs(kwargs, allow_console=True): """Explicit setting of kwargs for Popen for AE/PS/Harmony. diff --git a/client/ayon_core/pipeline/workfile/__init__.py b/client/ayon_core/pipeline/workfile/__init__.py index 94ecc81bd6..36766e3a04 100644 --- a/client/ayon_core/pipeline/workfile/__init__.py +++ b/client/ayon_core/pipeline/workfile/__init__.py @@ -13,6 +13,11 @@ from .path_resolving import ( create_workdir_extra_folders, ) +from .utils import ( + should_use_last_workfile_on_launch, + should_open_workfiles_tool_on_launch, +) + from .build_workfile import BuildWorkfile @@ -30,5 +35,8 @@ __all__ = ( "create_workdir_extra_folders", + "should_use_last_workfile_on_launch", + "should_open_workfiles_tool_on_launch", + "BuildWorkfile", ) diff --git a/client/ayon_core/pipeline/workfile/utils.py b/client/ayon_core/pipeline/workfile/utils.py new file mode 100644 index 0000000000..53de3269b2 --- /dev/null +++ b/client/ayon_core/pipeline/workfile/utils.py @@ -0,0 +1,121 @@ +from ayon_core.lib import filter_profiles +from ayon_core.settings import get_project_settings + + +def should_use_last_workfile_on_launch( + project_name, + host_name, + task_name, + task_type, + default_output=False, + project_settings=None, +): + """Define if host should start last version workfile if possible. + + Default output is `False`. Can be overridden with environment variable + `AYON_OPEN_LAST_WORKFILE`, valid values without case sensitivity are + `"0", "1", "true", "false", "yes", "no"`. + + Args: + project_name (str): Name of project. + host_name (str): Name of host which is launched. In avalon's + application context it's value stored in app definition under + key `"application_dir"`. Is not case sensitive. + task_name (str): Name of task which is used for launching the host. + Task name is not case sensitive. + task_type (str): Task type. + default_output (Optional[bool]): Default output value if no profile + is found. + project_settings (Optional[dict[str, Any]]): Project settings. + + Returns: + bool: True if host should start workfile. + + """ + if project_settings is None: + project_settings = get_project_settings(project_name) + profiles = ( + project_settings + ["core"] + ["tools"] + ["Workfiles"] + ["last_workfile_on_startup"] + ) + + if not profiles: + return default_output + + filter_data = { + "tasks": task_name, + "task_types": task_type, + "hosts": host_name + } + matching_item = filter_profiles(profiles, filter_data) + + output = None + if matching_item: + output = matching_item.get("enabled") + + if output is None: + return default_output + return output + + +def should_open_workfiles_tool_on_launch( + project_name, + host_name, + task_name, + task_type, + default_output=False, + project_settings=None, +): + """Define if host should start workfile tool at host launch. + + Default output is `False`. Can be overridden with environment variable + `AYON_WORKFILE_TOOL_ON_START`, valid values without case sensitivity are + `"0", "1", "true", "false", "yes", "no"`. + + Args: + project_name (str): Name of project. + host_name (str): Name of host which is launched. In avalon's + application context it's value stored in app definition under + key `"application_dir"`. Is not case sensitive. + task_name (str): Name of task which is used for launching the host. + Task name is not case sensitive. + task_type (str): Task type. + default_output (Optional[bool]): Default output value if no profile + is found. + project_settings (Optional[dict[str, Any]]): Project settings. + + Returns: + bool: True if host should start workfile. + + """ + + if project_settings is None: + project_settings = get_project_settings(project_name) + profiles = ( + project_settings + ["core"] + ["tools"] + ["Workfiles"] + ["open_workfile_tool_on_startup"] + ) + + if not profiles: + return default_output + + filter_data = { + "tasks": task_name, + "task_types": task_type, + "hosts": host_name + } + matching_item = filter_profiles(profiles, filter_data) + + output = None + if matching_item: + output = matching_item.get("enabled") + + if output is None: + return default_output + return output diff --git a/client/ayon_core/tools/launcher/models/actions.py b/client/ayon_core/tools/launcher/models/actions.py index 50c3e85b0a..97943e6ad7 100644 --- a/client/ayon_core/tools/launcher/models/actions.py +++ b/client/ayon_core/tools/launcher/models/actions.py @@ -6,6 +6,7 @@ from ayon_core.pipeline.actions import ( discover_launcher_actions, LauncherAction, ) +from ayon_core.pipeline.workfile import should_use_last_workfile_on_launch # class Action: @@ -301,8 +302,6 @@ class ActionsModel: host_name, not_open_workfile_actions ): - from ayon_core.lib.applications import should_start_last_workfile - if identifier in not_open_workfile_actions: return not not_open_workfile_actions[identifier] @@ -315,7 +314,7 @@ class ActionsModel: task_name = task_entity["name"] task_type = task_entity["taskType"] - output = should_start_last_workfile( + output = should_use_last_workfile_on_launch( project_name, host_name, task_name, From 93c22be6bf6e987babd450935374c18cb568b0d6 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 20:06:19 +0100 Subject: [PATCH 47/60] Fix syntax error --- .../hosts/maya/plugins/publish/validate_look_shading_group.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_look_shading_group.py b/client/ayon_core/hosts/maya/plugins/publish/validate_look_shading_group.py index 7d249a6021..e70a805de4 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_look_shading_group.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_look_shading_group.py @@ -16,7 +16,7 @@ class ValidateShadingEngine(pyblish.api.InstancePlugin, Shading engines should be named "{surface_shader}SG" """ -`` + order = ValidateContentsOrder families = ["look"] hosts = ["maya"] From 4f60f2b21e2c3cbafe156bfadb97fcb18fb78885 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 20:22:07 +0100 Subject: [PATCH 48/60] Add a way to globally disable the `cbId` workflow in Maya --- .../validate_animation_out_set_related_node_ids.py | 7 +++++++ .../publish/validate_arnold_scene_source_cbid.py | 7 +++++++ .../publish/validate_look_id_reference_edits.py | 7 +++++++ .../hosts/maya/plugins/publish/validate_node_ids.py | 7 +++++++ .../publish/validate_node_ids_deformed_shapes.py | 7 +++++++ .../plugins/publish/validate_node_ids_in_database.py | 7 +++++++ .../maya/plugins/publish/validate_node_ids_related.py | 7 +++++++ .../maya/plugins/publish/validate_node_ids_unique.py | 7 +++++++ .../plugins/publish/validate_rig_out_set_node_ids.py | 7 +++++++ .../maya/plugins/publish/validate_rig_output_ids.py | 7 +++++++ server_addon/maya/server/settings/main.py | 10 ++++++++++ 11 files changed, 80 insertions(+) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py b/client/ayon_core/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py index b96c5f07e2..b6876199e5 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py @@ -32,6 +32,13 @@ class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin, ] optional = False + @classmethod + def apply_settings(cls, project_settings): + # Disable plug-in if cbId workflow is disabled + if not project_settings["maya"].get("use_cbid_workflow", True): + cls.enabled = False + return + def process(self, instance): """Process all meshes""" if not self.is_active(instance.data): diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py b/client/ayon_core/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py index 8bcd272d01..a9d896952d 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_arnold_scene_source_cbid.py @@ -22,6 +22,13 @@ class ValidateArnoldSceneSourceCbid(pyblish.api.InstancePlugin, actions = [RepairAction] optional = False + @classmethod + def apply_settings(cls, project_settings): + # Disable plug-in if cbId workflow is disabled + if not project_settings["maya"].get("use_cbid_workflow", True): + cls.enabled = False + return + @staticmethod def _get_nodes_by_name(nodes): nodes_by_name = {} diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_look_id_reference_edits.py b/client/ayon_core/hosts/maya/plugins/publish/validate_look_id_reference_edits.py index 1d313bdae4..7ae3b4b9b5 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_look_id_reference_edits.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_look_id_reference_edits.py @@ -27,6 +27,13 @@ class ValidateLookIdReferenceEdits(pyblish.api.InstancePlugin): actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction, RepairAction] + @classmethod + def apply_settings(cls, project_settings): + # Disable plug-in if cbId workflow is disabled + if not project_settings["maya"].get("use_cbid_workflow", True): + cls.enabled = False + return + def process(self, instance): invalid = self.get_invalid(instance) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids.py b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids.py index f40db988c6..ba748a4fc4 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids.py @@ -31,6 +31,13 @@ class ValidateNodeIDs(pyblish.api.InstancePlugin): actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction, ayon_core.hosts.maya.api.action.GenerateUUIDsOnInvalidAction] + @classmethod + def apply_settings(cls, project_settings): + # Disable plug-in if cbId workflow is disabled + if not project_settings["maya"].get("use_cbid_workflow", True): + cls.enabled = False + return + def process(self, instance): """Process all meshes""" diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_deformed_shapes.py b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_deformed_shapes.py index 912311cc8d..545ab8e28c 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_deformed_shapes.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_deformed_shapes.py @@ -26,6 +26,13 @@ class ValidateNodeIdsDeformedShape(pyblish.api.InstancePlugin): RepairAction ] + @classmethod + def apply_settings(cls, project_settings): + # Disable plug-in if cbId workflow is disabled + if not project_settings["maya"].get("use_cbid_workflow", True): + cls.enabled = False + return + def process(self, instance): """Process all the nodes in the instance""" diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_in_database.py b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_in_database.py index 65a779f3f0..5ca9690fd7 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_in_database.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_in_database.py @@ -26,6 +26,13 @@ class ValidateNodeIdsInDatabase(pyblish.api.InstancePlugin): actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction, ayon_core.hosts.maya.api.action.GenerateUUIDsOnInvalidAction] + @classmethod + def apply_settings(cls, project_settings): + # Disable plug-in if cbId workflow is disabled + if not project_settings["maya"].get("use_cbid_workflow", True): + cls.enabled = False + return + def process(self, instance): invalid = self.get_invalid(instance) if invalid: diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py index 606abee3d2..992988dc7d 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_related.py @@ -24,6 +24,13 @@ class ValidateNodeIDsRelated(pyblish.api.InstancePlugin, actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction, ayon_core.hosts.maya.api.action.GenerateUUIDsOnInvalidAction] + @classmethod + def apply_settings(cls, project_settings): + # Disable plug-in if cbId workflow is disabled + if not project_settings["maya"].get("use_cbid_workflow", True): + cls.enabled = False + return + def process(self, instance): """Process all nodes in instance (including hierarchy)""" if not self.is_active(instance.data): diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_unique.py b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_unique.py index 6c5cd26259..f4994922ce 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_unique.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_node_ids_unique.py @@ -26,6 +26,13 @@ class ValidateNodeIdsUnique(pyblish.api.InstancePlugin): actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction, ayon_core.hosts.maya.api.action.GenerateUUIDsOnInvalidAction] + @classmethod + def apply_settings(cls, project_settings): + # Disable plug-in if cbId workflow is disabled + if not project_settings["maya"].get("use_cbid_workflow", True): + cls.enabled = False + return + def process(self, instance): """Process all meshes""" diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py b/client/ayon_core/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py index ab8cc25210..e42cd50977 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py @@ -34,6 +34,13 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin, allow_history_only = False optional = False + @classmethod + def apply_settings(cls, project_settings): + # Disable plug-in if cbId workflow is disabled + if not project_settings["maya"].get("use_cbid_workflow", True): + cls.enabled = False + return + def process(self, instance): """Process all meshes""" if not self.is_active(instance.data): diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_rig_output_ids.py b/client/ayon_core/hosts/maya/plugins/publish/validate_rig_output_ids.py index 93552ccce0..d04006f013 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_rig_output_ids.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_rig_output_ids.py @@ -32,6 +32,13 @@ class ValidateRigOutputIds(pyblish.api.InstancePlugin): actions = [RepairAction, ayon_core.hosts.maya.api.action.SelectInvalidAction] + @classmethod + def apply_settings(cls, project_settings): + # Disable plug-in if cbId workflow is disabled + if not project_settings["maya"].get("use_cbid_workflow", True): + cls.enabled = False + return + def process(self, instance): invalid = self.get_invalid(instance, compute=True) if invalid: diff --git a/server_addon/maya/server/settings/main.py b/server_addon/maya/server/settings/main.py index f7f62e219d..a4562f54d7 100644 --- a/server_addon/maya/server/settings/main.py +++ b/server_addon/maya/server/settings/main.py @@ -30,6 +30,15 @@ class ExtMappingItemModel(BaseSettingsModel): class MayaSettings(BaseSettingsModel): """Maya Project Settings.""" + use_cbid_workflow: bool = SettingsField( + True, title="Use cbId workflow", + description=( + "When enabled, a per node `cbId` identifier will be created and " + "validated for many product types. This is then used for look " + "publishing and many others. By disabling this, the `cbId` " + "attribute will still be created on scene save but it will not " + "be validated.")) + open_workfile_post_initialization: bool = SettingsField( True, title="Open Workfile Post Initialization") explicit_plugins_loading: ExplicitPluginsLoadingModel = SettingsField( @@ -88,6 +97,7 @@ DEFAULT_MEL_WORKSPACE_SETTINGS = "\n".join(( )) DEFAULT_MAYA_SETTING = { + "use_cbid_workflow": True, "open_workfile_post_initialization": True, "explicit_plugins_loading": DEFAULT_EXPLITCIT_PLUGINS_LOADING_SETTINGS, "imageio": DEFAULT_IMAGEIO_SETTINGS, From 8af23931ae46d6e2dc6b3243de62093b39590f8f Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 20:22:41 +0100 Subject: [PATCH 49/60] Bump maya server addon version --- server_addon/maya/server/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/maya/server/version.py b/server_addon/maya/server/version.py index a86a3ce0a1..0b44700d27 100644 --- a/server_addon/maya/server/version.py +++ b/server_addon/maya/server/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring addon version.""" -__version__ = "0.1.10" +__version__ = "0.1.11" From b19f640d538abdd7c9572703e792b45996c4f9d8 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 20:29:03 +0100 Subject: [PATCH 50/60] Preserve automatic settings applying when relevant --- .../validate_animation_out_set_related_node_ids.py | 11 ++++++++++- .../plugins/publish/validate_rig_out_set_node_ids.py | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py b/client/ayon_core/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py index b6876199e5..ac18dc7a57 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py @@ -7,7 +7,9 @@ from ayon_core.pipeline.publish import ( RepairAction, ValidateContentsOrder, PublishValidationError, - OptionalPyblishPluginMixin + OptionalPyblishPluginMixin, + get_plugin_settings, + apply_plugin_settings_automatically ) @@ -39,6 +41,13 @@ class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin, cls.enabled = False return + # Preserve automatic settings applying logic + settings = get_plugin_settings(plugin=cls, + project_settings=project_settings, + log=cls.log, + category="maya") + apply_plugin_settings_automatically(cls, settings, logger=cls.log) + def process(self, instance): """Process all meshes""" if not self.is_active(instance.data): diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py b/client/ayon_core/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py index e42cd50977..c7afd41a91 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py @@ -8,7 +8,9 @@ from ayon_core.pipeline.publish import ( RepairAction, ValidateContentsOrder, PublishValidationError, - OptionalPyblishPluginMixin + OptionalPyblishPluginMixin, + get_plugin_settings, + apply_plugin_settings_automatically ) @@ -41,6 +43,13 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin, cls.enabled = False return + # Preserve automatic settings applying logic + settings = get_plugin_settings(plugin=cls, + project_settings=project_settings, + log=cls.log, + category="maya") + apply_plugin_settings_automatically(cls, settings, logger=cls.log) + def process(self, instance): """Process all meshes""" if not self.is_active(instance.data): From e094573b454840b290a68daaaaafeeefebfb4402 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 20:36:49 +0100 Subject: [PATCH 51/60] Re-order logic so global toggle will always override any other settings --- .../validate_animation_out_set_related_node_ids.py | 10 +++++----- .../plugins/publish/validate_rig_out_set_node_ids.py | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py b/client/ayon_core/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py index ac18dc7a57..2502fd74b2 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py @@ -36,11 +36,6 @@ class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin, @classmethod def apply_settings(cls, project_settings): - # Disable plug-in if cbId workflow is disabled - if not project_settings["maya"].get("use_cbid_workflow", True): - cls.enabled = False - return - # Preserve automatic settings applying logic settings = get_plugin_settings(plugin=cls, project_settings=project_settings, @@ -48,6 +43,11 @@ class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin, category="maya") apply_plugin_settings_automatically(cls, settings, logger=cls.log) + # Disable plug-in if cbId workflow is disabled + if not project_settings["maya"].get("use_cbid_workflow", True): + cls.enabled = False + return + def process(self, instance): """Process all meshes""" if not self.is_active(instance.data): diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py b/client/ayon_core/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py index c7afd41a91..c55953df7a 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py @@ -38,11 +38,6 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin, @classmethod def apply_settings(cls, project_settings): - # Disable plug-in if cbId workflow is disabled - if not project_settings["maya"].get("use_cbid_workflow", True): - cls.enabled = False - return - # Preserve automatic settings applying logic settings = get_plugin_settings(plugin=cls, project_settings=project_settings, @@ -50,6 +45,11 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin, category="maya") apply_plugin_settings_automatically(cls, settings, logger=cls.log) + # Disable plug-in if cbId workflow is disabled + if not project_settings["maya"].get("use_cbid_workflow", True): + cls.enabled = False + return + def process(self, instance): """Process all meshes""" if not self.is_active(instance.data): From c7a1ab2a65ef24e568d5661d314eccf9d0ddd3d7 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 21:44:57 +0100 Subject: [PATCH 52/60] Add version check for Hou 20+ --- client/ayon_core/hosts/houdini/plugins/load/load_image.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/ayon_core/hosts/houdini/plugins/load/load_image.py b/client/ayon_core/hosts/houdini/plugins/load/load_image.py index 72bb873eff..0429b1c3fe 100644 --- a/client/ayon_core/hosts/houdini/plugins/load/load_image.py +++ b/client/ayon_core/hosts/houdini/plugins/load/load_image.py @@ -166,6 +166,10 @@ class ImageLoader(load.LoaderPlugin): dict: Parm to value mapping if colorspace data is defined. """ + # Using OCIO colorspace on COP2 File node is only supported in Hou 20+ + major, _, _ = hou.applicationVersion() + if major < 20: + return {} data = representation.get("data", {}).get("colorspaceData", {}) if not data: From 3cee75065734549542277bf0ee9585404343fe59 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 22:10:08 +0100 Subject: [PATCH 53/60] Fix instance node --- .../ayon_core/hosts/maya/plugins/publish/validate_step_size.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_step_size.py b/client/ayon_core/hosts/maya/plugins/publish/validate_step_size.py index a3419a83a9..cad584d8f9 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_step_size.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_step_size.py @@ -29,7 +29,7 @@ class ValidateStepSize(pyblish.api.InstancePlugin, @classmethod def get_invalid(cls, instance): - objset = instance.data['name'] + objset = instance.data['instance_node'] step = instance.data.get("step", 1.0) if step < cls.MIN or step > cls.MAX: From f95d172c55f1fba372d8b7b501894016b34fde23 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 25 Mar 2024 22:10:26 +0100 Subject: [PATCH 54/60] Improve validation message --- .../ayon_core/hosts/maya/plugins/publish/validate_step_size.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_step_size.py b/client/ayon_core/hosts/maya/plugins/publish/validate_step_size.py index cad584d8f9..a276a5b644 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_step_size.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_step_size.py @@ -47,4 +47,4 @@ class ValidateStepSize(pyblish.api.InstancePlugin, invalid = self.get_invalid(instance) if invalid: raise PublishValidationError( - "Invalid instances found: {0}".format(invalid)) + "Instance found with invalid step size: {0}".format(invalid)) From b57337ea7713a92d564bdab12e9885dc7c065a08 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Tue, 26 Mar 2024 12:58:19 +0200 Subject: [PATCH 55/60] Houdini Redshift allow disabling AOVs --- .../hosts/houdini/plugins/publish/collect_redshift_rop.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/houdini/plugins/publish/collect_redshift_rop.py b/client/ayon_core/hosts/houdini/plugins/publish/collect_redshift_rop.py index 67cc080ead..8437757c58 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/collect_redshift_rop.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/collect_redshift_rop.py @@ -68,12 +68,15 @@ class CollectRedshiftROPRenderProducts(pyblish.api.InstancePlugin): files_by_aov = { "_": self.generate_expected_files(instance, beauty_product)} - + aovs_rop = rop.parm("RS_aovGetFromNode").evalAsNode() if aovs_rop: rop = aovs_rop - num_aovs = rop.evalParm("RS_aov") + num_aovs = 0 + if not rop.evalParm('RS_aovAllAOVsDisabled'): + num_aovs = rop.evalParm("RS_aov") + for index in range(num_aovs): i = index + 1 From e391f058081d4bb6ab83aff18bea7598f7344c3b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 26 Mar 2024 14:47:42 +0100 Subject: [PATCH 56/60] Refactor frame data collection and sequence handling - Removed unnecessary line - Added check for files type before processing --- .../plugins/publish/collect_sequence_frame_data.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/traypublisher/plugins/publish/collect_sequence_frame_data.py b/client/ayon_core/hosts/traypublisher/plugins/publish/collect_sequence_frame_data.py index bd5bac114d..de18050f41 100644 --- a/client/ayon_core/hosts/traypublisher/plugins/publish/collect_sequence_frame_data.py +++ b/client/ayon_core/hosts/traypublisher/plugins/publish/collect_sequence_frame_data.py @@ -43,7 +43,6 @@ class CollectSequenceFrameData( instance.data[key] = value self.log.debug(f"Collected Frame range data '{key}':{value} ") - def get_frame_data_from_repre_sequence(self, instance): repres = instance.data.get("representations") folder_attributes = instance.data["folderEntity"]["attrib"] @@ -56,6 +55,9 @@ class CollectSequenceFrameData( return files = first_repre["files"] + if not isinstance(files, list): + files = [files] + collections, _ = clique.assemble(files) if not collections: # No sequences detected and we can't retrieve From ec11da9861ea3d9670ed066b19aed1db5829c876 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 26 Mar 2024 15:53:49 +0100 Subject: [PATCH 57/60] fix access to folder entity in look assigner tool --- .../ayon_core/hosts/maya/tools/mayalookassigner/widgets.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/maya/tools/mayalookassigner/widgets.py b/client/ayon_core/hosts/maya/tools/mayalookassigner/widgets.py index 6cc5f156e3..f345b87e36 100644 --- a/client/ayon_core/hosts/maya/tools/mayalookassigner/widgets.py +++ b/client/ayon_core/hosts/maya/tools/mayalookassigner/widgets.py @@ -125,8 +125,9 @@ class AssetOutliner(QtWidgets.QWidget): folder_items = {} namespaces_by_folder_path = defaultdict(set) for item in items: - folder_id = item["folder"]["id"] - folder_path = item["folder"]["path"] + folder_entity = item["folder_entity"] + folder_id = folder_entity["id"] + folder_path = folder_entity["path"] namespaces_by_folder_path[folder_path].add(item.get("namespace")) if folder_path in folder_items: From 3526a1e52e60aef2892ad26892eac8c677ece6a2 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 26 Mar 2024 16:02:44 +0100 Subject: [PATCH 58/60] use correct source for product type --- .../hosts/maya/plugins/load/load_redshift_proxy.py | 5 +---- client/ayon_core/hosts/maya/plugins/load/load_reference.py | 6 +----- .../ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py | 5 +---- .../hosts/maya/plugins/load/load_vdb_to_redshift.py | 5 +---- .../ayon_core/hosts/maya/plugins/load/load_vdb_to_vray.py | 5 +---- client/ayon_core/hosts/maya/plugins/load/load_vrayproxy.py | 5 +---- client/ayon_core/hosts/maya/plugins/load/load_vrayscene.py | 5 +---- client/ayon_core/hosts/maya/plugins/load/load_yeti_cache.py | 5 +---- 8 files changed, 8 insertions(+), 33 deletions(-) diff --git a/client/ayon_core/hosts/maya/plugins/load/load_redshift_proxy.py b/client/ayon_core/hosts/maya/plugins/load/load_redshift_proxy.py index 63dae87243..0f91d9048a 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_redshift_proxy.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_redshift_proxy.py @@ -32,10 +32,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): def load(self, context, name=None, namespace=None, options=None): """Plugin entry point.""" - try: - product_type = context["representation"]["context"]["family"] - except ValueError: - product_type = "redshiftproxy" + product_type = context["product"]["productType"] folder_name = context["folder"]["name"] namespace = namespace or unique_namespace( diff --git a/client/ayon_core/hosts/maya/plugins/load/load_reference.py b/client/ayon_core/hosts/maya/plugins/load/load_reference.py index fdd85eda43..de18b2b0ec 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_reference.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_reference.py @@ -117,11 +117,7 @@ class ReferenceLoader(plugin.ReferenceLoader): def process_reference(self, context, name, namespace, options): import maya.cmds as cmds - try: - product_type = context["representation"]["context"]["family"] - except ValueError: - product_type = "model" - + product_type = context["product"]["productType"] project_name = context["project"]["name"] # True by default to keep legacy behaviours attach_to_root = options.get("attach_to_root", True) diff --git a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py index f0fb89e5a4..3d984fdc79 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_arnold.py @@ -25,10 +25,7 @@ class LoadVDBtoArnold(load.LoaderPlugin): from ayon_core.hosts.maya.api.pipeline import containerise from ayon_core.hosts.maya.api.lib import unique_namespace - try: - product_type = context["representation"]["context"]["family"] - except ValueError: - product_type = "vdbcache" + product_type = context["product"]["productType"] # Check if the plugin for arnold is available on the pc try: diff --git a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_redshift.py b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_redshift.py index cad0900590..3fa490f405 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_redshift.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_redshift.py @@ -31,10 +31,7 @@ class LoadVDBtoRedShift(load.LoaderPlugin): from ayon_core.hosts.maya.api.pipeline import containerise from ayon_core.hosts.maya.api.lib import unique_namespace - try: - product_type = context["representation"]["context"]["family"] - except ValueError: - product_type = "vdbcache" + product_type = context["product"]["productType"] # Check if the plugin for redshift is available on the pc try: diff --git a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_vray.py b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_vray.py index 88f62e81a4..7b87c21f38 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_vray.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_vdb_to_vray.py @@ -94,10 +94,7 @@ class LoadVDBtoVRay(load.LoaderPlugin): "Path does not exist: %s" % path ) - try: - product_type = context["representation"]["context"]["family"] - except ValueError: - product_type = "vdbcache" + product_type = context["product"]["productType"] # Ensure V-ray is loaded with the vrayvolumegrid if not cmds.pluginInfo("vrayformaya", query=True, loaded=True): diff --git a/client/ayon_core/hosts/maya/plugins/load/load_vrayproxy.py b/client/ayon_core/hosts/maya/plugins/load/load_vrayproxy.py index 59d8eadefa..895a4a4127 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_vrayproxy.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_vrayproxy.py @@ -47,10 +47,7 @@ class VRayProxyLoader(load.LoaderPlugin): """ - try: - product_type = context["representation"]["context"]["family"] - except ValueError: - product_type = "vrayproxy" + product_type = context["product"]["productType"] # get all representations for this version filename = self._get_abc( diff --git a/client/ayon_core/hosts/maya/plugins/load/load_vrayscene.py b/client/ayon_core/hosts/maya/plugins/load/load_vrayscene.py index 2f4ab1d080..36a25e2af1 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_vrayscene.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_vrayscene.py @@ -26,10 +26,7 @@ class VRaySceneLoader(load.LoaderPlugin): color = "orange" def load(self, context, name, namespace, data): - try: - product_type = context["representation"]["context"]["family"] - except ValueError: - product_type = "vrayscene_layer" + product_type = context["product"]["productType"] folder_name = context["folder"]["name"] namespace = namespace or unique_namespace( diff --git a/client/ayon_core/hosts/maya/plugins/load/load_yeti_cache.py b/client/ayon_core/hosts/maya/plugins/load/load_yeti_cache.py index 8933c4d8a6..a5cd04b0f4 100644 --- a/client/ayon_core/hosts/maya/plugins/load/load_yeti_cache.py +++ b/client/ayon_core/hosts/maya/plugins/load/load_yeti_cache.py @@ -56,10 +56,7 @@ class YetiCacheLoader(load.LoaderPlugin): """ - try: - product_type = context["representation"]["context"]["family"] - except ValueError: - product_type = "yeticache" + product_type = context["product"]["productType"] # Build namespace folder_name = context["folder"]["name"] From cd0a3005d3d2cfc9418c4d32fa1fbac296b4d93b Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 26 Mar 2024 17:27:31 +0100 Subject: [PATCH 59/60] Fix - differentiate between host main and main --- client/ayon_core/hosts/aftereffects/api/launch_script.py | 4 ++-- client/ayon_core/hosts/harmony/api/launch_script.py | 4 ++-- client/ayon_core/hosts/photoshop/api/launch_script.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/ayon_core/hosts/aftereffects/api/launch_script.py b/client/ayon_core/hosts/aftereffects/api/launch_script.py index ad4e779bd0..87926c022b 100644 --- a/client/ayon_core/hosts/aftereffects/api/launch_script.py +++ b/client/ayon_core/hosts/aftereffects/api/launch_script.py @@ -8,7 +8,7 @@ workfile or others. import os import sys -from ayon_core.hosts.aftereffects.api.launch_logic import main +from ayon_core.hosts.aftereffects.api.launch_logic import main as host_main # Get current file to locate start point of sys.argv CURRENT_FILE = os.path.abspath(__file__) @@ -83,7 +83,7 @@ def main(argv): if launch_args: # Launch host implementation - main(*launch_args) + host_main(*launch_args) else: # Show message box on_invalid_args(after_script_idx is None) diff --git a/client/ayon_core/hosts/harmony/api/launch_script.py b/client/ayon_core/hosts/harmony/api/launch_script.py index 1f2c36b7e6..3c809e210f 100644 --- a/client/ayon_core/hosts/harmony/api/launch_script.py +++ b/client/ayon_core/hosts/harmony/api/launch_script.py @@ -8,7 +8,7 @@ workfile or others. import os import sys -from ayon_core.hosts.harmony.api.lib import main +from ayon_core.hosts.harmony.api.lib import main as host_main # Get current file to locate start point of sys.argv CURRENT_FILE = os.path.abspath(__file__) @@ -83,7 +83,7 @@ def main(argv): if launch_args: # Launch host implementation - main(*launch_args) + host_main(*launch_args) else: # Show message box on_invalid_args(after_script_idx is None) diff --git a/client/ayon_core/hosts/photoshop/api/launch_script.py b/client/ayon_core/hosts/photoshop/api/launch_script.py index c036b63c46..bb4de80086 100644 --- a/client/ayon_core/hosts/photoshop/api/launch_script.py +++ b/client/ayon_core/hosts/photoshop/api/launch_script.py @@ -8,7 +8,7 @@ workfile or others. import os import sys -from ayon_core.hosts.photoshop.api.lib import main +from ayon_core.hosts.photoshop.api.lib import main as host_main # Get current file to locate start point of sys.argv CURRENT_FILE = os.path.abspath(__file__) @@ -83,7 +83,7 @@ def main(argv): if launch_args: # Launch host implementation - main(*launch_args) + host_main(*launch_args) else: # Show message box on_invalid_args(after_script_idx is None) From df1d0d4a864fce397ba02d2f009666e1e09ef2cf Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 26 Mar 2024 18:32:55 +0100 Subject: [PATCH 60/60] fix unreal load plugins too --- .../hosts/unreal/plugins/load/load_alembic_animation.py | 2 +- client/ayon_core/hosts/unreal/plugins/load/load_layout.py | 2 +- .../ayon_core/hosts/unreal/plugins/load/load_layout_existing.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py b/client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py index 02259b706c..64d684939c 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py @@ -72,7 +72,7 @@ class AnimationAlembicLoader(plugin.Loader): root = unreal_pipeline.AYON_ASSET_DIR folder_name = context["folder"]["name"] folder_path = context["folder"]["path"] - product_type = context["representation"]["context"]["family"] + product_type = context["product"]["productType"] suffix = "_CON" if folder_name: asset_name = "{}_{}".format(folder_name, name) diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_layout.py b/client/ayon_core/hosts/unreal/plugins/load/load_layout.py index 6c667d3d2f..6c01925453 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_layout.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_layout.py @@ -659,7 +659,7 @@ class LayoutLoader(plugin.Loader): "loader": str(self.__class__.__name__), "representation": context["representation"]["id"], "parent": context["representation"]["versionId"], - "family": context["representation"]["context"]["family"], + "family": context["product"]["productType"], "loaded_assets": loaded_assets } imprint( diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py b/client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py index 700b6957a2..56e36f6185 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py @@ -393,7 +393,7 @@ class ExistingLayoutLoader(plugin.Loader): folder_name = context["folder"]["name"] folder_path = context["folder"]["path"] - product_type = context["representation"]["context"]["family"] + product_type = context["product"]["productType"] asset_name = f"{folder_name}_{name}" if folder_name else name container_name = f"{folder_name}_{name}_CON"