From 4944ad3e830593278e4a42c98b4afd96e512778f Mon Sep 17 00:00:00 2001 From: "Yuichiro Tachibana (Tsuchiya)" Date: Wed, 6 Mar 2024 02:12:18 +0900 Subject: [PATCH] dev/ruff (#1531) * Install Ruff and uninstall Black, isort, and Flake8 * Run ruff format * Update the format make rule * Update the CI steps * Fix --- .github/workflows/main.yml | 7 +- Makefile | 5 +- app_deepspeech.py | 2 +- pages/.isort.cfg | 3 - pages/8_media_files_streaming.py | 1 + pages/pyproject.toml | 3 + poetry.lock | 161 +++++------------------ pyproject.toml | 31 +---- sample_utils/download.py | 2 +- scripts/release_check.py | 3 +- streamlit_webrtc/__init__.py | 3 +- streamlit_webrtc/components_callbacks.py | 1 + streamlit_webrtc/factory.py | 18 +-- streamlit_webrtc/mix.py | 4 +- 14 files changed, 61 insertions(+), 183 deletions(-) delete mode 100644 pages/.isort.cfg create mode 100644 pages/pyproject.toml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5cf8c7e5..ea67f329 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -89,11 +89,10 @@ jobs: STREAMLIT_VERSION: ${{ matrix.streamlit-version }} - name: Install dependencies run: poetry install - - name: Lint with black, isort, and flake8 + - name: Run Ruff run: | - poetry run black . --check - poetry run isort . --check --resolve-all-configs - poetry run flake8 + poetry run ruff check --output-format=github . + poetry run ruff format . --check - name: Type checking with mypy run: | poetry run mypy . diff --git a/Makefile b/Makefile index adb63c2e..e5e158d1 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,8 @@ pkg/build: poetry build format: - poetry run isort . --resolve-all-configs - poetry run black . - poetry run flake8 + poetry run ruff format . + poetry run ruff check . --fix docker/build: # Set `--platform linux/amd64` because some packages do not work with Docker on M1 mac for now. diff --git a/app_deepspeech.py b/app_deepspeech.py index 605f9f34..cfe141de 100644 --- a/app_deepspeech.py +++ b/app_deepspeech.py @@ -44,7 +44,7 @@ def download_file(url, download_to: Path, expected_size=None): with urllib.request.urlopen(url) as response: length = int(response.info()["Content-Length"]) counter = 0.0 - MEGABYTES = 2.0 ** 20.0 + MEGABYTES = 2.0**20.0 while True: data = response.read(8192) if not data: diff --git a/pages/.isort.cfg b/pages/.isort.cfg deleted file mode 100644 index be9dd0b4..00000000 --- a/pages/.isort.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[settings] -profile=black -known_third_party=streamlit_webrtc diff --git a/pages/8_media_files_streaming.py b/pages/8_media_files_streaming.py index 56015034..841c24da 100644 --- a/pages/8_media_files_streaming.py +++ b/pages/8_media_files_streaming.py @@ -1,4 +1,5 @@ """Media streamings""" + import logging from pathlib import Path from typing import Dict, Optional, cast diff --git a/pages/pyproject.toml b/pages/pyproject.toml new file mode 100644 index 00000000..e439c5cd --- /dev/null +++ b/pages/pyproject.toml @@ -0,0 +1,3 @@ + +[tool.ruff.lint.isort] +known-third-party = ["streamlit_webrtc"] diff --git a/poetry.lock b/poetry.lock index dbe03c16..5321669a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "aiohttp" @@ -316,35 +316,6 @@ files = [ [package.extras] tzdata = ["tzdata"] -[[package]] -name = "black" -version = "21.12b0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.6.2" -files = [ - {file = "black-21.12b0-py3-none-any.whl", hash = "sha256:a615e69ae185e08fdd73e4715e260e2479c861b5740057fde6e8b4e3b7dd589f"}, - {file = "black-21.12b0.tar.gz", hash = "sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3"}, -] - -[package.dependencies] -click = ">=7.1.2" -mypy-extensions = ">=0.4.3" -pathspec = ">=0.9.0,<1" -platformdirs = ">=2" -tomli = ">=0.2.6,<2.0.0" -typing-extensions = [ - {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, - {version = ">=3.10.0.0,<3.10.0.1 || >3.10.0.1", markers = "python_version >= \"3.10\""}, -] - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -python2 = ["typed-ast (>=1.4.3)"] -uvloop = ["uvloop (>=0.15.2)"] - [[package]] name = "blinker" version = "1.5" @@ -796,22 +767,6 @@ files = [ [package.extras] test = ["pytest (>=6)"] -[[package]] -name = "flake8" -version = "5.0.4" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.6.1" -files = [ - {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"}, - {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.9.0,<2.10.0" -pyflakes = ">=2.5.0,<2.6.0" - [[package]] name = "fonttools" version = "4.43.0" @@ -1141,20 +1096,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - [[package]] name = "jinja2" version = "3.1.3" @@ -1421,17 +1362,6 @@ pillow = ">=6.2.0" pyparsing = ">=2.3.1" python-dateutil = ">=2.7" -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - [[package]] name = "mdurl" version = "0.1.2" @@ -1639,12 +1569,13 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.21.0", markers = "python_version <= \"3.9\" and platform_system == \"Darwin\" and platform_machine == \"arm64\" and python_version >= \"3.8\""}, + {version = ">=1.21.0", markers = "python_version <= \"3.9\" and platform_system == \"Darwin\" and platform_machine == \"arm64\""}, + {version = ">=1.21.2", markers = "python_version >= \"3.10\""}, + {version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\""}, {version = ">=1.23.5", markers = "python_version >= \"3.11\""}, - {version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\" and python_version < \"3.11\""}, - {version = ">=1.21.2", markers = "platform_system != \"Darwin\" and python_version >= \"3.10\" and python_version < \"3.11\""}, - {version = ">=1.19.3", markers = "platform_system == \"Linux\" and platform_machine == \"aarch64\" and python_version >= \"3.8\" and python_version < \"3.10\" or python_version > \"3.9\" and python_version < \"3.10\" or python_version >= \"3.9\" and platform_system != \"Darwin\" and python_version < \"3.10\" or python_version >= \"3.9\" and platform_machine != \"arm64\" and python_version < \"3.10\""}, - {version = ">=1.17.3", markers = "(platform_system != \"Darwin\" and platform_system != \"Linux\") and python_version >= \"3.8\" and python_version < \"3.9\" or platform_system != \"Darwin\" and python_version >= \"3.8\" and python_version < \"3.9\" and platform_machine != \"aarch64\" or platform_machine != \"arm64\" and python_version >= \"3.8\" and python_version < \"3.9\" and platform_system != \"Linux\" or (platform_machine != \"arm64\" and platform_machine != \"aarch64\") and python_version >= \"3.8\" and python_version < \"3.9\""}, + {version = ">=1.19.3", markers = "python_version >= \"3.6\" and platform_system == \"Linux\" and platform_machine == \"aarch64\" or python_version >= \"3.9\""}, + {version = ">=1.17.0", markers = "python_version >= \"3.7\""}, + {version = ">=1.17.3", markers = "python_version >= \"3.8\""}, ] [[package]] @@ -1697,7 +1628,7 @@ files = [ [package.dependencies] numpy = [ {version = ">=1.20.3", markers = "python_version < \"3.10\""}, - {version = ">=1.21.0", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, + {version = ">=1.21.0", markers = "python_version >= \"3.10\""}, ] python-dateutil = ">=2.8.1" pytz = ">=2020.1" @@ -1705,17 +1636,6 @@ pytz = ">=2020.1" [package.extras] test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] -[[package]] -name = "pathspec" -version = "0.11.0" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.7" -files = [ - {file = "pathspec-0.11.0-py3-none-any.whl", hash = "sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229"}, - {file = "pathspec-0.11.0.tar.gz", hash = "sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc"}, -] - [[package]] name = "pillow" version = "9.4.0" @@ -1817,21 +1737,6 @@ files = [ {file = "pkgutil_resolve_name-1.3.10.tar.gz", hash = "sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174"}, ] -[[package]] -name = "platformdirs" -version = "3.0.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -optional = false -python-versions = ">=3.7" -files = [ - {file = "platformdirs-3.0.0-py3-none-any.whl", hash = "sha256:b1d5eb14f221506f50d6604a561f4c5786d9e80355219694a1b244bcd96f4567"}, - {file = "platformdirs-3.0.0.tar.gz", hash = "sha256:8a1228abb1ef82d788f74139988b137e78692984ec7b08eaa6c65f1723af28f9"}, -] - -[package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] - [[package]] name = "pluggy" version = "1.4.0" @@ -1926,17 +1831,6 @@ files = [ [package.dependencies] numpy = ">=1.16.6" -[[package]] -name = "pycodestyle" -version = "2.9.1" -description = "Python style guide checker" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b"}, - {file = "pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785"}, -] - [[package]] name = "pycparser" version = "2.21" @@ -1992,17 +1886,6 @@ files = [ [package.dependencies] typing-extensions = "*" -[[package]] -name = "pyflakes" -version = "2.5.0" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"}, - {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"}, -] - [[package]] name = "pygments" version = "2.15.0" @@ -2242,6 +2125,32 @@ typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9 [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] +[[package]] +name = "ruff" +version = "0.3.0" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.3.0-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7deb528029bacf845bdbb3dbb2927d8ef9b4356a5e731b10eef171e3f0a85944"}, + {file = "ruff-0.3.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e1e0d4381ca88fb2b73ea0766008e703f33f460295de658f5467f6f229658c19"}, + {file = "ruff-0.3.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f7dbba46e2827dfcb0f0cc55fba8e96ba7c8700e0a866eb8cef7d1d66c25dcb"}, + {file = "ruff-0.3.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:23dbb808e2f1d68eeadd5f655485e235c102ac6f12ad31505804edced2a5ae77"}, + {file = "ruff-0.3.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ef655c51f41d5fa879f98e40c90072b567c666a7114fa2d9fe004dffba00932"}, + {file = "ruff-0.3.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d0d3d7ef3d4f06433d592e5f7d813314a34601e6c5be8481cccb7fa760aa243e"}, + {file = "ruff-0.3.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b08b356d06a792e49a12074b62222f9d4ea2a11dca9da9f68163b28c71bf1dd4"}, + {file = "ruff-0.3.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9343690f95710f8cf251bee1013bf43030072b9f8d012fbed6ad702ef70d360a"}, + {file = "ruff-0.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1f3ed501a42f60f4dedb7805fa8d4534e78b4e196f536bac926f805f0743d49"}, + {file = "ruff-0.3.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:cc30a9053ff2f1ffb505a585797c23434d5f6c838bacfe206c0e6cf38c921a1e"}, + {file = "ruff-0.3.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:5da894a29ec018a8293d3d17c797e73b374773943e8369cfc50495573d396933"}, + {file = "ruff-0.3.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:755c22536d7f1889be25f2baf6fedd019d0c51d079e8417d4441159f3bcd30c2"}, + {file = "ruff-0.3.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:dd73fe7f4c28d317855da6a7bc4aa29a1500320818dd8f27df95f70a01b8171f"}, + {file = "ruff-0.3.0-py3-none-win32.whl", hash = "sha256:19eacceb4c9406f6c41af806418a26fdb23120dfe53583df76d1401c92b7c14b"}, + {file = "ruff-0.3.0-py3-none-win_amd64.whl", hash = "sha256:128265876c1d703e5f5e5a4543bd8be47c73a9ba223fd3989d4aa87dd06f312f"}, + {file = "ruff-0.3.0-py3-none-win_arm64.whl", hash = "sha256:e3a4a6d46aef0a84b74fcd201a4401ea9a6cd85614f6a9435f2d33dd8cefbf83"}, + {file = "ruff-0.3.0.tar.gz", hash = "sha256:0886184ba2618d815067cf43e005388967b67ab9c80df52b32ec1152ab49f53a"}, +] + [[package]] name = "six" version = "1.16.0" @@ -2621,4 +2530,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more [metadata] lock-version = "2.0" python-versions = ">=3.8,<4,!=3.9.7" -content-hash = "804962dd8f05247f6f7398075b091ecc05303a9bacd2ce716f6d34a2fc809357" +content-hash = "87eedbe099a19c46a325de2120139d155bd1bf7c7b3920a14323428c8d16188a" diff --git a/pyproject.toml b/pyproject.toml index 2310adab..23b8bf2d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,10 +19,8 @@ typing_extensions = { version = ">=3.7.4,<5.0.0", python = "<3.8" } packaging = ">=20.0" [tool.poetry.group.dev.dependencies] -black = "^21.12b0" click = ">=7.0,<8.0" # We must specify the click version because we install older versions of Streamlit in the CI process and their depending click version is different from the newer releases. -isort = "^5.10.1" -flake8 = "^5.0.4" +ruff = "^0.3.0" mypy = "^1.0.0" pydub = "^0.25.1" matplotlib = "^3.5.1" @@ -39,31 +37,8 @@ pandas = [ streamlit = "^1.13.0" twilio = ">=8.1,<10.0" -[tool.black] -line-length = 88 -target-version = ['py38'] -exclude = ''' - -( - /( - \.eggs # exclude a few common directories in the - | \.git # root of the project - | \.hg - | \.mypy_cache - | \.tox - | \.venv - | _build - | buck-out - | build - | dist - )/ - | streamlit_webrtc/frontend -) -''' - -[tool.isort] -# https://pycqa.github.io/isort/docs/configuration/black_compatibility/ -profile = "black" +[tool.ruff.lint] +extend-select = ["I"] [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/sample_utils/download.py b/sample_utils/download.py index e19e8958..d6fb09dc 100644 --- a/sample_utils/download.py +++ b/sample_utils/download.py @@ -28,7 +28,7 @@ def download_file(url, download_to: Path, expected_size=None): with urllib.request.urlopen(url) as response: length = int(response.info()["Content-Length"]) counter = 0.0 - MEGABYTES = 2.0 ** 20.0 + MEGABYTES = 2.0**20.0 while True: data = response.read(8192) if not data: diff --git a/scripts/release_check.py b/scripts/release_check.py index a5a1637e..c19a8aa5 100644 --- a/scripts/release_check.py +++ b/scripts/release_check.py @@ -1,5 +1,4 @@ -""" A script to check whether a variable `_RELEASE` is set as True. -""" +"""A script to check whether a variable `_RELEASE` is set as True.""" import argparse import ast diff --git a/streamlit_webrtc/__init__.py b/streamlit_webrtc/__init__.py index dc1b627b..5a127e95 100644 --- a/streamlit_webrtc/__init__.py +++ b/streamlit_webrtc/__init__.py @@ -1,5 +1,4 @@ -"""streamlit-webrtc -""" +"""streamlit-webrtc""" try: import importlib.metadata as importlib_metadata diff --git a/streamlit_webrtc/components_callbacks.py b/streamlit_webrtc/components_callbacks.py index 7349b333..82627edc 100644 --- a/streamlit_webrtc/components_callbacks.py +++ b/streamlit_webrtc/components_callbacks.py @@ -25,6 +25,7 @@ Script begins... """ + from streamlit import session_state as _state from streamlit.components.v1 import components as _components diff --git a/streamlit_webrtc/factory.py b/streamlit_webrtc/factory.py index c8ad95cc..e683007a 100644 --- a/streamlit_webrtc/factory.py +++ b/streamlit_webrtc/factory.py @@ -63,8 +63,7 @@ def create_process_track( frame_callback: Optional[FrameCallback] = None, queued_frames_callback: Optional[QueuedVideoFramesCallback] = None, on_ended: Optional[MediaEndedCallback] = None, -) -> AudioProcessTrack[AudioProcessorT]: - ... +) -> AudioProcessTrack[AudioProcessorT]: ... @overload @@ -76,8 +75,7 @@ def create_process_track( frame_callback: Optional[FrameCallback] = None, queued_frames_callback: Optional[QueuedVideoFramesCallback] = None, on_ended: Optional[MediaEndedCallback] = None, -) -> AsyncAudioProcessTrack[AudioProcessorT]: - ... +) -> AsyncAudioProcessTrack[AudioProcessorT]: ... @overload @@ -89,8 +87,7 @@ def create_process_track( frame_callback: Optional[FrameCallback] = None, queued_frames_callback: Optional[QueuedVideoFramesCallback] = None, on_ended: Optional[MediaEndedCallback] = None, -) -> VideoProcessTrack[VideoProcessorT]: - ... +) -> VideoProcessTrack[VideoProcessorT]: ... @overload @@ -102,8 +99,7 @@ def create_process_track( frame_callback: Optional[FrameCallback] = None, queued_frames_callback: Optional[QueuedVideoFramesCallback] = None, on_ended: Optional[MediaEndedCallback] = None, -) -> AsyncVideoProcessTrack[VideoProcessorT]: - ... +) -> AsyncVideoProcessTrack[VideoProcessorT]: ... # Overloads for the cases where the processor_factory is NOT specified @@ -116,8 +112,7 @@ def create_process_track( processor_factory: Literal[None] = None, queued_frames_callback: Optional[QueuedVideoFramesCallback] = None, on_ended: Optional[MediaEndedCallback] = None, -) -> MediaProcessTrack[CallbackAttachableProcessor[FrameT], FrameT]: - ... +) -> MediaProcessTrack[CallbackAttachableProcessor[FrameT], FrameT]: ... @overload @@ -129,8 +124,7 @@ def create_process_track( async_processing: Literal[True] = True, queued_frames_callback: Optional[QueuedVideoFramesCallback] = None, on_ended: Optional[MediaEndedCallback] = None, -) -> AsyncMediaProcessTrack[CallbackAttachableProcessor[FrameT], FrameT]: - ... +) -> AsyncMediaProcessTrack[CallbackAttachableProcessor[FrameT], FrameT]: ... def create_process_track( diff --git a/streamlit_webrtc/mix.py b/streamlit_webrtc/mix.py index 51c8a46a..bd10add5 100644 --- a/streamlit_webrtc/mix.py +++ b/streamlit_webrtc/mix.py @@ -127,7 +127,9 @@ class MediaStreamMixTrack(MediaStreamTrack, Generic[FrameT]): _input_tasks: "weakref.WeakKeyDictionary[RelayStreamTrack, asyncio.Task]" _input_queue: asyncio.Queue _queue: "asyncio.Queue[Optional[Frame]]" - _latest_frames_map: "weakref.WeakKeyDictionary[RelayStreamTrack, Union[Frame, None]]" # noqa: E501 + _latest_frames_map: ( + "weakref.WeakKeyDictionary[RelayStreamTrack, Union[Frame, None]]" + ) _latest_frames_updated_event: asyncio.Event _output_started: bool