Merge branch stable into develop

environments/review-docs-merge-py0v6m/deployments/18364
Georg Krause 2023-09-01 14:09:58 +02:00
rodzic d2f7d45a0d
commit ec8dc8e09f
57 zmienionych plików z 2851 dodań i 1914 usunięć

Wyświetl plik

@ -93,6 +93,7 @@ review_front:
VUE_APP_ROUTER_BASE_URL: /-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/front-review/
VUE_APP_INSTANCE_URL: https://demo.funkwhale.audio
NODE_ENV: review
NODE_OPTIONS: --max-old-space-size=4096
environment:
name: review/front/$CI_COMMIT_REF_NAME
url: http://$CI_PROJECT_NAMESPACE.pages.funkwhale.audio/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/front-review/index.html
@ -403,6 +404,7 @@ build_front:
image: $CI_REGISTRY/funkwhale/ci/node-python:18
variables:
<<: *keep_git_files_permissions
NODE_OPTIONS: --max-old-space-size=4096
cache: *front_cache
before_script:
- cd front

Wyświetl plik

@ -36,14 +36,14 @@ repos:
args: [--directory=api, --check]
- repo: https://github.com/asottile/pyupgrade
rev: v3.6.0
rev: v3.9.0
hooks:
- id: pyupgrade
args: [--py38-plus]
exclude: ^(api/.*/migrations/.*)
- repo: https://github.com/psf/black
rev: 23.3.0
rev: 23.7.0
hooks:
- id: black
@ -58,7 +58,7 @@ repos:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1
rev: v3.0.2
hooks:
- id: prettier
files: \.(md|yml|yaml|json)$

Wyświetl plik

@ -9,10 +9,74 @@ This changelog is viewable on the web at https://docs.funkwhale.audio/changelog.
<!-- towncrier -->
## 1.3.2 (2023-09-01)
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Enhancements:
- Enable sourcemaps for production builds
- Use logger composable instead of window.console
Bugfixes:
- Clear shuffled id list on queue clear (#2192)
- Fetch the nodeinfo endpoint from .well-known/nodeinfo when checking instance availability
- Fix instance checking its own availability (#2199)
- Fix multiarch docker builds #2211
- Fix ordering when querystring contains `+` prefix
Resolve multiple updates to ordering fields
- Fix password reset via email
- Make podcast episode pagination reactive (#2205)
- Render HTML in podcast short description (#2206)
- Resolve race condition regarding axios when initializing the frontend
Prevent sending same language setting to backend multiple times
Documentation:
- Fixed incorrect upgrade instructions link in docs.
Contributors to our Issues:
- Ciarán Ainsworth
- Georg Krause
- Kasper Seweryn
- Kay Borowski
- Marcos Peña
- Mathieu Jourdan
- Virgile Robles
- codl
- jooola
- petitminion
- tinglycraniumplacidly
- unkn0wwn52
Contributors to our Merge Requests:
- Ciarán Ainsworth
- Georg Krause
- JuniorJPDJ
- Kasper Seweryn
- Marcos Peña
- Virgile Robles
- codl
- jooola
- petitminion
Committers:
- Ciarán Ainsworth
- codl
- Georg Krause
- jo
- Kasper Seweryn
- petitminion
## 1.3.1 (2023-06-27)
Upgrade instructions are available at
https://docs.funkwhale.audio/admin/upgrading.html
https://docs.funkwhale.audio/administrator/upgrade/index.html
Bugfixes:
@ -82,7 +146,7 @@ Committers:
## 1.3.0 (2023-06-01)
Upgrade instructions are available at
https://docs.funkwhale.audio/admin/upgrading.html
https://docs.funkwhale.audio/administrator/upgrade/index.html
Update instructions:
@ -496,7 +560,8 @@ Committers:
## 1.2.9 (2022-11-25)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Bugfixes:
@ -535,7 +600,8 @@ Contributors to our Merge Requests:
## 1.2.8 (2022-09-12)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Features:
@ -590,7 +656,8 @@ Contributors to our Merge Requests:
## 1.2.7 (2022-07-14)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Bugfixes:
@ -613,7 +680,8 @@ Contributors to our Merge Requests:
## 1.2.6 (2022-07-04)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Bugfixes:
@ -662,7 +730,8 @@ Contributors to our Merge Requests:
## 1.2.5 (2022-05-07)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Enhancements:
@ -711,7 +780,8 @@ Contributors to our Merge Requests:
## 1.2.4 (2022-04-23)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Enhancements:
@ -752,7 +822,8 @@ Committers:
## 1.2.3 (2022-03-18)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Enhancements:
@ -808,7 +879,8 @@ Committers
## 1.2.2 (2022-02-04)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Bugfixes:
@ -862,7 +934,8 @@ Committers
## 1.2.1 (2022-01-06)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Bugfixes:
@ -891,7 +964,8 @@ Committers:
## 1.2.0 (2021-12-27)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Due to a bug in our CI Pipeline, you need to download the frontend artifact here: https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/81069/artifacts/download
@ -1086,13 +1160,15 @@ Contributors to our Merge Requests:
## 1.1.4 (2021-08-02)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
- Pinned version of asgiref to avoid trouble with latest release. For further information, see #1516
## 1.1.3 (2021-08-02)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Enhancements:
@ -1108,7 +1184,8 @@ Bugfixes:
## 1.1.2 (2021-05-19)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Enhancements:
@ -1123,7 +1200,8 @@ Bugfixes:
## 1.1.1 (2021-04-13)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Enhancements:
@ -1140,7 +1218,8 @@ Bugfixes:
## 1.1 (2021-03-10)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Enhancements:
@ -1222,7 +1301,8 @@ Contributors to this release (development, documentation, reviews):
## 1.1-rc2 (2021-03-01)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Bugfixes:
@ -1233,7 +1313,8 @@ Bugfixes:
## 1.1-rc1 (2021-02-24)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Enhancements:
@ -1292,7 +1373,8 @@ Contributors to this release (development, documentation, reviews):
## 1.0.1 (2020-10-31)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Enhancements:
@ -1314,7 +1396,8 @@ Contributors to this release (development, documentation, reviews):
## 1.0 (2020-09-09)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
### Dropped python 3.5 support [manual action required, non-docker only]
@ -1444,7 +1527,8 @@ Contributors to this release (translation, development, documentation, reviews,
## 0.21.2 (2020-07-27)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Enhancements:
@ -1472,7 +1556,8 @@ Contributors to this release (development, documentation, reviews):
## 0.21.1 (2020-06-11)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Features:
@ -1530,7 +1615,8 @@ This 0.21 release is dedicated to Agate, to thank her, for both having created t
We are truly grateful as well to the dozens of people who contributed to this release with translations, development, documentation, reviews, design, testing, feedback, financial support, third-party projects and integrations… You made it possible!
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html, there are also additional operations you need to execute, listed in the changelog below (search "Manual action").
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html, there are also additional operations you need to execute, listed in the changelog below (search "Manual action").
### Channels and podcasts
@ -1835,7 +1921,8 @@ Contributors to this release (translation, development, documentation, reviews,
## 0.20.1 (2019-10-28)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
### Denormalized audio permission logic in a separate table to enhance performance
@ -1897,6 +1984,9 @@ Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgradi
### Support for genres via tags
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
One of our most requested missing features is now available!
Starting with Funkwhale 0.20,
@ -2206,7 +2296,8 @@ Contributors to this release (translation, development, documentation, reviews,
## 0.19.1 (2019-06-28)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Enhancements:
@ -2250,7 +2341,8 @@ Contributors to this release (committers and reviewers):
## 0.19.0 (2019-05-16)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
### Edits on tracks, albums and artists
@ -2454,7 +2546,8 @@ Contributors to this release (committers and translators):
## 0.18.3 (2019-03-21)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
### Avoid mixed content when deploying mono-container behind proxy [Manual action required]
@ -2497,7 +2590,8 @@ Documentation:
## 0.18.2 (2019-02-13)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
Enhancements:
@ -2514,7 +2608,8 @@ Bugfixes:
## 0.18.1 (2019-01-29)
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html
### Fix Gzip compression to avoid BREACH exploit [security] [manual action required]
@ -2637,7 +2732,8 @@ as you can enjoy it today. Thank you so much Naomi <3
Many thanks to the dozens of people that contributed to this release: translators, developers,
bug hunters, admins and backers. You made it possible!
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html, ensure you also execute the instructions
Upgrade instructions are available at
https://docs.funkwhale.audio/administrator/upgrade/index.html, ensure you also execute the instructions
marked with `[manual action required]` and `[manual action suggested]`.
See `Full changelog` below for an exhaustive list of changes!

Wyświetl plik

@ -8,7 +8,7 @@ The Funkwhale software is the core of the community project. While we have a cor
Funkwhale's backend is written in [Python](https://www.python.org/) using [Django](https://www.djangoproject.com) and [Django REST framework](https://www.django-rest-framework.org/). Our web app is written in [Vue.js](https://vuejs.org/) and [Typescript](https://typescriptlang.org).
Whether you're an experienced developer or you're just learning, check out our [developer guide](https://docs.funkwhale.audio/developers/index.html) to get started.
Whether you're an experienced developer or you're just learning, check out our [developer guide](https://docs.funkwhale.audio/developer/index.html) to get started.
## Document Funkwhale

Wyświetl plik

@ -10,7 +10,7 @@ Want to help make Funkwhale even better? We welcome contributions from across th
You can find contribution information in our [documentation hub](https://docs.funkwhale.audio).
- [Developer guides](https://docs.funkwhale.audio/developers/index.html)
- [Developer guides](https://docs.funkwhale.audio/developer/index.html)
- [Contributor guides](https://docs.funkwhale.audio/contributing.html)
## Get help

Wyświetl plik

@ -32,7 +32,7 @@ Each API call returns HTTP headers to pass the following information:
- How many more requests in the scope can be made within the rate-limit timeframe (`X-RateLimit-Remaining`)
- How much time does the client need to wait to send another request (`Retry-After`)
For more information, check our [rate limit documentation](https://docs.funkwhale.audio/admin/configuration.html#api-configuration)
For more information, check our [rate limit documentation](https://docs.funkwhale.audio/developer/api/rate-limit.html)
## Resources

Wyświetl plik

@ -1181,7 +1181,8 @@ if BROWSABLE_API_ENABLED:
)
REST_AUTH_SERIALIZERS = {
"PASSWORD_RESET_SERIALIZER": "funkwhale_api.users.serializers.PasswordResetSerializer" # noqa
"PASSWORD_RESET_SERIALIZER": "funkwhale_api.users.serializers.PasswordResetSerializer", # noqa
"PASSWORD_RESET_CONFIRM_SERIALIZER": "funkwhale_api.users.serializers.PasswordResetConfirmSerializer", # noqa
}
REST_SESSION_LOGIN = False

Wyświetl plik

@ -632,7 +632,7 @@ def fetch_collection(url, max_pages, channel, is_page=False):
def check_all_remote_instance_availability():
domains = models.Domain.objects.all().prefetch_related()
for domain in domains:
if domain == settings.FUNKWHALE_HOSTNAME:
if domain.name == settings.FUNKWHALE_HOSTNAME:
# No need to check the instance itself: Its always reachable
domain.reachable = True
domain.last_successful_contact = timezone.now()
@ -643,8 +643,7 @@ def check_all_remote_instance_availability():
@celery.app.task(name="federation.check_single_remote_instance_availability")
def check_single_remote_instance_availability(domain):
try:
response = requests.get(f"https://{domain.name}/api/v1/instance/nodeinfo/2.0/")
nodeinfo = response.json()
nodeinfo = fetch_nodeinfo(domain.name)
except Exception as e:
logger.info(
f"Domain {domain.name} could not be reached because of the following error : {e}. \

Wyświetl plik

@ -3,15 +3,18 @@ import re
from allauth.account import models as allauth_models
from dj_rest_auth.registration.serializers import RegisterSerializer as RS
from dj_rest_auth.registration.serializers import get_adapter
from dj_rest_auth.serializers import PasswordResetConfirmSerializer as PRCS
from dj_rest_auth.serializers import PasswordResetSerializer as PRS
from django.contrib import auth
from django.contrib.auth.forms import PasswordResetForm
from django.core import validators
from django.utils.deconstruct import deconstructible
from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy as _
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from funkwhale_api.activity import serializers as activity_serializers
from funkwhale_api.common import models as common_models
@ -252,6 +255,34 @@ class PasswordResetSerializer(PRS):
return {"extra_email_context": adapters.get_email_context()}
class PasswordResetConfirmSerializer(PRCS):
def validate(self, attrs):
from allauth.account.forms import default_token_generator
from django.utils.http import urlsafe_base64_decode as uid_decoder
UserModel = auth.get_user_model()
# Decode the uidb64 (allauth use base36) to uid to get User object
try:
uid = force_str(uid_decoder(attrs["uid"]))
self.user = UserModel._default_manager.get(pk=uid)
except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
raise ValidationError({"uid": [_("Invalid value")]})
if not default_token_generator.check_token(self.user, attrs["token"]):
raise ValidationError({"token": [_("Invalid value")]})
self.custom_validation(attrs)
# Construct SetPasswordForm instance
self.set_password_form = self.set_password_form_class(
user=self.user,
data=attrs,
)
if not self.set_password_form.is_valid():
raise serializers.ValidationError(self.set_password_form.errors)
return attrs
class UserDeleteSerializer(serializers.Serializer):
password = serializers.CharField()
confirm = serializers.BooleanField()

452
api/poetry.lock wygenerowano
Wyświetl plik

@ -152,24 +152,24 @@ vine = ">=5.0.0"
[[package]]
name = "anyio"
version = "3.7.1"
version = "4.0.0"
description = "High level compatibility layer for multiple asynchronous event loop implementations"
optional = false
python-versions = ">=3.7"
python-versions = ">=3.8"
files = [
{file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"},
{file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"},
{file = "anyio-4.0.0-py3-none-any.whl", hash = "sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f"},
{file = "anyio-4.0.0.tar.gz", hash = "sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a"},
]
[package.dependencies]
exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""}
idna = ">=2.8"
sniffio = ">=1.1"
[package.extras]
doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"]
test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
trio = ["trio (<0.22)"]
doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)"]
test = ["anyio[trio]", "coverage[toml] (>=7)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
trio = ["trio (>=0.22)"]
[[package]]
name = "appnope"
@ -234,13 +234,13 @@ wrapt = [
[[package]]
name = "async-timeout"
version = "4.0.2"
version = "4.0.3"
description = "Timeout context manager for asyncio programs"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
files = [
{file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"},
{file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"},
{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]]
@ -541,13 +541,13 @@ zstd = ["zstandard"]
[[package]]
name = "certifi"
version = "2023.5.7"
version = "2023.7.22"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.6"
files = [
{file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"},
{file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"},
{file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"},
{file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"},
]
[[package]]
@ -1034,13 +1034,13 @@ dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"]
[[package]]
name = "dill"
version = "0.3.6"
description = "serialize all of python"
version = "0.3.7"
description = "serialize all of Python"
optional = false
python-versions = ">=3.7"
files = [
{file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"},
{file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"},
{file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"},
{file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"},
]
[package.extras]
@ -1370,13 +1370,13 @@ sidecar = ["drf-spectacular-sidecar"]
[[package]]
name = "exceptiongroup"
version = "1.1.2"
version = "1.1.3"
description = "Backport of PEP 654 (exception groups)"
optional = false
python-versions = ">=3.7"
files = [
{file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"},
{file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"},
{file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"},
{file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"},
]
[package.extras]
@ -1695,13 +1695,13 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs
[[package]]
name = "importlib-resources"
version = "6.0.0"
version = "6.0.1"
description = "Read resources from Python packages"
optional = false
python-versions = ">=3.8"
files = [
{file = "importlib_resources-6.0.0-py3-none-any.whl", hash = "sha256:d952faee11004c045f785bb5636e8f885bed30dc3c940d5d42798a2a4541c185"},
{file = "importlib_resources-6.0.0.tar.gz", hash = "sha256:4cf94875a8368bd89531a756df9a9ebe1f150e0f885030b461237bc7f2d905f2"},
{file = "importlib_resources-6.0.1-py3-none-any.whl", hash = "sha256:134832a506243891221b88b4ae1213327eea96ceb4e407a00d790bb0626f45cf"},
{file = "importlib_resources-6.0.1.tar.gz", hash = "sha256:4359457e42708462b9626a04657c6208ad799ceb41e5c58c57ffa0e6a098a5d4"},
]
[package.dependencies]
@ -1819,21 +1819,21 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"]
[[package]]
name = "jedi"
version = "0.18.2"
version = "0.19.0"
description = "An autocompletion tool for Python that can be used for text editors."
optional = false
python-versions = ">=3.6"
files = [
{file = "jedi-0.18.2-py2.py3-none-any.whl", hash = "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e"},
{file = "jedi-0.18.2.tar.gz", hash = "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612"},
{file = "jedi-0.19.0-py2.py3-none-any.whl", hash = "sha256:cb8ce23fbccff0025e9386b5cf85e892f94c9b822378f8da49970471335ac64e"},
{file = "jedi-0.19.0.tar.gz", hash = "sha256:bcf9894f1753969cbac8022a8c2eaee06bfa3724e4192470aaffe7eb6272b0c4"},
]
[package.dependencies]
parso = ">=0.8.0,<0.9.0"
parso = ">=0.8.3,<0.9.0"
[package.extras]
docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"]
qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
[[package]]
@ -1849,13 +1849,13 @@ files = [
[[package]]
name = "jsonschema"
version = "4.18.4"
version = "4.19.0"
description = "An implementation of JSON Schema validation for Python"
optional = false
python-versions = ">=3.8"
files = [
{file = "jsonschema-4.18.4-py3-none-any.whl", hash = "sha256:971be834317c22daaa9132340a51c01b50910724082c2c1a2ac87eeec153a3fe"},
{file = "jsonschema-4.18.4.tar.gz", hash = "sha256:fb3642735399fa958c0d2aad7057901554596c63349f4f6b283c493cf692a25d"},
{file = "jsonschema-4.19.0-py3-none-any.whl", hash = "sha256:043dc26a3845ff09d20e4420d6012a9c91c9aa8999fa184e7efcfeccb41e32cb"},
{file = "jsonschema-4.19.0.tar.gz", hash = "sha256:6e1e7569ac13be8139b2dd2c21a55d350066ee3f80df06c608b398cdc6f30e8f"},
]
[package.dependencies]
@ -2356,13 +2356,13 @@ testing = ["docopt", "pytest (<6.0.0)"]
[[package]]
name = "pathspec"
version = "0.11.1"
version = "0.11.2"
description = "Utility library for gitignore style pattern matching of file paths."
optional = false
python-versions = ">=3.7"
files = [
{file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
{file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
{file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"},
{file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
]
[[package]]
@ -2488,28 +2488,28 @@ files = [
[[package]]
name = "platformdirs"
version = "3.9.1"
version = "3.10.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.9.1-py3-none-any.whl", hash = "sha256:ad8291ae0ae5072f66c16945166cb11c63394c7a3ad1b1bc9828ca3162da8c2f"},
{file = "platformdirs-3.9.1.tar.gz", hash = "sha256:1b42b450ad933e981d56e59f1b97495428c9bd60698baab9f3eb3d00d5822421"},
{file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"},
{file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"},
]
[package.extras]
docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"]
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
[[package]]
name = "pluggy"
version = "1.2.0"
version = "1.3.0"
description = "plugin and hook calling mechanisms for python"
optional = false
python-versions = ">=3.7"
python-versions = ">=3.8"
files = [
{file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"},
{file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"},
{file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"},
{file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"},
]
[package.extras]
@ -2645,13 +2645,13 @@ files = [
[[package]]
name = "pygments"
version = "2.15.1"
version = "2.16.1"
description = "Pygments is a syntax highlighting package written in Python."
optional = false
python-versions = ">=3.7"
files = [
{file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
{file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
{file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"},
{file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"},
]
[package.extras]
@ -2997,7 +2997,6 @@ files = [
{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"},
@ -3005,15 +3004,8 @@ files = [
{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"},
@ -3030,7 +3022,6 @@ files = [
{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"},
@ -3038,7 +3029,6 @@ files = [
{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"},
@ -3064,13 +3054,13 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"
[[package]]
name = "referencing"
version = "0.30.0"
version = "0.30.2"
description = "JSON Referencing + Python"
optional = false
python-versions = ">=3.8"
files = [
{file = "referencing-0.30.0-py3-none-any.whl", hash = "sha256:c257b08a399b6c2f5a3510a50d28ab5dbc7bbde049bcaf954d43c446f83ab548"},
{file = "referencing-0.30.0.tar.gz", hash = "sha256:47237742e990457f7512c7d27486394a9aadaf876cbfaa4be65b27b4f4d47c6b"},
{file = "referencing-0.30.2-py3-none-any.whl", hash = "sha256:449b6669b6121a9e96a7f9e410b245d471e8d48964c67113ce9afe50c8dd7bdf"},
{file = "referencing-0.30.2.tar.gz", hash = "sha256:794ad8003c65938edcdbc027f1933215e0d0ccc0291e3ce20a4d87432b59efc0"},
]
[package.dependencies]
@ -3152,119 +3142,119 @@ rsa = ["oauthlib[signedtoken] (>=3.0.0)"]
[[package]]
name = "rpds-py"
version = "0.9.2"
version = "0.10.0"
description = "Python bindings to Rust's persistent data structures (rpds)"
optional = false
python-versions = ">=3.8"
files = [
{file = "rpds_py-0.9.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:ab6919a09c055c9b092798ce18c6c4adf49d24d4d9e43a92b257e3f2548231e7"},
{file = "rpds_py-0.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d55777a80f78dd09410bd84ff8c95ee05519f41113b2df90a69622f5540c4f8b"},
{file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a216b26e5af0a8e265d4efd65d3bcec5fba6b26909014effe20cd302fd1138fa"},
{file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29cd8bfb2d716366a035913ced99188a79b623a3512292963d84d3e06e63b496"},
{file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44659b1f326214950a8204a248ca6199535e73a694be8d3e0e869f820767f12f"},
{file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:745f5a43fdd7d6d25a53ab1a99979e7f8ea419dfefebcab0a5a1e9095490ee5e"},
{file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a987578ac5214f18b99d1f2a3851cba5b09f4a689818a106c23dbad0dfeb760f"},
{file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bf4151acb541b6e895354f6ff9ac06995ad9e4175cbc6d30aaed08856558201f"},
{file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:03421628f0dc10a4119d714a17f646e2837126a25ac7a256bdf7c3943400f67f"},
{file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:13b602dc3e8dff3063734f02dcf05111e887f301fdda74151a93dbbc249930fe"},
{file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fae5cb554b604b3f9e2c608241b5d8d303e410d7dfb6d397c335f983495ce7f6"},
{file = "rpds_py-0.9.2-cp310-none-win32.whl", hash = "sha256:47c5f58a8e0c2c920cc7783113df2fc4ff12bf3a411d985012f145e9242a2764"},
{file = "rpds_py-0.9.2-cp310-none-win_amd64.whl", hash = "sha256:4ea6b73c22d8182dff91155af018b11aac9ff7eca085750455c5990cb1cfae6e"},
{file = "rpds_py-0.9.2-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:e564d2238512c5ef5e9d79338ab77f1cbbda6c2d541ad41b2af445fb200385e3"},
{file = "rpds_py-0.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f411330a6376fb50e5b7a3e66894e4a39e60ca2e17dce258d53768fea06a37bd"},
{file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e7521f5af0233e89939ad626b15278c71b69dc1dfccaa7b97bd4cdf96536bb7"},
{file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8d3335c03100a073883857e91db9f2e0ef8a1cf42dc0369cbb9151c149dbbc1b"},
{file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d25b1c1096ef0447355f7293fbe9ad740f7c47ae032c2884113f8e87660d8f6e"},
{file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a5d3fbd02efd9cf6a8ffc2f17b53a33542f6b154e88dd7b42ef4a4c0700fdad"},
{file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5934e2833afeaf36bd1eadb57256239785f5af0220ed8d21c2896ec4d3a765f"},
{file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:095b460e117685867d45548fbd8598a8d9999227e9061ee7f012d9d264e6048d"},
{file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:91378d9f4151adc223d584489591dbb79f78814c0734a7c3bfa9c9e09978121c"},
{file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:24a81c177379300220e907e9b864107614b144f6c2a15ed5c3450e19cf536fae"},
{file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:de0b6eceb46141984671802d412568d22c6bacc9b230174f9e55fc72ef4f57de"},
{file = "rpds_py-0.9.2-cp311-none-win32.whl", hash = "sha256:700375326ed641f3d9d32060a91513ad668bcb7e2cffb18415c399acb25de2ab"},
{file = "rpds_py-0.9.2-cp311-none-win_amd64.whl", hash = "sha256:0766babfcf941db8607bdaf82569ec38107dbb03c7f0b72604a0b346b6eb3298"},
{file = "rpds_py-0.9.2-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:b1440c291db3f98a914e1afd9d6541e8fc60b4c3aab1a9008d03da4651e67386"},
{file = "rpds_py-0.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0f2996fbac8e0b77fd67102becb9229986396e051f33dbceada3debaacc7033f"},
{file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f30d205755566a25f2ae0382944fcae2f350500ae4df4e795efa9e850821d82"},
{file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:159fba751a1e6b1c69244e23ba6c28f879a8758a3e992ed056d86d74a194a0f3"},
{file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1f044792e1adcea82468a72310c66a7f08728d72a244730d14880cd1dabe36b"},
{file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9251eb8aa82e6cf88510530b29eef4fac825a2b709baf5b94a6094894f252387"},
{file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01899794b654e616c8625b194ddd1e5b51ef5b60ed61baa7a2d9c2ad7b2a4238"},
{file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0c43f8ae8f6be1d605b0465671124aa8d6a0e40f1fb81dcea28b7e3d87ca1e1"},
{file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:207f57c402d1f8712618f737356e4b6f35253b6d20a324d9a47cb9f38ee43a6b"},
{file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b52e7c5ae35b00566d244ffefba0f46bb6bec749a50412acf42b1c3f402e2c90"},
{file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:978fa96dbb005d599ec4fd9ed301b1cc45f1a8f7982d4793faf20b404b56677d"},
{file = "rpds_py-0.9.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6aa8326a4a608e1c28da191edd7c924dff445251b94653988efb059b16577a4d"},
{file = "rpds_py-0.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aad51239bee6bff6823bbbdc8ad85136c6125542bbc609e035ab98ca1e32a192"},
{file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd4dc3602370679c2dfb818d9c97b1137d4dd412230cfecd3c66a1bf388a196"},
{file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dd9da77c6ec1f258387957b754f0df60766ac23ed698b61941ba9acccd3284d1"},
{file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:190ca6f55042ea4649ed19c9093a9be9d63cd8a97880106747d7147f88a49d18"},
{file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:876bf9ed62323bc7dcfc261dbc5572c996ef26fe6406b0ff985cbcf460fc8a4c"},
{file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa2818759aba55df50592ecbc95ebcdc99917fa7b55cc6796235b04193eb3c55"},
{file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9ea4d00850ef1e917815e59b078ecb338f6a8efda23369677c54a5825dbebb55"},
{file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:5855c85eb8b8a968a74dc7fb014c9166a05e7e7a8377fb91d78512900aadd13d"},
{file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:14c408e9d1a80dcb45c05a5149e5961aadb912fff42ca1dd9b68c0044904eb32"},
{file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:65a0583c43d9f22cb2130c7b110e695fff834fd5e832a776a107197e59a1898e"},
{file = "rpds_py-0.9.2-cp38-none-win32.whl", hash = "sha256:71f2f7715935a61fa3e4ae91d91b67e571aeb5cb5d10331ab681256bda2ad920"},
{file = "rpds_py-0.9.2-cp38-none-win_amd64.whl", hash = "sha256:674c704605092e3ebbbd13687b09c9f78c362a4bc710343efe37a91457123044"},
{file = "rpds_py-0.9.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:07e2c54bef6838fa44c48dfbc8234e8e2466d851124b551fc4e07a1cfeb37260"},
{file = "rpds_py-0.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f7fdf55283ad38c33e35e2855565361f4bf0abd02470b8ab28d499c663bc5d7c"},
{file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:890ba852c16ace6ed9f90e8670f2c1c178d96510a21b06d2fa12d8783a905193"},
{file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50025635ba8b629a86d9d5474e650da304cb46bbb4d18690532dd79341467846"},
{file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:517cbf6e67ae3623c5127206489d69eb2bdb27239a3c3cc559350ef52a3bbf0b"},
{file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0836d71ca19071090d524739420a61580f3f894618d10b666cf3d9a1688355b1"},
{file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c439fd54b2b9053717cca3de9583be6584b384d88d045f97d409f0ca867d80f"},
{file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f68996a3b3dc9335037f82754f9cdbe3a95db42bde571d8c3be26cc6245f2324"},
{file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7d68dc8acded354c972116f59b5eb2e5864432948e098c19fe6994926d8e15c3"},
{file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f963c6b1218b96db85fc37a9f0851eaf8b9040aa46dec112611697a7023da535"},
{file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a46859d7f947061b4010e554ccd1791467d1b1759f2dc2ec9055fa239f1bc26"},
{file = "rpds_py-0.9.2-cp39-none-win32.whl", hash = "sha256:e07e5dbf8a83c66783a9fe2d4566968ea8c161199680e8ad38d53e075df5f0d0"},
{file = "rpds_py-0.9.2-cp39-none-win_amd64.whl", hash = "sha256:682726178138ea45a0766907957b60f3a1bf3acdf212436be9733f28b6c5af3c"},
{file = "rpds_py-0.9.2-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:196cb208825a8b9c8fc360dc0f87993b8b260038615230242bf18ec84447c08d"},
{file = "rpds_py-0.9.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:c7671d45530fcb6d5e22fd40c97e1e1e01965fc298cbda523bb640f3d923b387"},
{file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83b32f0940adec65099f3b1c215ef7f1d025d13ff947975a055989cb7fd019a4"},
{file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f67da97f5b9eac838b6980fc6da268622e91f8960e083a34533ca710bec8611"},
{file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03975db5f103997904c37e804e5f340c8fdabbb5883f26ee50a255d664eed58c"},
{file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:987b06d1cdb28f88a42e4fb8a87f094e43f3c435ed8e486533aea0bf2e53d931"},
{file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c861a7e4aef15ff91233751619ce3a3d2b9e5877e0fcd76f9ea4f6847183aa16"},
{file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02938432352359805b6da099c9c95c8a0547fe4b274ce8f1a91677401bb9a45f"},
{file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:ef1f08f2a924837e112cba2953e15aacfccbbfcd773b4b9b4723f8f2ddded08e"},
{file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:35da5cc5cb37c04c4ee03128ad59b8c3941a1e5cd398d78c37f716f32a9b7f67"},
{file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:141acb9d4ccc04e704e5992d35472f78c35af047fa0cfae2923835d153f091be"},
{file = "rpds_py-0.9.2-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:79f594919d2c1a0cc17d1988a6adaf9a2f000d2e1048f71f298b056b1018e872"},
{file = "rpds_py-0.9.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:a06418fe1155e72e16dddc68bb3780ae44cebb2912fbd8bb6ff9161de56e1798"},
{file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b2eb034c94b0b96d5eddb290b7b5198460e2d5d0c421751713953a9c4e47d10"},
{file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b08605d248b974eb02f40bdcd1a35d3924c83a2a5e8f5d0fa5af852c4d960af"},
{file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a0805911caedfe2736935250be5008b261f10a729a303f676d3d5fea6900c96a"},
{file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab2299e3f92aa5417d5e16bb45bb4586171c1327568f638e8453c9f8d9e0f020"},
{file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c8d7594e38cf98d8a7df25b440f684b510cf4627fe038c297a87496d10a174f"},
{file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b9ec12ad5f0a4625db34db7e0005be2632c1013b253a4a60e8302ad4d462afd"},
{file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1fcdee18fea97238ed17ab6478c66b2095e4ae7177e35fb71fbe561a27adf620"},
{file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:933a7d5cd4b84f959aedeb84f2030f0a01d63ae6cf256629af3081cf3e3426e8"},
{file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:686ba516e02db6d6f8c279d1641f7067ebb5dc58b1d0536c4aaebb7bf01cdc5d"},
{file = "rpds_py-0.9.2-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0173c0444bec0a3d7d848eaeca2d8bd32a1b43f3d3fde6617aac3731fa4be05f"},
{file = "rpds_py-0.9.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d576c3ef8c7b2d560e301eb33891d1944d965a4d7a2eacb6332eee8a71827db6"},
{file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed89861ee8c8c47d6beb742a602f912b1bb64f598b1e2f3d758948721d44d468"},
{file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1054a08e818f8e18910f1bee731583fe8f899b0a0a5044c6e680ceea34f93876"},
{file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99e7c4bb27ff1aab90dcc3e9d37ee5af0231ed98d99cb6f5250de28889a3d502"},
{file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c545d9d14d47be716495076b659db179206e3fd997769bc01e2d550eeb685596"},
{file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9039a11bca3c41be5a58282ed81ae422fa680409022b996032a43badef2a3752"},
{file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fb39aca7a64ad0c9490adfa719dbeeb87d13be137ca189d2564e596f8ba32c07"},
{file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2d8b3b3a2ce0eaa00c5bbbb60b6713e94e7e0becab7b3db6c5c77f979e8ed1f1"},
{file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:99b1c16f732b3a9971406fbfe18468592c5a3529585a45a35adbc1389a529a03"},
{file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c27ee01a6c3223025f4badd533bea5e87c988cb0ba2811b690395dfe16088cfe"},
{file = "rpds_py-0.9.2.tar.gz", hash = "sha256:8d70e8f14900f2657c249ea4def963bed86a29b81f81f5b76b5a9215680de945"},
{file = "rpds_py-0.10.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:c1e0e9916301e3b3d970814b1439ca59487f0616d30f36a44cead66ee1748c31"},
{file = "rpds_py-0.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ce8caa29ebbdcde67e5fd652c811d34bc01f249dbc0d61e5cc4db05ae79a83b"},
{file = "rpds_py-0.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad277f74b1c164f7248afa968700e410651eb858d7c160d109fb451dc45a2f09"},
{file = "rpds_py-0.10.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8e1c68303ccf7fceb50fbab79064a2636119fd9aca121f28453709283dbca727"},
{file = "rpds_py-0.10.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:780fcb855be29153901c67fc9c5633d48aebef21b90aa72812fa181d731c6b00"},
{file = "rpds_py-0.10.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bbd7b24d108509a1b9b6679fcc1166a7dd031dbef1f3c2c73788f42e3ebb3beb"},
{file = "rpds_py-0.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0700c2133ba203c4068aaecd6a59bda22e06a5e46255c9da23cbf68c6942215d"},
{file = "rpds_py-0.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:576da63eae7809f375932bfcbca2cf20620a1915bf2fedce4b9cc8491eceefe3"},
{file = "rpds_py-0.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:23750a9b8a329844ba1fe267ca456bb3184984da2880ed17ae641c5af8de3fef"},
{file = "rpds_py-0.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d08395595c42bcd82c3608762ce734504c6d025eef1c06f42326a6023a584186"},
{file = "rpds_py-0.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1d7b7b71bcb82d8713c7c2e9c5f061415598af5938666beded20d81fa23e7640"},
{file = "rpds_py-0.10.0-cp310-none-win32.whl", hash = "sha256:97f5811df21703446b42303475b8b855ee07d6ab6cdf8565eff115540624f25d"},
{file = "rpds_py-0.10.0-cp310-none-win_amd64.whl", hash = "sha256:cdbed8f21204398f47de39b0a9b180d7e571f02dfb18bf5f1b618e238454b685"},
{file = "rpds_py-0.10.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:7a3a3d3e4f1e3cd2a67b93a0b6ed0f2499e33f47cc568e3a0023e405abdc0ff1"},
{file = "rpds_py-0.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fc72ae476732cdb7b2c1acb5af23b478b8a0d4b6fcf19b90dd150291e0d5b26b"},
{file = "rpds_py-0.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0583f69522732bdd79dca4cd3873e63a29acf4a299769c7541f2ca1e4dd4bc6"},
{file = "rpds_py-0.10.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f8b9a7cd381970e64849070aca7c32d53ab7d96c66db6c2ef7aa23c6e803f514"},
{file = "rpds_py-0.10.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0d292cabd7c8335bdd3237ded442480a249dbcdb4ddfac5218799364a01a0f5c"},
{file = "rpds_py-0.10.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6903cdca64f1e301af9be424798328c1fe3b4b14aede35f04510989fc72f012"},
{file = "rpds_py-0.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bed57543c99249ab3a4586ddc8786529fbc33309e5e8a1351802a06ca2baf4c2"},
{file = "rpds_py-0.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:15932ec5f224b0e35764dc156514533a4fca52dcfda0dfbe462a1a22b37efd59"},
{file = "rpds_py-0.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:eb2d59bc196e6d3b1827c7db06c1a898bfa0787c0574af398e65ccf2e97c0fbe"},
{file = "rpds_py-0.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f99d74ddf9d3b6126b509e81865f89bd1283e3fc1b568b68cd7bd9dfa15583d7"},
{file = "rpds_py-0.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f70bec8a14a692be6dbe7ce8aab303e88df891cbd4a39af091f90b6702e28055"},
{file = "rpds_py-0.10.0-cp311-none-win32.whl", hash = "sha256:5f7487be65b9c2c510819e744e375bd41b929a97e5915c4852a82fbb085df62c"},
{file = "rpds_py-0.10.0-cp311-none-win_amd64.whl", hash = "sha256:748e472345c3a82cfb462d0dff998a7bf43e621eed73374cb19f307e97e08a83"},
{file = "rpds_py-0.10.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:d4639111e73997567343df6551da9dd90d66aece1b9fc26c786d328439488103"},
{file = "rpds_py-0.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f4760e1b02173f4155203054f77a5dc0b4078de7645c922b208d28e7eb99f3e2"},
{file = "rpds_py-0.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a6420a36975e0073acaeee44ead260c1f6ea56812cfc6c31ec00c1c48197173"},
{file = "rpds_py-0.10.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:58fc4d66ee349a23dbf08c7e964120dc9027059566e29cf0ce6205d590ed7eca"},
{file = "rpds_py-0.10.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:063411228b852fb2ed7485cf91f8e7d30893e69b0acb207ec349db04cccc8225"},
{file = "rpds_py-0.10.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65af12f70355de29e1092f319f85a3467f4005e959ab65129cb697169ce94b86"},
{file = "rpds_py-0.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:298e8b5d8087e0330aac211c85428c8761230ef46a1f2c516d6a2f67fb8803c5"},
{file = "rpds_py-0.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5b9bf77008f2c55dabbd099fd3ac87009471d223a1c7ebea36873d39511b780a"},
{file = "rpds_py-0.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c7853f27195598e550fe089f78f0732c66ee1d1f0eaae8ad081589a5a2f5d4af"},
{file = "rpds_py-0.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:75dbfd41a61bc1fb0536bf7b1abf272dc115c53d4d77db770cd65d46d4520882"},
{file = "rpds_py-0.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b25136212a3d064a8f0b9ebbb6c57094c5229e0de76d15c79b76feff26aeb7b8"},
{file = "rpds_py-0.10.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:9affee8cb1ec453382c27eb9043378ab32f49cd4bc24a24275f5c39bf186c279"},
{file = "rpds_py-0.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4d55528ef13af4b4e074d067977b1f61408602f53ae4537dccf42ba665c2c7bd"},
{file = "rpds_py-0.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7865df1fb564092bcf46dac61b5def25342faf6352e4bc0e61a286e3fa26a3d"},
{file = "rpds_py-0.10.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3f5cc8c7bc99d2bbcd704cef165ca7d155cd6464c86cbda8339026a42d219397"},
{file = "rpds_py-0.10.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cbae50d352e4717ffc22c566afc2d0da744380e87ed44a144508e3fb9114a3f4"},
{file = "rpds_py-0.10.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fccbf0cd3411719e4c9426755df90bf3449d9fc5a89f077f4a7f1abd4f70c910"},
{file = "rpds_py-0.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d10c431073dc6ebceed35ab22948a016cc2b5120963c13a41e38bdde4a7212"},
{file = "rpds_py-0.10.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1b401e8b9aece651512e62c431181e6e83048a651698a727ea0eb0699e9f9b74"},
{file = "rpds_py-0.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:7618a082c55cf038eede4a918c1001cc8a4411dfe508dc762659bcd48d8f4c6e"},
{file = "rpds_py-0.10.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:b3226b246facae14909b465061ddcfa2dfeadb6a64f407f24300d42d69bcb1a1"},
{file = "rpds_py-0.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a8edd467551c1102dc0f5754ab55cd0703431cd3044edf8c8e7d9208d63fa453"},
{file = "rpds_py-0.10.0-cp38-none-win32.whl", hash = "sha256:71333c22f7cf5f0480b59a0aef21f652cf9bbaa9679ad261b405b65a57511d1e"},
{file = "rpds_py-0.10.0-cp38-none-win_amd64.whl", hash = "sha256:a8ab1adf04ae2d6d65835995218fd3f3eb644fe20655ca8ee233e2c7270ff53b"},
{file = "rpds_py-0.10.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:87c93b25d538c433fb053da6228c6290117ba53ff6a537c133b0f2087948a582"},
{file = "rpds_py-0.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7996aed3f65667c6dcc8302a69368435a87c2364079a066750a2eac75ea01e"},
{file = "rpds_py-0.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8856aa76839dc234d3469f1e270918ce6bec1d6a601eba928f45d68a15f04fc3"},
{file = "rpds_py-0.10.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:00215f6a9058fbf84f9d47536902558eb61f180a6b2a0fa35338d06ceb9a2e5a"},
{file = "rpds_py-0.10.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23a059143c1393015c68936370cce11690f7294731904bdae47cc3e16d0b2474"},
{file = "rpds_py-0.10.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e5c26905aa651cc8c0ddc45e0e5dea2a1296f70bdc96af17aee9d0493280a17"},
{file = "rpds_py-0.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c651847545422c8131660704c58606d841e228ed576c8f1666d98b3d318f89da"},
{file = "rpds_py-0.10.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:80992eb20755701753e30a6952a96aa58f353d12a65ad3c9d48a8da5ec4690cf"},
{file = "rpds_py-0.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ffcf18ad3edf1c170e27e88b10282a2c449aa0358659592462448d71b2000cfc"},
{file = "rpds_py-0.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:08e08ccf5b10badb7d0a5c84829b914c6e1e1f3a716fdb2bf294e2bd01562775"},
{file = "rpds_py-0.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7150b83b3e3ddaac81a8bb6a9b5f93117674a0e7a2b5a5b32ab31fdfea6df27f"},
{file = "rpds_py-0.10.0-cp39-none-win32.whl", hash = "sha256:3455ecc46ea443b5f7d9c2f946ce4017745e017b0d0f8b99c92564eff97e97f5"},
{file = "rpds_py-0.10.0-cp39-none-win_amd64.whl", hash = "sha256:afe6b5a04b2ab1aa89bad32ca47bf71358e7302a06fdfdad857389dca8fb5f04"},
{file = "rpds_py-0.10.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:b1cb078f54af0abd835ca76f93a3152565b73be0f056264da45117d0adf5e99c"},
{file = "rpds_py-0.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8e7e2b3577e97fa43c2c2b12a16139b2cedbd0770235d5179c0412b4794efd9b"},
{file = "rpds_py-0.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae46a50d235f1631d9ec4670503f7b30405103034830bc13df29fd947207f795"},
{file = "rpds_py-0.10.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f869e34d2326e417baee430ae998e91412cc8e7fdd83d979277a90a0e79a5b47"},
{file = "rpds_py-0.10.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3d544a614055b131111bed6edfa1cb0fb082a7265761bcb03321f2dd7b5c6c48"},
{file = "rpds_py-0.10.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ee9c2f6ca9774c2c24bbf7b23086264e6b5fa178201450535ec0859739e6f78d"},
{file = "rpds_py-0.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2da4a8c6d465fde36cea7d54bf47b5cf089073452f0e47c8632ecb9dec23c07"},
{file = "rpds_py-0.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ac00c41dd315d147b129976204839ca9de699d83519ff1272afbe4fb9d362d12"},
{file = "rpds_py-0.10.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:0155c33af0676fc38e1107679be882077680ad1abb6303956b97259c3177e85e"},
{file = "rpds_py-0.10.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:db6585b600b2e76e98131e0ac0e5195759082b51687ad0c94505970c90718f4a"},
{file = "rpds_py-0.10.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:7b6975d3763d0952c111700c0634968419268e6bbc0b55fe71138987fa66f309"},
{file = "rpds_py-0.10.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:6388e4e95a26717b94a05ced084e19da4d92aca883f392dffcf8e48c8e221a24"},
{file = "rpds_py-0.10.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:18f87baa20e02e9277ad8960cd89b63c79c05caf106f4c959a9595c43f2a34a5"},
{file = "rpds_py-0.10.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92f05fc7d832e970047662b3440b190d24ea04f8d3c760e33e7163b67308c878"},
{file = "rpds_py-0.10.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:291c9ce3929a75b45ce8ddde2aa7694fc8449f2bc8f5bd93adf021efaae2d10b"},
{file = "rpds_py-0.10.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:861d25ae0985a1dd5297fee35f476b60c6029e2e6e19847d5b4d0a43a390b696"},
{file = "rpds_py-0.10.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:668d2b45d62c68c7a370ac3dce108ffda482b0a0f50abd8b4c604a813a59e08f"},
{file = "rpds_py-0.10.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:344b89384c250ba6a4ce1786e04d01500e4dac0f4137ceebcaad12973c0ac0b3"},
{file = "rpds_py-0.10.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:885e023e73ce09b11b89ab91fc60f35d80878d2c19d6213a32b42ff36543c291"},
{file = "rpds_py-0.10.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:841128a22e6ac04070a0f84776d07e9c38c4dcce8e28792a95e45fc621605517"},
{file = "rpds_py-0.10.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:899b5e7e2d5a8bc92aa533c2d4e55e5ebba095c485568a5e4bedbc163421259a"},
{file = "rpds_py-0.10.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e7947d9a6264c727a556541b1630296bbd5d0a05068d21c38dde8e7a1c703ef0"},
{file = "rpds_py-0.10.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4992266817169997854f81df7f6db7bdcda1609972d8ffd6919252f09ec3c0f6"},
{file = "rpds_py-0.10.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:26d9fd624649a10e4610fab2bc820e215a184d193e47d0be7fe53c1c8f67f370"},
{file = "rpds_py-0.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0028eb0967942d0d2891eae700ae1a27b7fd18604cfcb16a1ef486a790fee99e"},
{file = "rpds_py-0.10.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f9e7e493ded7042712a374471203dd43ae3fff5b81e3de1a0513fa241af9fd41"},
{file = "rpds_py-0.10.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2d68a8e8a3a816629283faf82358d8c93fe5bd974dd2704152394a3de4cec22a"},
{file = "rpds_py-0.10.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6d5f061f6a2aa55790b9e64a23dfd87b6664ab56e24cd06c78eb43986cb260b"},
{file = "rpds_py-0.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c7c4266c1b61eb429e8aeb7d8ed6a3bfe6c890a1788b18dbec090c35c6b93fa"},
{file = "rpds_py-0.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:80772e3bda6787510d9620bc0c7572be404a922f8ccdfd436bf6c3778119464c"},
{file = "rpds_py-0.10.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:b98e75b21fc2ba5285aef8efaf34131d16af1c38df36bdca2f50634bea2d3060"},
{file = "rpds_py-0.10.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:d63787f289944cc4bde518ad2b5e70a4f0d6e2ce76324635359c74c113fd188f"},
{file = "rpds_py-0.10.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:872f3dcaa8bf2245944861d7311179d2c0c9b2aaa7d3b464d99a7c2e401f01fa"},
{file = "rpds_py-0.10.0.tar.gz", hash = "sha256:e36d7369363d2707d5f68950a64c4e025991eb0177db01ccb6aa6facae48b69f"},
]
[[package]]
name = "s3transfer"
version = "0.6.1"
version = "0.6.2"
description = "An Amazon S3 Transfer Manager"
optional = false
python-versions = ">= 3.7"
files = [
{file = "s3transfer-0.6.1-py3-none-any.whl", hash = "sha256:3c0da2d074bf35d6870ef157158641178a4204a6e689e82546083e31e0311346"},
{file = "s3transfer-0.6.1.tar.gz", hash = "sha256:640bb492711f4c0c0905e1f62b6aaeb771881935ad27884852411f8e9cacbca9"},
{file = "s3transfer-0.6.2-py3-none-any.whl", hash = "sha256:b014be3a8a2aab98cfe1abc7229cc5a9a0cf05eb9c1f2b86b230fd8df3f78084"},
{file = "s3transfer-0.6.2.tar.gz", hash = "sha256:cab66d3380cca3e70939ef2255d01cd8aece6a4907a9528740f668c4b0611861"},
]
[package.dependencies]
@ -3340,18 +3330,18 @@ tests = ["coverage[toml] (>=5.0.2)", "pytest"]
[[package]]
name = "setuptools"
version = "68.0.0"
version = "68.1.2"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
python-versions = ">=3.7"
python-versions = ">=3.8"
files = [
{file = "setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f"},
{file = "setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"},
{file = "setuptools-68.1.2-py3-none-any.whl", hash = "sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b"},
{file = "setuptools-68.1.2.tar.gz", hash = "sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d"},
]
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5,<=7.1.2)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
[[package]]
@ -3429,13 +3419,13 @@ files = [
[[package]]
name = "tomlkit"
version = "0.11.8"
version = "0.12.1"
description = "Style preserving TOML library"
optional = false
python-versions = ">=3.7"
files = [
{file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"},
{file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"},
{file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"},
{file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"},
]
[[package]]
@ -3455,68 +3445,70 @@ test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"]
[[package]]
name = "twisted"
version = "22.10.0"
version = "23.8.0"
description = "An asynchronous networking framework written in Python"
optional = false
python-versions = ">=3.7.1"
files = [
{file = "Twisted-22.10.0-py3-none-any.whl", hash = "sha256:86c55f712cc5ab6f6d64e02503352464f0400f66d4f079096d744080afcccbd0"},
{file = "Twisted-22.10.0.tar.gz", hash = "sha256:32acbd40a94f5f46e7b42c109bfae2b302250945561783a8b7a059048f2d4d31"},
{file = "twisted-23.8.0-py3-none-any.whl", hash = "sha256:b8bdba145de120ffb36c20e6e071cce984e89fba798611ed0704216fb7f884cd"},
{file = "twisted-23.8.0.tar.gz", hash = "sha256:3c73360add17336a622c0d811c2a2ce29866b6e59b1125fd6509b17252098a24"},
]
[package.dependencies]
attrs = ">=19.2.0"
Automat = ">=0.8.0"
attrs = ">=21.3.0"
automat = ">=0.8.0"
constantly = ">=15.1"
hyperlink = ">=17.1.1"
idna = {version = ">=2.4", optional = true, markers = "extra == \"tls\""}
incremental = ">=21.3.0"
incremental = ">=22.10.0"
pyopenssl = {version = ">=21.0.0", optional = true, markers = "extra == \"tls\""}
service-identity = {version = ">=18.1.0", optional = true, markers = "extra == \"tls\""}
twisted-iocpsupport = {version = ">=1.0.2,<2", markers = "platform_system == \"Windows\""}
typing-extensions = ">=3.6.5"
"zope.interface" = ">=4.4.2"
typing-extensions = ">=3.10.0"
zope-interface = ">=5"
[package.extras]
all-non-platform = ["PyHamcrest (>=1.9.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "contextvars (>=2.4,<3)", "cryptography (>=2.6)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.0,<7.0)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "pyasn1", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "service-identity (>=18.1.0)"]
conch = ["appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "cryptography (>=2.6)", "pyasn1"]
conch-nacl = ["PyNaCl", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "cryptography (>=2.6)", "pyasn1"]
all-non-platform = ["twisted[conch,contextvars,http2,serial,test,tls]", "twisted[conch,contextvars,http2,serial,test,tls]"]
conch = ["appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)"]
contextvars = ["contextvars (>=2.4,<3)"]
dev = ["coverage (>=6b1,<7)", "pydoctor (>=22.9.0,<22.10.0)", "pyflakes (>=2.2,<3.0)", "python-subunit (>=1.4,<2.0)", "readthedocs-sphinx-ext (>=2.1,<3.0)", "sphinx (>=5.0,<6)", "sphinx-rtd-theme (>=1.0,<2.0)", "towncrier (>=22.8,<23.0)", "twistedchecker (>=0.7,<1.0)"]
dev-release = ["pydoctor (>=22.9.0,<22.10.0)", "readthedocs-sphinx-ext (>=2.1,<3.0)", "sphinx (>=5.0,<6)", "sphinx-rtd-theme (>=1.0,<2.0)", "towncrier (>=22.8,<23.0)"]
gtk-platform = ["PyHamcrest (>=1.9.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "contextvars (>=2.4,<3)", "cryptography (>=2.6)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.0,<7.0)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "pyasn1", "pygobject", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "service-identity (>=18.1.0)"]
dev = ["coverage (>=6b1,<7)", "pyflakes (>=2.2,<3.0)", "python-subunit (>=1.4,<2.0)", "twisted[dev-release]", "twistedchecker (>=0.7,<1.0)"]
dev-release = ["pydoctor (>=23.4.0,<23.5.0)", "pydoctor (>=23.4.0,<23.5.0)", "readthedocs-sphinx-ext (>=2.2,<3.0)", "readthedocs-sphinx-ext (>=2.2,<3.0)", "sphinx (>=5,<7)", "sphinx (>=5,<7)", "sphinx-rtd-theme (>=1.2,<2.0)", "sphinx-rtd-theme (>=1.2,<2.0)", "towncrier (>=22.12,<23.0)", "towncrier (>=22.12,<23.0)", "urllib3 (<2)", "urllib3 (<2)"]
gtk-platform = ["pygobject", "pygobject", "twisted[all-non-platform]", "twisted[all-non-platform]"]
http2 = ["h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)"]
macos-platform = ["PyHamcrest (>=1.9.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "contextvars (>=2.4,<3)", "cryptography (>=2.6)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.0,<7.0)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "pyasn1", "pyobjc-core", "pyobjc-framework-CFNetwork", "pyobjc-framework-Cocoa", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "service-identity (>=18.1.0)"]
mypy = ["PyHamcrest (>=1.9.0)", "PyNaCl", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "contextvars (>=2.4,<3)", "coverage (>=6b1,<7)", "cryptography (>=2.6)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.0,<7.0)", "idna (>=2.4)", "mypy (==0.930)", "mypy-zope (==0.3.4)", "priority (>=1.1.0,<2.0)", "pyasn1", "pydoctor (>=22.9.0,<22.10.0)", "pyflakes (>=2.2,<3.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "python-subunit (>=1.4,<2.0)", "pywin32 (!=226)", "readthedocs-sphinx-ext (>=2.1,<3.0)", "service-identity (>=18.1.0)", "sphinx (>=5.0,<6)", "sphinx-rtd-theme (>=1.0,<2.0)", "towncrier (>=22.8,<23.0)", "twistedchecker (>=0.7,<1.0)", "types-pyOpenSSL", "types-setuptools"]
osx-platform = ["PyHamcrest (>=1.9.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "contextvars (>=2.4,<3)", "cryptography (>=2.6)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.0,<7.0)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "pyasn1", "pyobjc-core", "pyobjc-framework-CFNetwork", "pyobjc-framework-Cocoa", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "service-identity (>=18.1.0)"]
macos-platform = ["pyobjc-core", "pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "pyobjc-framework-cocoa", "twisted[all-non-platform]", "twisted[all-non-platform]"]
mypy = ["mypy (==0.981)", "mypy-extensions (==0.4.3)", "mypy-zope (==0.3.11)", "twisted[all-non-platform,dev]", "types-pyopenssl", "types-setuptools"]
osx-platform = ["twisted[macos-platform]", "twisted[macos-platform]"]
serial = ["pyserial (>=3.0)", "pywin32 (!=226)"]
test = ["PyHamcrest (>=1.9.0)", "cython-test-exception-raiser (>=1.0.2,<2)", "hypothesis (>=6.0,<7.0)"]
test = ["cython-test-exception-raiser (>=1.0.2,<2)", "hypothesis (>=6.56)", "pyhamcrest (>=2)"]
tls = ["idna (>=2.4)", "pyopenssl (>=21.0.0)", "service-identity (>=18.1.0)"]
windows-platform = ["PyHamcrest (>=1.9.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "contextvars (>=2.4,<3)", "cryptography (>=2.6)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.0,<7.0)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "pyasn1", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)"]
windows-platform = ["pywin32 (!=226)", "pywin32 (!=226)", "twisted[all-non-platform]", "twisted[all-non-platform]"]
[[package]]
name = "twisted-iocpsupport"
version = "1.0.3"
version = "1.0.4"
description = "An extension for use in the twisted I/O Completion Ports reactor."
optional = false
python-versions = "*"
files = [
{file = "twisted-iocpsupport-1.0.3.tar.gz", hash = "sha256:afb00801fdfbaccf0d0173a722626500023d4a19719ac9f129d1347a32e2fc66"},
{file = "twisted_iocpsupport-1.0.3-cp310-cp310-win32.whl", hash = "sha256:a379ef56a576c8090889f74441bc3822ca31ac82253cc61e8d50631bcb0c26d0"},
{file = "twisted_iocpsupport-1.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:1ea2c3fbdb739c95cc8b3355305cd593d2c9ec56d709207aa1a05d4d98671e85"},
{file = "twisted_iocpsupport-1.0.3-cp311-cp311-win32.whl", hash = "sha256:7efcdfafb377f32db90f42bd5fc5bb32cd1e3637ee936cdaf3aff4f4786ab3bf"},
{file = "twisted_iocpsupport-1.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1dbfac706972bf9ec5ce1ddbc735d2ebba406ad363345df8751ffd5252aa1618"},
{file = "twisted_iocpsupport-1.0.3-cp36-cp36m-win32.whl", hash = "sha256:1ddfc5fa22ec6f913464b736b3f46e642237f17ac41be47eed6fa9bd52f5d0e0"},
{file = "twisted_iocpsupport-1.0.3-cp36-cp36m-win_amd64.whl", hash = "sha256:1bdccbb22199fc69fd7744d6d2dfd22d073c028c8611d994b41d2d2ad0e0f40d"},
{file = "twisted_iocpsupport-1.0.3-cp37-cp37m-win32.whl", hash = "sha256:db11c80054b52dbdea44d63d5474a44c9a6531882f0e2960268b15123088641a"},
{file = "twisted_iocpsupport-1.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:67bec1716eb8f466ef366bbf262e1467ecc9e20940111207663ac24049785bad"},
{file = "twisted_iocpsupport-1.0.3-cp38-cp38-win32.whl", hash = "sha256:98a6f16ab215f8c1446e9fc60aaed0ab7c746d566aa2f3492a23cea334e6bebb"},
{file = "twisted_iocpsupport-1.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:4f249d0baac836bb431d6fa0178be063a310136bc489465a831e3abd2d7acafd"},
{file = "twisted_iocpsupport-1.0.3-cp39-cp39-win32.whl", hash = "sha256:aaca8f30c3b7c80d27a33fe9fe0d0bac42b1b012ddc60f677175c30e1becc1f3"},
{file = "twisted_iocpsupport-1.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:dff43136c33665c2d117a73706aef6f7d6433e5c4560332a118fe066b16b8695"},
{file = "twisted_iocpsupport-1.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:8faceae553cfadc42ad791b1790e7cdecb7751102608c405217f6a26e877e0c5"},
{file = "twisted_iocpsupport-1.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:6f8c433faaad5d53d30d1da6968d5a3730df415e2efb6864847267a9b51290cd"},
{file = "twisted_iocpsupport-1.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3f39c41c0213a81a9ce0961e30d0d7650f371ad80f8d261007d15a2deb6d5be3"},
{file = "twisted-iocpsupport-1.0.4.tar.gz", hash = "sha256:858096c0d15e33f15ac157f455d8f86f2f2cdd223963e58c0f682a3af8362d89"},
{file = "twisted_iocpsupport-1.0.4-cp310-cp310-win32.whl", hash = "sha256:afa2b630797f9ed2f27f3d9f55e3f72b4244911e45a8c82756f44babbf0b243e"},
{file = "twisted_iocpsupport-1.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:0058c963c8957bcd3deda62122e89953c9de1e867a274facc9b15dde1a9f31e8"},
{file = "twisted_iocpsupport-1.0.4-cp311-cp311-win32.whl", hash = "sha256:196f7c7ccad4ba4d1783b1c4e1d1b22d93c04275cd780bf7498d16c77319ad6e"},
{file = "twisted_iocpsupport-1.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:4e5f97bcbabdd79cbaa969b63439b89801ea560f11d42b0a387634275c633623"},
{file = "twisted_iocpsupport-1.0.4-cp312-cp312-win32.whl", hash = "sha256:6081bd7c2f4fcf9b383dcdb3b3385d75a26a7c9d2be25b6950c3d8ea652d2d2d"},
{file = "twisted_iocpsupport-1.0.4-cp312-cp312-win_amd64.whl", hash = "sha256:76f7e67cec1f1d097d1f4ed7de41be3d74546e1a4ede0c7d56e775c4dce5dfb0"},
{file = "twisted_iocpsupport-1.0.4-cp36-cp36m-win32.whl", hash = "sha256:3d306fc4d88a6bcf61ce9d572c738b918578121bfd72891625fab314549024b5"},
{file = "twisted_iocpsupport-1.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:391ac4d6002a80e15f35adc4ad6056f4fe1c17ceb0d1f98ba01b0f4f917adfd7"},
{file = "twisted_iocpsupport-1.0.4-cp37-cp37m-win32.whl", hash = "sha256:0c1b5cf37f0b2d96cc3c9bc86fff16613b9f5d0ca565c96cf1f1fb8cfca4b81c"},
{file = "twisted_iocpsupport-1.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:3c5dc11d72519e55f727320e3cee535feedfaee09c0f0765ed1ca7badff1ab3c"},
{file = "twisted_iocpsupport-1.0.4-cp38-cp38-win32.whl", hash = "sha256:cc86c2ef598c15d824a243c2541c29459881c67fc3c0adb6efe2242f8f0ec3af"},
{file = "twisted_iocpsupport-1.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:c27985e949b9b1a1fb4c20c71d315c10ea0f93fdf3ccdd4a8c158b5926edd8c8"},
{file = "twisted_iocpsupport-1.0.4-cp39-cp39-win32.whl", hash = "sha256:e311dfcb470696e3c077249615893cada598e62fa7c4e4ca090167bd2b7d331f"},
{file = "twisted_iocpsupport-1.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:4574eef1f3bb81501fb02f911298af3c02fe8179c31a33b361dd49180c3e644d"},
{file = "twisted_iocpsupport-1.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:872747a3b64e2909aee59c803ccd0bceb9b75bf27915520ebd32d69687040fa2"},
{file = "twisted_iocpsupport-1.0.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:c2712b778bacf1db434e3e065adfed3db300754186a29aecac1efae9ef4bcaff"},
{file = "twisted_iocpsupport-1.0.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7c66fa0aa4236b27b3c61cb488662d85dae746a6d1c7b0d91cf7aae118445adf"},
{file = "twisted_iocpsupport-1.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:300437af17396a945a58dcfffd77863303a8b6d9e65c6e81f1d2eed55b50d444"},
]
[[package]]
@ -3734,33 +3726,33 @@ watchmedo = ["PyYAML (>=3.10)"]
[[package]]
name = "watchfiles"
version = "0.19.0"
version = "0.20.0"
description = "Simple, modern and high performance file watching and code reload in python."
optional = false
python-versions = ">=3.7"
files = [
{file = "watchfiles-0.19.0-cp37-abi3-macosx_10_7_x86_64.whl", hash = "sha256:91633e64712df3051ca454ca7d1b976baf842d7a3640b87622b323c55f3345e7"},
{file = "watchfiles-0.19.0-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:b6577b8c6c8701ba8642ea9335a129836347894b666dd1ec2226830e263909d3"},
{file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:18b28f6ad871b82df9542ff958d0c86bb0d8310bb09eb8e87d97318a3b5273af"},
{file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fac19dc9cbc34052394dbe81e149411a62e71999c0a19e1e09ce537867f95ae0"},
{file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:09ea3397aecbc81c19ed7f025e051a7387feefdb789cf768ff994c1228182fda"},
{file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c0376deac92377817e4fb8f347bf559b7d44ff556d9bc6f6208dd3f79f104aaf"},
{file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c75eff897786ee262c9f17a48886f4e98e6cfd335e011c591c305e5d083c056"},
{file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb5d45c4143c1dd60f98a16187fd123eda7248f84ef22244818c18d531a249d1"},
{file = "watchfiles-0.19.0-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:79c533ff593db861ae23436541f481ec896ee3da4e5db8962429b441bbaae16e"},
{file = "watchfiles-0.19.0-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3d7d267d27aceeeaa3de0dd161a0d64f0a282264d592e335fff7958cc0cbae7c"},
{file = "watchfiles-0.19.0-cp37-abi3-win32.whl", hash = "sha256:176a9a7641ec2c97b24455135d58012a5be5c6217fc4d5fef0b2b9f75dbf5154"},
{file = "watchfiles-0.19.0-cp37-abi3-win_amd64.whl", hash = "sha256:945be0baa3e2440151eb3718fd8846751e8b51d8de7b884c90b17d271d34cae8"},
{file = "watchfiles-0.19.0-cp37-abi3-win_arm64.whl", hash = "sha256:0089c6dc24d436b373c3c57657bf4f9a453b13767150d17284fc6162b2791911"},
{file = "watchfiles-0.19.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:cae3dde0b4b2078f31527acff6f486e23abed307ba4d3932466ba7cdd5ecec79"},
{file = "watchfiles-0.19.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f3920b1285a7d3ce898e303d84791b7bf40d57b7695ad549dc04e6a44c9f120"},
{file = "watchfiles-0.19.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9afd0d69429172c796164fd7fe8e821ade9be983f51c659a38da3faaaaac44dc"},
{file = "watchfiles-0.19.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68dce92b29575dda0f8d30c11742a8e2b9b8ec768ae414b54f7453f27bdf9545"},
{file = "watchfiles-0.19.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:5569fc7f967429d4bc87e355cdfdcee6aabe4b620801e2cf5805ea245c06097c"},
{file = "watchfiles-0.19.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5471582658ea56fca122c0f0d0116a36807c63fefd6fdc92c71ca9a4491b6b48"},
{file = "watchfiles-0.19.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b538014a87f94d92f98f34d3e6d2635478e6be6423a9ea53e4dd96210065e193"},
{file = "watchfiles-0.19.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20b44221764955b1e703f012c74015306fb7e79a00c15370785f309b1ed9aa8d"},
{file = "watchfiles-0.19.0.tar.gz", hash = "sha256:d9b073073e048081e502b6c6b0b88714c026a1a4c890569238d04aca5f9ca74b"},
{file = "watchfiles-0.20.0-cp37-abi3-macosx_10_7_x86_64.whl", hash = "sha256:3796312bd3587e14926013612b23066912cf45a14af71cf2b20db1c12dadf4e9"},
{file = "watchfiles-0.20.0-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:d0002d81c89a662b595645fb684a371b98ff90a9c7d8f8630c82f0fde8310458"},
{file = "watchfiles-0.20.0-cp37-abi3-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:570848706440373b4cd8017f3e850ae17f76dbdf1e9045fc79023b11e1afe490"},
{file = "watchfiles-0.20.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a0351d20d03c6f7ad6b2e8a226a5efafb924c7755ee1e34f04c77c3682417fa"},
{file = "watchfiles-0.20.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:007dcc4a401093010b389c044e81172c8a2520dba257c88f8828b3d460c6bb38"},
{file = "watchfiles-0.20.0-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0d82dbc1832da83e441d112069833eedd4cf583d983fb8dd666fbefbea9d99c0"},
{file = "watchfiles-0.20.0-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99f4c65fd2fce61a571b2a6fcf747d6868db0bef8a934e8ca235cc8533944d95"},
{file = "watchfiles-0.20.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5392dd327a05f538c56edb1c6ebba6af91afc81b40822452342f6da54907bbdf"},
{file = "watchfiles-0.20.0-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:08dc702529bb06a2b23859110c214db245455532da5eaea602921687cfcd23db"},
{file = "watchfiles-0.20.0-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:7d4e66a857621584869cfbad87039e65dadd7119f0d9bb9dbc957e089e32c164"},
{file = "watchfiles-0.20.0-cp37-abi3-win32.whl", hash = "sha256:a03d1e6feb7966b417f43c3e3783188167fd69c2063e86bad31e62c4ea794cc5"},
{file = "watchfiles-0.20.0-cp37-abi3-win_amd64.whl", hash = "sha256:eccc8942bcdc7d638a01435d915b913255bbd66f018f1af051cd8afddb339ea3"},
{file = "watchfiles-0.20.0-cp37-abi3-win_arm64.whl", hash = "sha256:b17d4176c49d207865630da5b59a91779468dd3e08692fe943064da260de2c7c"},
{file = "watchfiles-0.20.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d97db179f7566dcf145c5179ddb2ae2a4450e3a634eb864b09ea04e68c252e8e"},
{file = "watchfiles-0.20.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:835df2da7a5df5464c4a23b2d963e1a9d35afa422c83bf4ff4380b3114603644"},
{file = "watchfiles-0.20.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:608cd94a8767f49521901aff9ae0c92cc8f5a24d528db7d6b0295290f9d41193"},
{file = "watchfiles-0.20.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89d1de8218874925bce7bb2ae9657efc504411528930d7a83f98b1749864f2ef"},
{file = "watchfiles-0.20.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:13f995d5152a8ba4ed7c2bbbaeee4e11a5944defc7cacd0ccb4dcbdcfd78029a"},
{file = "watchfiles-0.20.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:9b5c8d3be7b502f8c43a33c63166ada8828dbb0c6d49c8f9ce990a96de2f5a49"},
{file = "watchfiles-0.20.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e43af4464daa08723c04b43cf978ab86cc55c684c16172622bdac64b34e36af0"},
{file = "watchfiles-0.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87d9e1f75c4f86c93d73b5bd1ebe667558357548f11b4f8af4e0e272f79413ce"},
{file = "watchfiles-0.20.0.tar.gz", hash = "sha256:728575b6b94c90dd531514677201e8851708e6e4b5fe7028ac506a200b622019"},
]
[package.dependencies]

Wyświetl plik

@ -1,6 +1,6 @@
[tool.poetry]
name = "funkwhale-api"
version = "1.3.1"
version = "1.3.2"
description = "Funkwhale API"
authors = ["Funkwhale Collective"]

Wyświetl plik

@ -669,7 +669,18 @@ def test_fetch_collection(mocker, r_mock):
def test_check_all_remote_instance_reachable(factories, r_mock):
domain = factories["federation.Domain"]()
r_mock.get(
f"https://{domain.name}/api/v1/instance/nodeinfo/2.0/", json={"version": "2"}
f"https://{domain.name}/api/v1/instance/nodeinfo/2.0", json={"version": "2"}
)
r_mock.get(
f"https://{domain.name}/.well-known/nodeinfo",
json={
"links": [
{
"rel": "http://nodeinfo.diaspora.software/ns/schema/2.0",
"href": f"https://{domain.name}/api/v1/instance/nodeinfo/2.0",
}
]
},
)
tasks.check_all_remote_instance_availability()
domain = models.Domain.objects.get(name=domain.name)
@ -683,3 +694,10 @@ def test_check_remote_instance_unreachable(factories, r_mock):
tasks.check_all_remote_instance_availability()
domain = models.Domain.objects.get(name=domain.name)
assert domain.reachable is False
def test_check_all_remote_instance_skips_local(settings, factories, r_mock):
domain = factories["federation.Domain"]()
settings.FUNKWHALE_HOSTNAME = domain.name
tasks.check_all_remote_instance_availability()
assert not r_mock.called

1411
docs/poetry.lock wygenerowano

Plik diff jest za duży Load Diff

Wyświetl plik

@ -41,6 +41,7 @@ admin/commands.html, ../administrator/manage-script/index.html
admin/mrf.html, ../administrator/configuration/mrf.html
admin/url.html, ../administrator/configuration/change-url.html
admin/optimization.html, ../administrator/configuration/optimize.html
admin/upgrading.html, ../administrator/upgrade/index.html
architecture.html, ../developer/architecture.html
contributing.html, ../developer/index.html
api.html, ../developer/api/index.html
@ -53,3 +54,6 @@ translators.html, ../contributor/translation.html
federation.html, ../developer/federation/index.html
upgrading.html, ../administrator/upgrade/index.html
administrator_documentation/upgrade_docs/docker.html, ../../administrator/upgrade/docker.html
upgrading/0.17.html, ../user/libraries/index.html
admin/external-storages.html, ../../administrator/configuration/object-storage.html
admin/external-storage.html#no-resolver-found, ../../administrator/configuration/object-storage.html#troubleshooting

Wyświetl plik

@ -26,6 +26,9 @@ module.exports = {
// NOTE: Nicer for the eye
'operator-linebreak': ['error', 'before'],
// NOTE: We have a logger instance
'no-console': 'error',
// NOTE: Handled by typescript
'@typescript-eslint/no-unused-vars': 'off',
'no-use-before-define': 'off',

Wyświetl plik

@ -20,26 +20,25 @@
"@sentry/tracing": "7.47.0",
"@sentry/vue": "7.47.0",
"@vue/runtime-core": "3.3.2",
"@vueuse/core": "9.12.0",
"@vueuse/integrations": "9.12.0",
"@vueuse/math": "9.12.0",
"@vueuse/router": "9.12.0",
"@vueuse/core": "10.3.0",
"@vueuse/integrations": "10.3.0",
"@vueuse/math": "10.3.0",
"@vueuse/router": "10.3.0",
"axios": "1.2.3",
"axios-auth-refresh": "3.3.6",
"butterchurn": "3.0.0-beta.4",
"butterchurn-presets": "3.0.0-beta.4",
"diff": "5.1.0",
"dompurify": "2.4.5",
"dompurify": "2.4.7",
"focus-trap": "7.2.0",
"fomantic-ui-css": "2.9.2",
"howler": "2.2.3",
"idb-keyval": "6.2.1",
"js-logger": "1.6.1",
"lodash-es": "4.17.21",
"lru-cache": "7.14.1",
"moment": "2.29.4",
"showdown": "2.1.0",
"standardized-audio-context": "25.3.53",
"standardized-audio-context": "25.3.55",
"text-clipper": "2.2.0",
"transliteration": "2.3.5",
"universal-cookie": "4.0.4",
@ -50,7 +49,7 @@
"vue-upload-component": "3.1.8",
"vue-virtual-scroller": "2.0.0-beta.8",
"vue3-gettext": "2.3.4",
"vue3-lazyload": "0.3.6",
"vue3-lazyload": "0.3.8",
"vuedraggable": "4.1.0",
"vuex": "4.1.0",
"vuex-persistedstate": "4.1.0",
@ -72,6 +71,7 @@
"@typescript-eslint/eslint-plugin": "5.48.2",
"@vitejs/plugin-vue": "4.2.3",
"@vitest/coverage-c8": "0.25.8",
"@vue-macros/volar": "0.13.3",
"@vue/compiler-sfc": "3.3.2",
"@vue/eslint-config-standard": "8.0.1",
"@vue/eslint-config-typescript": "11.0.2",
@ -94,6 +94,7 @@
"sinon": "15.0.2",
"standardized-audio-context-mock": "9.6.18",
"typescript": "4.9.5",
"unplugin-vue-macros": "2.4.6",
"utility-types": "3.10.0",
"vite": "4.3.5",
"vite-plugin-pwa": "0.14.4",

Wyświetl plik

@ -267,7 +267,11 @@ REPLACEMENTS = {
("background", "var(--site-background)"),
("color", "var(--text-color)"),
],
("::-webkit-selection", "::-moz-selection", "::selection"): [
(
"::-webkit-selection",
"::-moz-selection",
"::selection",
): [
("color", "var(--text-selection-color)"),
("background-color", "var(--text-selection-background)"),
],
@ -448,7 +452,10 @@ REPLACEMENTS = {
): [
("color", "var(--input-focus-placeholder-color)"),
],
(".ui.form .field > label", ".ui.form .inline.fields .field > label"): [
(
".ui.form .field > label",
".ui.form .inline.fields .field > label",
): [
("color", "var(--form-label-color)"),
],
},
@ -779,7 +786,10 @@ REPLACEMENTS = {
".structured",
"tablet stackable",
],
(".ui.table", ".ui.table > thead > tr > th"): [
(
".ui.table",
".ui.table > thead > tr > th",
): [
("color", "var(--text-color)"),
("background", "var(--table-background)"),
],

Wyświetl plik

@ -4,6 +4,10 @@ import { createEventHook, refDefault, type EventHookOn, useEventListener } from
import { createAudioSource } from '~/composables/audio/audio-api'
import { effectScope, reactive, ref, type Ref } from 'vue'
import useLogger from '~/composables/useLogger'
const logger = useLogger()
export interface SoundSource {
uuid: string
mimetype: string
@ -73,7 +77,7 @@ export class HTMLSound implements Sound {
this.#audio.src = source
this.#audio.preload = 'auto'
console.log('CREATED SOUND INSTANCE', this)
logger.log('CREATED SOUND INSTANCE', this)
this.#scope.run(() => {
useEventListener(this.#audio, 'ended', () => this.#soundEndEventHook.trigger(this))
@ -84,19 +88,19 @@ export class HTMLSound implements Sound {
})
useEventListener(this.#audio, 'waiting', () => {
console.log('>> AUDIO WAITING', this)
logger.log('>> AUDIO WAITING', this)
})
useEventListener(this.#audio, 'playing', () => {
console.log('>> AUDIO PLAYING', this)
logger.log('>> AUDIO PLAYING', this)
})
useEventListener(this.#audio, 'stalled', () => {
console.log('>> AUDIO STALLED', this)
logger.log('>> AUDIO STALLED', this)
})
useEventListener(this.#audio, 'suspend', () => {
console.log('>> AUDIO SUSPEND', this)
logger.log('>> AUDIO SUSPEND', this)
})
useEventListener(this.#audio, 'loadeddata', () => {
@ -106,7 +110,7 @@ export class HTMLSound implements Sound {
useEventListener(this.#audio, 'error', (err) => {
if (this.#ignoreError) return
console.error('>> AUDIO ERRORED', err, this)
logger.error('>> AUDIO ERRORED', err, this)
this.isErrored.value = true
this.isLoaded.value = true
})
@ -116,7 +120,7 @@ export class HTMLSound implements Sound {
async preload () {
this.isDisposed.value = false
this.isErrored.value = false
console.log('CALLING PRELOAD ON', this)
logger.log('CALLING PRELOAD ON', this)
this.#audio.load()
}
@ -141,7 +145,7 @@ export class HTMLSound implements Sound {
try {
await this.#audio.play()
} catch (err) {
console.error('>> AUDIO PLAY ERROR', err, this)
logger.error('>> AUDIO PLAY ERROR', err, this)
this.isErrored.value = true
}
}

Wyświetl plik

@ -5,6 +5,7 @@ import ChannelsWidget from '~/components/audio/ChannelsWidget.vue'
import LoginForm from '~/components/auth/LoginForm.vue'
import SignupForm from '~/components/auth/SignupForm.vue'
import useMarkdown from '~/composables/useMarkdown'
import useLogger from '~/composables/useLogger'
import { humanSize } from '~/utils/filters'
import { useStore } from '~/store'
import { computed } from 'vue'
@ -18,6 +19,7 @@ const labels = computed(() => ({
}))
const store = useStore()
const logger = useLogger()
const nodeinfo = computed(() => store.state.instance.nodeinfo)
const podName = computed(() => get(nodeinfo.value, 'metadata.nodeName') || 'Funkwhale')
@ -54,7 +56,7 @@ const headerStyle = computed(() => {
// TODO (wvffle): Check if needed
const router = useRouter()
whenever(() => store.state.auth.authenticated, () => {
console.log('Authenticated, redirecting to /library…')
logger.log('Authenticated, redirecting to /library…')
router.push('/library')
})
</script>

Wyświetl plik

@ -9,6 +9,7 @@ import { useStore } from '~/store'
import axios from 'axios'
import updateQueryString from '~/composables/updateQueryString'
import useLogger from '~/composables/useLogger'
type Type = 'rss' | 'artists' | 'both'
@ -37,6 +38,7 @@ const type = ref(props.initialType)
const id = ref(props.initialId)
const errors = ref([] as string[])
const logger = useLogger()
const { t } = useI18n()
const labels = computed(() => ({
title: type.value === 'rss'
@ -102,7 +104,7 @@ const submit = () => {
const isLoading = ref(false)
const createFetch = async () => {
console.log(id.value, props.standalone)
logger.debug(id.value, props.standalone)
if (!id.value) return
if (props.standalone) {
history.replaceState(history.state, '', updateQueryString(location.href, 'id', id.value))

Wyświetl plik

@ -18,15 +18,16 @@ const values = reactive({} as Record<string, unknown | Form | string>)
const result = ref<boolean | null>(null)
const errors = ref([] as string[])
const fileRefs = reactive({} as Record<string, HTMLInputElement>)
const setFileRef = (identifier: string) => (el: FunctionRef) => {
console.log(el)
fileRefs[identifier] = el as HTMLInputElement
}
const logger = useLogger()
const store = useStore()
// TODO (wvffle): Use VueUse
const fileRefs = reactive({} as Record<string, HTMLInputElement>)
const setFileRef = (identifier: string) => (el: FunctionRef) => {
logger.debug(el)
fileRefs[identifier] = el as HTMLInputElement
}
const settings = computed(() => {
const byIdentifier = props.settingsData.reduce((acc, entry) => {
acc[entry.identifier] = entry

Wyświetl plik

@ -71,6 +71,7 @@ watch(page, fetchData, { immediate: true })
<podcast-table
v-if="isPodcast"
v-model:page="page"
:paginate-by="limit"
:default-cover="defaultCover"
:is-podcast="isPodcast"
:show-art="true"
@ -80,7 +81,6 @@ watch(page, fetchData, { immediate: true })
:show-album="false"
:paginate-results="true"
:total="count"
:paginate-by="limit"
/>
<track-table
v-else

Wyświetl plik

@ -13,6 +13,7 @@ import PlayButton from '~/components/audio/PlayButton.vue'
import useMarkdown from '~/composables/useMarkdown'
import usePlayOptions from '~/composables/audio/usePlayOptions'
import useErrorHandler from '~/composables/useErrorHandler'
import SanitizedHtml from '~/components/SanitizedHtml.vue'
interface Props extends PlayOptionsProps {
tracks: Track[]
@ -81,7 +82,7 @@ await fetchData()
@click.prevent.exact="activateTrack(track, index)"
>
<img
v-if="track.cover?.urls.original "
v-if="track.cover?.urls.original"
v-lazy="$store.getters['instance/absoluteUrl'](track.cover.urls.medium_square_crop)"
alt=""
class="ui artist-track mini image"
@ -111,7 +112,7 @@ await fetchData()
v-if="renderedDescription"
class="podcast-episode-meta"
>
{{ renderedDescription }}
<SanitizedHtml :html="renderedDescription" />
</p>
</div>
<div

Wyświetl plik

@ -16,7 +16,6 @@ interface Props {
isPodcast?: boolean
paginateResults?: boolean
paginateBy?: number
page?: number
total?: number
}
@ -30,9 +29,10 @@ withDefaults(defineProps<Props>(), {
isPodcast: true,
paginateResults: true,
paginateBy: 25,
page: 1,
total: 0
})
const { page } = defineModels<{ page: number, }>()
</script>
<template>
@ -44,9 +44,7 @@ withDefaults(defineProps<Props>(), {
<slot name="header" />
<div>
<div
:class="['track-table', 'ui', 'unstackable', 'grid', 'tablet-and-up']"
>
<div :class="['track-table', 'ui', 'unstackable', 'grid', 'tablet-and-up']">
<!-- For each item, build a row -->
<podcast-row
v-for="(track, index) in tracks"
@ -65,8 +63,8 @@ withDefaults(defineProps<Props>(), {
>
<pagination
v-bind="$attrs"
v-model:current="page"
:total="total"
:current="page"
:paginate-by="paginateBy"
/>
</div>
@ -95,8 +93,8 @@ withDefaults(defineProps<Props>(), {
<pagination
v-if="paginateResults"
v-bind="$attrs"
v-model:current="page"
:total="total"
:current="page"
:compact="true"
/>
</div>

Wyświetl plik

@ -9,6 +9,8 @@ import { useStore } from '~/store'
import ApplicationForm from '~/components/auth/ApplicationForm.vue'
import useLogger from '~/composables/useLogger'
interface Props {
name?: string
scopes?: string
@ -27,6 +29,7 @@ const defaults = reactive({
redirectUris: props.redirectUris
})
const logger = useLogger()
const { t } = useI18n()
const labels = computed(() => ({
title: t('components.auth.ApplicationNew.title')
@ -37,7 +40,7 @@ const store = useStore()
const created = (application: Application) => {
store.state.auth.applicationSecret = application.client_secret
console.log(application)
logger.debug(application)
return router.push({
name: 'settings.applications.edit',
params: {

Wyświetl plik

@ -42,7 +42,7 @@ const labels = computed(() => ({
const signupRequiresApproval = computed(() => props.signupApprovalEnabled ?? store.state.instance.settings.moderation.signup_approval_enabled.value)
const formCustomization = computed(() => props.customization ?? store.state.instance.settings.moderation.signup_form_customization.value)
watchEffect(() => console.log(store.state.instance.settings.moderation.signup_approval_enabled.value))
watchEffect(() => logger.debug(store.state.instance.settings.moderation.signup_approval_enabled.value))
const payload = reactive({
username: '',

Wyświetl plik

@ -4,6 +4,8 @@ import { useVModel, watchDebounced, useTextareaAutosize, syncRef } from '@vueuse
import { ref, computed, watchEffect, onMounted, nextTick, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import useLogger from '~/composables/useLogger'
interface Events {
(e: 'update:modelValue', value: string): void
}
@ -26,6 +28,8 @@ const props = withDefaults(defineProps<Props>(), {
required: false
})
const logger = useLogger()
const { t } = useI18n()
const { textarea, input } = useTextareaAutosize()
const value = useVModel(props, 'modelValue', emit)
@ -47,7 +51,7 @@ const loadPreview = async () => {
const response = await axios.post('text-preview/', { text: value.value, permissive: props.permissive })
preview.value = response.data.rendered
} catch (error) {
console.error(error)
logger.error(error)
}
isLoadingPreview.value = false
}

Wyświetl plik

@ -64,8 +64,8 @@ const fetchFavorites = async () => {
ordering: orderingString.value
}
const measureLoading = logger.time('Loading user favorites')
try {
logger.time('Loading user favorites')
const response = await axios.get('tracks/', { params })
results.length = 0
@ -81,7 +81,7 @@ const fetchFavorites = async () => {
} catch (error) {
useErrorHandler(error as Error)
} finally {
logger.timeEnd('Loading user favorites')
measureLoading()
isLoading.value = false
}
}

Wyświetl plik

@ -15,6 +15,7 @@ import TagsList from '~/components/tags/List.vue'
import AlbumDropdown from './AlbumDropdown.vue'
import useErrorHandler from '~/composables/useErrorHandler'
import useLogger from '~/composables/useLogger'
interface Events {
(e: 'deleted'): void
@ -39,6 +40,8 @@ const isSerie = computed(() => object.value?.artist.content_category === 'podcas
const totalDuration = computed(() => sum((object.value?.tracks ?? []).map(track => track.uploads[0]?.duration ?? 0)))
const publicLibraries = computed(() => libraries.value?.filter(library => library.privacy_level === 'everyone') ?? [])
const logger = useLogger()
const { t } = useI18n()
const labels = computed(() => ({
title: t('components.library.AlbumBase.title')
@ -93,7 +96,7 @@ const fetchTracks = async () => {
tracks.push(...response.data.results)
}
} catch (error) {
console.error(error)
logger.error(error)
} finally {
isLoadingTracks.value = false
}

Wyświetl plik

@ -72,7 +72,7 @@ const fetchData = async () => {
content_category: 'music'
}
logger.time('Fetching albums')
const measureLoading = logger.time('Fetching albums')
try {
const response = await axios.get('albums/', {
params,
@ -86,7 +86,7 @@ const fetchData = async () => {
useErrorHandler(error as Error)
result.value = undefined
} finally {
logger.timeEnd('Fetching albums')
measureLoading()
isLoading.value = false
}
}

Wyświetl plik

@ -73,7 +73,7 @@ const fetchData = async () => {
has_albums: excludeCompilation.value
}
logger.time('Fetching artists')
const measureLoading = logger.time('Fetching artists')
try {
const response = await axios.get('artists/', {
params,
@ -87,7 +87,7 @@ const fetchData = async () => {
useErrorHandler(error as Error)
result.value = undefined
} finally {
logger.timeEnd('Fetching artists')
measureLoading()
isLoading.value = false
}
}

Wyświetl plik

@ -32,7 +32,7 @@ const labels = computed(() => ({
const isLoading = ref(false)
const fetchData = async () => {
isLoading.value = true
logger.time('Loading latest artists')
const measureLoading = logger.time('Loading latest artists')
const params = {
ordering: '-creation_date',
@ -47,7 +47,7 @@ const fetchData = async () => {
}
isLoading.value = false
logger.timeEnd('Loading latest artists')
measureLoading()
}
fetchData()

Wyświetl plik

@ -74,7 +74,7 @@ const fetchData = async () => {
content_category: 'podcast'
}
logger.time('Fetching podcasts')
const measureLoading = logger.time('Fetching podcasts')
try {
const response = await axios.get('artists/', {
params,
@ -88,7 +88,7 @@ const fetchData = async () => {
useErrorHandler(error as Error)
result.value = undefined
} finally {
logger.timeEnd('Fetching podcasts')
measureLoading()
isLoading.value = false
}
}

Wyświetl plik

@ -64,7 +64,7 @@ const fetchData = async () => {
ordering: orderingString.value
}
logger.time('Fetching radios')
const measureLoading = logger.time('Fetching radios')
try {
const response = await axios.get('radios/radios/', {
params
@ -75,7 +75,7 @@ const fetchData = async () => {
useErrorHandler(error as Error)
result.value = undefined
} finally {
logger.timeEnd('Fetching radios')
measureLoading()
isLoading.value = false
}
}

Wyświetl plik

@ -15,6 +15,7 @@ import NoteForm from '~/components/manage/moderation/NoteForm.vue'
import useReportConfigs from '~/composables/moderation/useReportConfigs'
import useErrorHandler from '~/composables/useErrorHandler'
import useMarkdown from '~/composables/useMarkdown'
import useLogger from '~/composables/useLogger'
interface Events {
(e: 'updated', updating: { type: string }): void
@ -29,6 +30,7 @@ const emit = defineEmits<Events>()
const props = defineProps<Props>()
const configs = useReportConfigs()
const logger = useLogger()
const obj = ref(props.initObj)
const summary = useMarkdown(() => obj.value.summary ?? '')
@ -77,11 +79,11 @@ const actions = computed(() => {
handler: async () => {
try {
await axios.delete(deleteUrl)
console.log('Target deleted')
logger.info('Target deleted')
obj.value.target = undefined
resolveReport(true)
} catch (error) {
console.log('Error while deleting target', error)
logger.error('Error while deleting target', error)
useErrorHandler(error as Error)
}
}

Wyświetl plik

@ -9,6 +9,8 @@ import { useStore } from '~/store'
import axios from 'axios'
import { useClamp } from '@vueuse/math'
import useLogger from '~/composables/useLogger'
// Looping
export enum LoopingMode {
None,
@ -17,7 +19,6 @@ export enum LoopingMode {
}
// Pausing
export enum PauseReason {
UserInput,
EndOfQueue,
@ -26,6 +27,8 @@ export enum PauseReason {
EndOfRadio
}
const logger = useLogger()
const MODE_MAX = 1 + Math.max(...Object.values(LoopingMode).filter(mode => typeof mode === 'number') as number[])
export const looping: Ref<number> = useStorage('player:looping', LoopingMode.None)
@ -131,12 +134,12 @@ export const usePlayer = createGlobalState(() => {
const trackListenSubmissions = () => {
const store = useStore()
whenever(listenSubmitted, async () => {
console.log('Listening submitted!')
logger.log('Listening submitted!')
if (!store.state.auth.authenticated) return
if (!currentTrack.value) return
await axios.post('history/listenings/', { track: currentTrack.value.id })
.catch((error) => console.error('Could not record track in history', error))
.catch((error) => logger.error('Could not record track in history', error))
})
}

Wyświetl plik

@ -11,6 +11,8 @@ import { delMany, getMany, setMany } from '~/composables/data/indexedDB'
import { setGain } from '~/composables/audio/audio-api'
import { useTracks } from '~/composables/audio/tracks'
import useLogger from '~/composables/useLogger'
import axios from 'axios'
export interface QueueTrackSource {
@ -36,6 +38,8 @@ export interface QueueTrack {
sources: QueueTrackSource[]
}
const logger = useLogger()
// Queue
const tracks = useStorage('queue:tracks', [] as number[])
const shuffledIds = useStorage('queue:tracks:shuffled', [] as number[])
@ -69,7 +73,7 @@ watchEffect(async () => {
tracksById.set(track.id, track)
}
} catch (error) {
console.error(error)
logger.error(error)
} finally {
fetchingTracks.value = false
}
@ -329,6 +333,10 @@ export const useQueue = createGlobalState(() => {
clearRadio.value = true
const lastTracks = [...tracks.value]
// Clear shuffled tracks
shuffledIds.value.length = 0
tracks.value.length = 0
await delMany(lastTracks)
@ -340,7 +348,7 @@ export const useQueue = createGlobalState(() => {
const store = useStore()
watchEffect(() => {
if (store.state.radios.running && currentIndex.value === tracks.value.length - 1) {
console.log('POPULATING QUEUE FROM RADIO')
logger.log('POPULATING QUEUE FROM RADIO')
return store.dispatch('radios/populateQueue')
}
})
@ -375,7 +383,7 @@ export const useQueue = createGlobalState(() => {
currentIndex.value = index
delete localStorage.queue
})().catch((error) => console.error('Could not successfully migrate between queue versions', error))
})().catch((error) => logger.error('Could not successfully migrate between queue versions', error))
}
if (localStorage.player) {
@ -385,7 +393,7 @@ export const useQueue = createGlobalState(() => {
setGain(volume ?? 0.7)
delete localStorage.player
} catch (error) {
console.error('Could not successfully migrate between player versions', error)
logger.error('Could not successfully migrate between player versions', error)
}
}
}

Wyświetl plik

@ -11,6 +11,7 @@ import { useQueue } from '~/composables/audio/queue'
import { soundImplementation } from '~/api/player'
import useLRUCache from '~/composables/data/useLRUCache'
import useLogger from '~/composables/useLogger'
import store from '~/store'
import axios from 'axios'
@ -18,6 +19,8 @@ import axios from 'axios'
const ALLOWED_PLAY_TYPES: (CanPlayTypeResult | undefined)[] = ['maybe', 'probably']
const AUDIO_ELEMENT = document.createElement('audio')
const logger = useLogger()
const soundPromises = new Map<number, Promise<Sound>>()
const soundCache = useLRUCache<number, Sound>({
max: 3,
@ -95,7 +98,7 @@ export const useTracks = createGlobalState(() => {
const sound = new SoundImplementation(sources)
sound.onSoundEnd(() => {
console.log('TRACK ENDED, PLAYING NEXT')
logger.log('TRACK ENDED, PLAYING NEXT')
// NOTE: We push it to the end of the job queue
setTimeout(() => playNext(), 0)
@ -140,7 +143,7 @@ export const useTracks = createGlobalState(() => {
return sound
}
console.log('NO TRACK IN CACHE, CREATING', track)
logger.log('NO TRACK IN CACHE, CREATING', track)
const soundPromise = createSoundPromise()
soundPromises.set(track.id, soundPromise)
return soundPromise
@ -171,7 +174,7 @@ export const useTracks = createGlobalState(() => {
const { queue, currentIndex } = useQueue()
if (queue.value.length <= index || index === -1) return
console.log('LOADING TRACK', index)
logger.log('LOADING TRACK', index)
const track = queue.value[index]
const sound = await createSound(track)
@ -181,7 +184,7 @@ export const useTracks = createGlobalState(() => {
return
}
console.log('CONNECTING NODE', sound)
logger.log('CONNECTING NODE', sound)
sound.audioNode.disconnect()
connectAudioSource(sound.audioNode)

Wyświetl plik

@ -4,6 +4,8 @@ import { AUDIO_CONTEXT, GAIN_NODE } from './audio-api'
import { useResizeObserver, useStorage } from '@vueuse/core'
import { watchEffect, ref, markRaw } from 'vue'
import useLogger from '~/composables/useLogger'
// @ts-expect-error butterchurn has no typings
import butterchurnPresets from 'butterchurn-presets'
@ -11,6 +13,8 @@ import butterchurnPresets from 'butterchurn-presets'
import butterchurn from 'butterchurn'
export const useMilkDrop = (canvas: Ref<HTMLCanvasElement>) => {
const logger = useLogger()
const presets = Object.keys(butterchurnPresets)
const visualizer = ref()
@ -24,7 +28,7 @@ export const useMilkDrop = (canvas: Ref<HTMLCanvasElement>) => {
const name = presetName.value
if (name === undefined) return
console.log(`Switching to preset: '${name}'`)
logger.log(`Switching to preset: '${name}'`)
visualizer.value?.loadPreset(butterchurnPresets[name], 1)
})
@ -67,7 +71,7 @@ export const useMilkDrop = (canvas: Ref<HTMLCanvasElement>) => {
try {
visualizer.value?.render()
} catch (error) {
console.error(error)
logger.error(error)
loadRandomPreset()
}
}

Wyświetl plik

@ -3,71 +3,73 @@ import type { RouteRecordName } from 'vue-router'
import { toRefs, useStorage, syncRef } from '@vueuse/core'
import { useRouteQuery } from '@vueuse/router'
import { useRoute } from 'vue-router'
import { ref, watch } from 'vue'
import { watch, readonly } from 'vue'
export interface OrderingProps {
orderingConfigName?: RouteRecordName
}
export default (props: OrderingProps) => {
export default <T extends string = string>(props: OrderingProps) => {
const route = useRoute()
const preferences = useStorage(`route-preferences:${props.orderingConfigName?.toString() ?? route.name?.toString() ?? '*'}`, {
interface Preferences {
orderingDirection: '-' | '+'
ordering: T
paginateBy: number
}
const preferences = useStorage<Preferences>(`route-preferences:${props.orderingConfigName?.toString() ?? route.name?.toString() ?? '*'}`, () => ({
orderingDirection: route.meta.orderingDirection ?? '-',
ordering: route.meta.ordering ?? 'creation_date',
paginateBy: route.meta.paginateBy ?? 50
})
}))
const {
orderingDirection: perfOrderingDirection,
paginateBy: perfPaginateBy,
ordering: perfOrdering
} = toRefs(preferences)
const queryPaginateBy = useRouteQuery<string>('paginateBy', perfPaginateBy.value.toString())
const paginateBy = ref()
syncRef(queryPaginateBy, paginateBy, {
transform: {
ltr: (left) => +left,
rtl: (right) => right.toString()
}
orderingDirection: prefOrderingDirection,
paginateBy: prefPaginateBy,
ordering: prefOrdering
} = toRefs(preferences, {
replaceRef: false
})
const queryOrdering = useRouteQuery('ordering', perfOrderingDirection.value + perfOrdering.value)
console.log(queryOrdering.value)
const normalizeDirection = (direction: string) => direction === '+' ? '' : '-'
const queryOrdering = useRouteQuery(
'ordering',
normalizeDirection(prefOrderingDirection.value) + prefOrdering.value,
{ transform: (value) => value.trim() }
)
const queryPaginateBy = useRouteQuery('paginateBy', prefPaginateBy.value, {
transform: Number
})
// NOTE: Sync paginateBy in query string and preferences. We're using `flush: 'post'` to make sure that we sync after all updates are done
syncRef(queryPaginateBy, prefPaginateBy, {
flush: 'post'
})
// NOTE: Sync ordering from preferences to query string
watch([prefOrderingDirection, prefOrdering], () => {
queryOrdering.value = normalizeDirection(prefOrderingDirection.value) + prefOrdering.value.trim()
})
// NOTE: Sync ordering from query string to preferences
watch(queryOrdering, (ordering) => {
perfOrderingDirection.value = ordering[0] === '-' ? '-' : '+'
perfOrdering.value = ordering[0] === '-' || ordering[0] === '+'
? ordering.slice(1)
: ordering
prefOrderingDirection.value = ordering[0] === '-' ? '-' : '+'
prefOrdering.value = ordering.replace(/^[+-]/, '')
}, { immediate: true })
// NOTE: We're using `flush: 'post'` to make sure that the `onOrderingUpdate` callback is called after all updates are done
const onOrderingUpdate = (fn: () => void) => watch(preferences, fn, {
flush: 'post'
})
watch(perfOrderingDirection, (direction) => {
if (direction === '-') {
queryOrdering.value = direction + perfOrdering.value
return
}
queryOrdering.value = perfOrdering.value
})
watch(perfOrdering, (field) => {
const direction = perfOrderingDirection.value
queryOrdering.value = (direction === '-' ? '-' : '') + field
})
watch(queryPaginateBy, (paginateBy) => {
perfPaginateBy.value = +paginateBy
})
const onOrderingUpdate = (fn: () => void) => watch(preferences, fn)
return {
paginateBy,
ordering: perfOrdering,
orderingDirection: perfOrderingDirection,
orderingString: queryOrdering,
paginateBy: prefPaginateBy,
ordering: prefOrdering,
orderingDirection: prefOrderingDirection,
orderingString: readonly(queryOrdering),
onOrderingUpdate
}
}

Wyświetl plik

@ -2,6 +2,8 @@ import { DefaultMagicKeysAliasMap, tryOnScopeDispose, useEventListener } from '@
import { isEqual, isMatch } from 'lodash-es'
import { reactive } from 'vue'
import useLogger from './useLogger'
type KeyFilter = string | string[]
interface Entry {
@ -10,6 +12,7 @@ interface Entry {
__location?: string
}
const logger = useLogger()
const combinations = reactive(new Map())
const current = new Set()
@ -59,7 +62,7 @@ export default (key: KeyFilter, handler: () => unknown, prevent = false) => {
}
if (collisions.length) {
console.warn([
logger.warn([
'onKeyboardShortcut detected a possible collision in:',
`${entry.__location}: ${combination.join(' + ')}`,
...collisions

Wyświetl plik

@ -1,11 +1,112 @@
import Logger from 'js-logger'
type LogLevel = 'info' | 'warn' | 'error' | 'debug' | 'time'
Logger.useDefaults({
defaultLevel: import.meta.env.DEV
? Logger.DEBUG
: Logger.WARN
})
const LOG_LEVEL_LABELS: Record<LogLevel, string> = {
info: ' INFO',
warn: ' WARN',
error: 'ERROR',
debug: 'DEBUG',
time: ' TIME'
}
export default (logger?: string) => logger
? Logger.get(logger)
: Logger
const LOG_LEVEL_BACKGROUND: Record<LogLevel, string> = {
info: '#a6e22e',
warn: '#FF9800',
error: '#F44336',
debug: '#00BCD4',
time: '#00BCD4'
}
const LOG_LEVEL_COLOR: Record<LogLevel, string> = {
info: '#000',
warn: '#000',
error: '#fff',
debug: '#000',
time: '#000'
}
const TIMESTAMP_COLOR = '#9E9E9E'
const FILETYPE_BACKGROUND: Record<string, string> = {
js: '#f1e05a',
ts: '#2b7489',
vue: '#41b883',
html: '#e34c26',
default: '#ccc'
}
const FILETYPE_COLOR: Record<string, string> = {
js: '#000',
ts: '#fff',
vue: '#fff',
html: '#fff',
default: '#000'
}
const getFile = () => {
const { stack } = new Error()
const line = stack?.split('\n')[2] ?? ''
const [, method, url, lineNo] = line.match(/^(\w+)?(?:\/<)*@(.+?)(?:\?.*)?:(\d+):\d+$/) ?? []
const file = url.startsWith(location.origin) ? url.slice(location.origin.length) : url
return { method, file, lineNo }
}
// NOTE: We're pushing all logs to the end of the event loop
const createLoggerFn = (level: LogLevel) => {
// NOTE: We don't want to handle logs ourselves in tests
// eslint-disable-next-line no-console
if (import.meta.env.VITEST) return console[level]
return (...args: any[]) => {
const timestamp = new Date().toUTCString()
const { method, file, lineNo } = getFile()
const ext = file?.split('.').pop() ?? 'default'
// NOTE: Don't log time and debug in production
if (level === 'time' || level === 'debug') {
if (import.meta.env.PROD) return
}
// eslint-disable-next-line no-console
console[level === 'time' ? 'debug' : level](
'%c %c [%s] %c %s %c%s',
`background: ${LOG_LEVEL_BACKGROUND[level]};border-radius:1em`,
`color: ${TIMESTAMP_COLOR}`,
timestamp,
`background: ${LOG_LEVEL_BACKGROUND[level]}; color: ${LOG_LEVEL_COLOR[level]}; border-radius: 1em 0 0 1em`,
LOG_LEVEL_LABELS[level],
`background: ${FILETYPE_BACKGROUND[ext]}; color: ${FILETYPE_COLOR[ext]}; border-radius: 0 1em 1em 0`,
method !== undefined
? ` ${file}:${lineNo} ${method}() `
: ` ${file}:${lineNo} `,
...args
)
}
}
const infoLogger = createLoggerFn('info')
const warnLogger = createLoggerFn('warn')
const timeLogger = createLoggerFn('time')
const errorLogger = createLoggerFn('error')
const debugLogger = createLoggerFn('debug')
export const logger = {
log: infoLogger,
info: infoLogger,
warn: warnLogger,
error: errorLogger,
debug: debugLogger,
time: (label: string) => {
const now = performance.now()
timeLogger(`${label}: start`)
return () => {
const duration = performance.now() - now
timeLogger(`${label}: ${duration.toFixed(2)}ms`)
}
}
}
export default () => logger

Wyświetl plik

@ -1,12 +1,12 @@
import type { MaybeComputedRef } from '@vueuse/core'
import type { MaybeRefOrGetter } from '@vueuse/core'
import { resolveUnref } from '@vueuse/core'
import { toValue } from '@vueuse/core'
import { computed } from 'vue'
import showdown from 'showdown'
showdown.extension('openExternalInNewTab', {
type: 'output',
regex: /<a.+?href.+">/g,
regex: /<a.+?href.+?">/g,
replace (text: string) {
const matches = text.match(/href="(.+)">/) ?? []
@ -51,6 +51,6 @@ const markdown = new showdown.Converter({
})
export const useMarkdownRaw = (md: string) => markdown.makeHtml(md)
export const useMarkdownComputed = (md: MaybeComputedRef<string>) => computed(() => useMarkdownRaw(resolveUnref(md)))
export const useMarkdownComputed = (md: MaybeRefOrGetter<string>) => computed(() => useMarkdownRaw(toValue(md)))
export default useMarkdownComputed

Wyświetl plik

@ -118,7 +118,7 @@ export const install: InitModule = ({ store, router }) => {
const refreshAuth = async (failedRequest: AxiosError) => {
if (store.state.auth.oauth.accessToken) {
console.log('Failed request, refreshing auth…')
logger.warn('Failed request, refreshing auth…')
try {
// maybe the token was expired, let's try to refresh it

Wyświetl plik

@ -3,9 +3,12 @@ import type { InitModule } from '~/types'
import { watchEffect, watch } from 'vue'
import { useWebSocket, whenever } from '@vueuse/core'
import useWebSocketHandler from '~/composables/useWebSocketHandler'
import useLogger from '~/composables/useLogger'
import { CLIENT_RADIOS } from '~/utils/clientRadios'
export const install: InitModule = ({ store }) => {
const logger = useLogger()
watch(() => store.state.instance.instanceUrl, () => {
const url = store.getters['instance/absoluteUrl']('/api/v1/activity')
.replace(/^http/, 'ws')
@ -25,7 +28,7 @@ export const install: InitModule = ({ store }) => {
})
watchEffect(() => {
console.log('Websocket status:', status.value)
logger.log('Websocket status:', status.value)
})
}, { immediate: true })

Wyświetl plik

@ -1,4 +1,4 @@
import type { InitModule } from '~/types'
import type { InitModule, InitModuleContext } from '~/types'
import store, { key } from '~/store'
import router from '~/router'
@ -24,6 +24,7 @@ const app = createApp({
data: () => ({ ready: false }),
mounted () {
this.ready = true
logger.info('Everything loaded!')
},
render () {
if (this.ready) {
@ -37,19 +38,35 @@ const app = createApp({
app.use(router)
app.use(store, key)
const modules: Array<void | Promise<void>> = []
for (const module of Object.values(import.meta.glob('./init/*.ts', { eager: true })) as { install?: InitModule }[]) {
modules.push(module.install?.({
app,
router,
store
}))
const modules: Record<string | 'axios', { install?: InitModule }> = import.meta.glob('./init/*.ts', { eager: true })
const moduleContext: InitModuleContext = {
app,
router,
store
}
// Wait for all modules to load
Promise.all(modules).finally(() => {
app.mount('#app')
logger.info('Everything loaded!')
})
// NOTE: Other modules may depend on network requests and we need to ensure
// that all axios interceptors are set before any requests are made
// and that the instance url is set before any requests are made
const IMPORTANT_MODULES_QUEUE = ['axios', 'instance']
const waitForImportantModules = async () => {
for (const moduleName of IMPORTANT_MODULES_QUEUE) {
const path = `./init/${moduleName}.ts`
if (!(path in modules)) {
logger.error(`Failed to load important module: ${path}`)
continue
}
await modules[path].install?.(moduleContext)
delete modules[path]
}
}
waitForImportantModules()
// NOTE: We load the modules in parallel
.then(() => Promise.all(Object.values(modules).map(module => module.install?.(moduleContext))))
.catch(error => logger.error('Failed to load modules:', error))
// NOTE: We need to mount the app after all modules are loaded
.finally(() => app.mount('#app'))
// TODO (wvffle): Rename filters from useSharedLabels to filters from backend

Wyświetl plik

@ -1,20 +1,23 @@
import type { NavigationGuardNext, RouteLocationNamedRaw, RouteLocationNormalized } from 'vue-router'
import type { Permission } from '~/store/auth'
import useLogger from '~/composables/useLogger'
import store from '~/store'
const logger = useLogger()
export const hasPermissions = (permission: Permission) => (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
if (store.state.auth.authenticated && store.state.auth.availablePermissions[permission]) {
return next()
}
console.log('Not authenticated. Redirecting to library.')
logger.warn('Not authenticated. Redirecting to library.')
next({ name: 'library.index' })
}
export const requireLoggedIn = (fallbackLocation?: RouteLocationNamedRaw) => (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
if (store.state.auth.authenticated) return next()
console.log('!', to)
logger.debug('!', to)
return next(fallbackLocation ?? { name: 'login', query: { next: to.fullPath } })
}

Wyświetl plik

@ -168,7 +168,7 @@ const store: Module<State, RootState> = {
try {
await axios.post('users/logout')
} catch (error) {
console.log('Error while logging out, probably logged in via oauth')
logger.error('Error while logging out, probably logged in via oauth', error)
}
const modules = [
@ -249,11 +249,11 @@ const store: Module<State, RootState> = {
const redirectUri = encodeURIComponent(`${location.origin}/auth/callback`)
const params = `response_type=code&scope=${encodeURIComponent(NEEDED_SCOPES)}&redirect_uri=${redirectUri}&state=${next}&client_id=${state.oauth.clientId}`
const authorizeUrl = `${rootState.instance.instanceUrl}authorize?${params}`
console.log('Redirecting user...', authorizeUrl)
logger.log('Redirecting user...', authorizeUrl)
window.location.href = authorizeUrl
},
async handleOauthCallback ({ state, commit, dispatch }, authorizationCode) {
console.log('Fetching token...')
logger.log('Fetching token...')
const payload = {
client_id: state.oauth.clientId,
client_secret: state.oauth.clientSecret,

Wyświetl plik

@ -5,6 +5,8 @@ import type { SUPPORTED_LOCALES } from '~/init/locale'
import axios from 'axios'
import moment from 'moment'
import useLogger from '~/composables/useLogger'
type SupportedExtension = 'flac' | 'ogg' | 'mp3' | 'opus' | 'aac' | 'm4a' | 'aiff' | 'aif'
export type WebSocketEventName = 'inbox.item_added' | 'import.status_updated' | 'mutation.created' | 'mutation.updated'
@ -50,6 +52,8 @@ export interface State {
websocketEventsHandlers: Record<WebSocketEventName, WebSocketHandlers>
}
const logger = useLogger()
const store: Module<State, RootState> = {
namespaced: true,
state: {
@ -225,7 +229,9 @@ const store: Module<State, RootState> = {
commit('notifications', { type: 'pendingReviewRequests', count: response.data.count })
},
async currentLanguage ({ commit, rootState }, value) {
async currentLanguage ({ commit, rootState, state }, value) {
if (state.selectedLanguage && state.currentLanguage === value) return
commit('currentLanguage', value)
if (rootState.auth.authenticated) {
await axios.post('users/settings', { language: value })
@ -234,7 +240,7 @@ const store: Module<State, RootState> = {
websocketEvent ({ state }, event: WebSocketEvent) {
const handlers = state.websocketEventsHandlers[event.type]
console.log('Dispatching websocket event', event, handlers)
logger.log('Dispatching websocket event', event, handlers)
if (!handlers) {
return
}

Wyświetl plik

@ -19,6 +19,7 @@ import RadioCard from '~/components/radios/Card.vue'
import TagsList from '~/components/tags/List.vue'
import useErrorHandler from '~/composables/useErrorHandler'
import useLogger from '~/composables/useLogger'
type QueryType = 'artists' | 'albums' | 'tracks' | 'playlists' | 'tags' | 'radios' | 'podcasts' | 'series' | 'rss'
@ -35,6 +36,8 @@ syncRef(pageQuery, page, {
direction: 'both'
})
const logger = useLogger()
const q = useRouteQuery('q', '')
const query = ref(q.value)
syncRef(q, query, { direction: 'ltr' })
@ -209,8 +212,7 @@ const radioConfig = computed(() => {
} as RadioConfig
}
// TODO (wvffle): Use logger
console.info('This type is not yet supported for radio')
logger.warn('This type is not yet supported for radio')
}
return null

Wyświetl plik

@ -20,6 +20,7 @@ import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import usePage from '~/composables/navigation/usePage'
import useLogger from '~/composables/useLogger'
interface Props extends SmartSearchProps, OrderingProps {
mode?: 'card'
@ -37,6 +38,8 @@ const props = withDefaults(defineProps<Props>(), {
orderingConfigName: undefined
})
const logger = useLogger()
const search = ref()
const page = usePage()
@ -68,7 +71,7 @@ const fetchData = async () => {
result.value = response.data
if (query.value === 'resolved:no') {
console.log('Refreshing sidebar notifications')
logger.log('Refreshing sidebar notifications')
store.commit('ui/incrementNotifications', {
type: 'pendingReviewReports',
value: response.data.count

Wyświetl plik

@ -12,6 +12,7 @@ import RadioButton from '~/components/radios/Button.vue'
import useErrorHandler from '~/composables/useErrorHandler'
import useReport from '~/composables/moderation/useReport'
import useLogger from '~/composables/useLogger'
interface Emits {
(e: 'followed'): void
@ -31,6 +32,8 @@ const props = withDefaults(defineProps<Props>(), {
displayCopyFid: true
})
const logger = useLogger()
const { report, getReportableObjects } = useReport()
const store = useStore()
@ -80,7 +83,7 @@ const follow = async () => {
library.value.follow = response.data
emit('followed')
} catch (error) {
console.error(error)
logger.error(error)
store.commit('ui/addMessage', {
content: t('views.content.remote.Card.error.follow', { error }),
date: new Date()

Wyświetl plik

@ -65,7 +65,7 @@ const fetchData = async () => {
playable: true
}
logger.time('Fetching albums')
const measureLoading = logger.time('Fetching albums')
try {
const response = await axios.get('playlists/', {
params
@ -76,7 +76,7 @@ const fetchData = async () => {
useErrorHandler(error as Error)
result.value = undefined
} finally {
logger.timeEnd('Fetching albums')
measureLoading()
isLoading.value = false
}
}

Wyświetl plik

@ -0,0 +1,25 @@
import { useMarkdownRaw } from '~/composables/useMarkdown'
describe('useMarkdownRaw', () => {
describe('anchors', () => {
it('should add target="_blank" to external links', () => {
const html = useMarkdownRaw('https://open.audio')
expect(html).toBe('<p><a href="https://open.audio" target="_blank" rel="noopener noreferrer">https://open.audio</a></p>')
})
it('should not link raw path', () => {
const html = useMarkdownRaw('/library/tags')
expect(html).toBe('<p>/library/tags</p>')
})
it('should not add target="_blank" to internal links', () => {
const html = useMarkdownRaw('[/library/tags](/library/tags)')
expect(html).toBe('<p><a href="/library/tags">/library/tags</a></p>')
})
it('should handle multiple links', () => {
const html = useMarkdownRaw('https://open.audio https://funkwhale.audio')
expect(html).toBe('<p><a href="https://open.audio" target="_blank" rel="noopener noreferrer">https://open.audio</a> <a href="https://funkwhale.audio" target="_blank" rel="noopener noreferrer">https://funkwhale.audio</a></p>')
})
})
})

Wyświetl plik

@ -10,7 +10,8 @@
"vitest/globals",
"vite/client",
"vue/ref-macros",
"vite-plugin-pwa/client"
"vite-plugin-pwa/client",
"unplugin-vue-macros/macros-global"
],
"paths": {
"#/*": ["src/worker/*"],
@ -24,5 +25,17 @@
"src/**/*.vue",
"vite.config.ts",
"test/**/*.ts"
]
],
"vueCompilerOptions": {
"plugins": [
"@vue-macros/volar/define-options",
"@vue-macros/volar/define-models",
"@vue-macros/volar/define-props",
"@vue-macros/volar/define-props-refs",
"@vue-macros/volar/short-vmodel",
"@vue-macros/volar/define-slots",
"@vue-macros/volar/export-props",
"@vue-macros/volar/jsx-directive"
]
}
}

Wyświetl plik

@ -7,6 +7,7 @@ import manifest from './pwa-manifest.json'
import VueI18n from '@intlify/unplugin-vue-i18n/vite'
import Vue from '@vitejs/plugin-vue'
import VueMacros from 'unplugin-vue-macros/vite'
const port = +(process.env.VUE_PORT ?? 8080)
@ -15,8 +16,13 @@ const port = +(process.env.VUE_PORT ?? 8080)
export default defineConfig(({ mode }) => ({
envPrefix: ['VUE_', 'FUNKWHALE_SENTRY_'],
plugins: [
// https://github.com/vitejs/vite/tree/main/packages/plugin-vue
Vue(),
// https://vue-macros.sxzz.moe/
VueMacros({
plugins: {
// https://github.com/vitejs/vite/tree/main/packages/plugin-vue
vue: Vue(),
}
}),
// https://github.com/intlify/bundle-tools/tree/main/packages/vite-plugin-vue-i18n
VueI18n({
@ -51,6 +57,7 @@ export default defineConfig(({ mode }) => ({
}
},
build: {
sourcemap: true,
// https://rollupjs.org/configuration-options/
rollupOptions: {
output: {
@ -79,7 +86,7 @@ export default defineConfig(({ mode }) => ({
},
setupFiles: [
'./test/setup/mock-audio-context.ts',
'./test/setup/mock-vue-i18n.ts',
'./test/setup/mock-vue-i18n.ts'
]
}
}))

Plik diff jest za duży Load Diff