Compare commits

...

2 Commits
4.65.5 ... main

Author SHA1 Message Date
89fad50529 4.66.1
Some checks failed
Build-Release-Image / Build-Image (linux/arm64) (push) Failing after 7m6s
Build-Release-Image / Build-Image (linux/amd64) (push) Has been cancelled
Build-Release-Image / Merge-Images (push) Has been cancelled
Build-Release-Image / Create-Release (push) Has been cancelled
Build-Release-Image / Notify (push) Has been cancelled
2025-03-04 12:00:09 +00:00
d09b3b992c 4.66.0
Some checks failed
Build-Release-Image / Build-Image (linux/arm64) (push) Failing after 7m18s
Build-Release-Image / Build-Image (linux/amd64) (push) Has been cancelled
Build-Release-Image / Merge-Images (push) Has been cancelled
Build-Release-Image / Create-Release (push) Has been cancelled
Build-Release-Image / Notify (push) Has been cancelled
2025-03-03 12:00:09 +00:00
59 changed files with 836 additions and 575 deletions

View File

@ -27,11 +27,6 @@ jobs:
sudo apt update sudo apt update
sudo apt install -y libre2-dev libpq-dev sudo apt install -y libre2-dev libpq-dev
- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version-file: "pyproject.toml"
- name: Install dependencies - name: Install dependencies
if: steps.setup-uv.outputs.cache-hit != 'true' if: steps.setup-uv.outputs.cache-hit != 'true'
run: uv sync --locked --all-extras run: uv sync --locked --all-extras
@ -86,11 +81,6 @@ jobs:
sudo apt update sudo apt update
sudo apt install -y libre2-dev libpq-dev sudo apt install -y libre2-dev libpq-dev
- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version-file: "pyproject.toml"
- name: Install dependencies - name: Install dependencies
if: steps.setup-uv.outputs.cache-hit != 'true' if: steps.setup-uv.outputs.cache-hit != 'true'
run: uv sync --locked --all-extras run: uv sync --locked --all-extras

View File

@ -1 +1 @@
3.10.16 3.12.8

View File

@ -215,7 +215,7 @@ python email_handler.py
4) Send a test email 4) Send a test email
```bash ```bash
swaks --to e1@sl.local --from hey@google.com --server 127.0.0.1:20381 swaks --to e1@sl.lan --from hey@google.com --server 127.0.0.1:20381
``` ```
Now open http://localhost:1080/ (or http://localhost:1080/ for MailHog), you should see the forwarded email. Now open http://localhost:1080/ (or http://localhost:1080/ for MailHog), you should see the forwarded email.

View File

@ -1,7 +1,6 @@
import secrets import secrets
import string import string
import facebook
import google.oauth2.credentials import google.oauth2.credentials
import googleapiclient.discovery import googleapiclient.discovery
from flask import jsonify, request from flask import jsonify, request
@ -261,6 +260,8 @@ def auth_facebook():
} }
""" """
import facebook
data = request.get_json() data = request.get_json()
if not data: if not data:
return jsonify(error="request body cannot be empty"), 400 return jsonify(error="request body cannot be empty"), 400

View File

@ -2,7 +2,7 @@ from flask import jsonify, g
from sqlalchemy_utils.types.arrow import arrow from sqlalchemy_utils.types.arrow import arrow
from app.api.base import api_bp, require_api_sudo, require_api_auth from app.api.base import api_bp, require_api_sudo, require_api_auth
from app import config from app.constants import JobType
from app.extensions import limiter from app.extensions import limiter
from app.log import LOG from app.log import LOG
from app.models import Job, ApiToCookieToken from app.models import Job, ApiToCookieToken
@ -24,7 +24,7 @@ def delete_user():
) )
LOG.w("schedule delete account job for %s", g.user) LOG.w("schedule delete account job for %s", g.user)
Job.create( Job.create(
name=config.JOB_DELETE_ACCOUNT, name=JobType.DELETE_ACCOUNT.value,
payload={"user_id": g.user.id}, payload={"user_id": g.user.id},
run_at=arrow.now(), run_at=arrow.now(),
commit=True, commit=True,
@ -44,6 +44,8 @@ def get_api_session_token():
token: "asdli3ldq39h9hd3", token: "asdli3ldq39h9hd3",
} }
""" """
if not g.api_key:
return jsonify(ok=False), 401
token = ApiToCookieToken.create( token = ApiToCookieToken.create(
user=g.user, user=g.user,
api_key_id=g.api_key.id, api_key_id=g.api_key.id,

View File

@ -316,20 +316,6 @@ MFA_USER_ID = "mfa_user_id"
FLASK_PROFILER_PATH = os.environ.get("FLASK_PROFILER_PATH") FLASK_PROFILER_PATH = os.environ.get("FLASK_PROFILER_PATH")
FLASK_PROFILER_PASSWORD = os.environ.get("FLASK_PROFILER_PASSWORD") FLASK_PROFILER_PASSWORD = os.environ.get("FLASK_PROFILER_PASSWORD")
# Job names
JOB_ONBOARDING_1 = "onboarding-1"
JOB_ONBOARDING_2 = "onboarding-2"
JOB_ONBOARDING_3 = "onboarding-3"
JOB_ONBOARDING_4 = "onboarding-4"
JOB_BATCH_IMPORT = "batch-import"
JOB_DELETE_ACCOUNT = "delete-account"
JOB_DELETE_MAILBOX = "delete-mailbox"
JOB_DELETE_DOMAIN = "delete-domain"
JOB_SEND_USER_REPORT = "send-user-report"
JOB_SEND_PROTON_WELCOME_1 = "proton-welcome-1"
JOB_SEND_ALIAS_CREATION_EVENTS = "send-alias-creation-events"
JOB_SEND_EVENT_TO_WEBHOOK = "send-event-to-webhook"
# for pagination # for pagination
PAGE_LIMIT = 20 PAGE_LIMIT = 20

View File

@ -1,2 +1,18 @@
import enum
HEADER_ALLOW_API_COOKIES = "X-Sl-Allowcookies" HEADER_ALLOW_API_COOKIES = "X-Sl-Allowcookies"
DMARC_RECORD = "v=DMARC1; p=quarantine; pct=100; adkim=s; aspf=s" DMARC_RECORD = "v=DMARC1; p=quarantine; pct=100; adkim=s; aspf=s"
class JobType(enum.Enum):
ONBOARDING_1 = "onboarding-1"
ONBOARDING_2 = "onboarding-2"
ONBOARDING_4 = "onboarding-4"
BATCH_IMPORT = "batch-import"
DELETE_ACCOUNT = "delete-account"
DELETE_MAILBOX = "delete-mailbox"
DELETE_DOMAIN = "delete-domain"
SEND_USER_REPORT = "send-user-report"
SEND_PROTON_WELCOME_1 = "proton-welcome-1"
SEND_ALIAS_CREATION_EVENTS = "send-alias-creation-events"
SEND_EVENT_TO_WEBHOOK = "send-event-to-webhook"

View File

@ -5,7 +5,7 @@ from dataclasses import dataclass
from enum import Enum from enum import Enum
from typing import List, Optional from typing import List, Optional
from app.config import JOB_DELETE_DOMAIN from app.constants import JobType
from app.db import Session from app.db import Session
from app.email_utils import get_email_domain_part from app.email_utils import get_email_domain_part
from app.log import LOG from app.log import LOG
@ -156,7 +156,7 @@ def delete_custom_domain(domain: CustomDomain):
LOG.w("schedule delete domain job for %s", domain) LOG.w("schedule delete domain job for %s", domain)
domain.pending_deletion = True domain.pending_deletion = True
Job.create( Job.create(
name=JOB_DELETE_DOMAIN, name=JobType.DELETE_DOMAIN.value,
payload={"custom_domain_id": domain.id}, payload={"custom_domain_id": domain.id},
run_at=arrow.now(), run_at=arrow.now(),
commit=True, commit=True,

View File

@ -3,7 +3,7 @@ from flask import render_template, flash, request, redirect, url_for
from flask_login import login_required, current_user from flask_login import login_required, current_user
from app import s3 from app import s3
from app.config import JOB_BATCH_IMPORT from app.constants import JobType
from app.dashboard.base import dashboard_bp from app.dashboard.base import dashboard_bp
from app.dashboard.views.enter_sudo import sudo_required from app.dashboard.views.enter_sudo import sudo_required
from app.db import Session from app.db import Session
@ -64,7 +64,7 @@ def batch_import_route():
# Schedule batch import job # Schedule batch import job
Job.create( Job.create(
name=JOB_BATCH_IMPORT, name=JobType.BATCH_IMPORT.value,
payload={"batch_import_id": bi.id}, payload={"batch_import_id": bi.id},
run_at=arrow.now(), run_at=arrow.now(),
) )

View File

@ -3,7 +3,7 @@ from flask import flash, redirect, url_for, request, render_template
from flask_login import login_required, current_user from flask_login import login_required, current_user
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from app.config import JOB_DELETE_ACCOUNT from app.constants import JobType
from app.dashboard.base import dashboard_bp from app.dashboard.base import dashboard_bp
from app.dashboard.views.enter_sudo import sudo_required from app.dashboard.views.enter_sudo import sudo_required
from app.log import LOG from app.log import LOG
@ -40,7 +40,7 @@ def delete_account():
message=f"User {current_user.id} ({current_user.email}) marked for deletion via webapp", message=f"User {current_user.id} ({current_user.email}) marked for deletion via webapp",
) )
Job.create( Job.create(
name=JOB_DELETE_ACCOUNT, name=JobType.DELETE_ACCOUNT.value,
payload={"user_id": current_user.id}, payload={"user_id": current_user.id},
run_at=arrow.now(), run_at=arrow.now(),
commit=True, commit=True,

View File

@ -1,4 +1,5 @@
"""List of clients""" """List of clients"""
from flask import render_template from flask import render_template
from flask_login import current_user, login_required from flask_login import current_user, login_required

View File

@ -1,4 +1,5 @@
"""Email headers""" """Email headers"""
MESSAGE_ID = "Message-ID" MESSAGE_ID = "Message-ID"
IN_REPLY_TO = "In-Reply-To" IN_REPLY_TO = "In-Reply-To"
REFERENCES = "References" REFERENCES = "References"

View File

@ -1355,7 +1355,9 @@ def get_queue_id(msg: Message) -> Optional[str]:
search_result = re.search(r"with E?SMTP[AS]? id ([0-9a-zA-Z]{1,})", received_header) search_result = re.search(r"with E?SMTP[AS]? id ([0-9a-zA-Z]{1,})", received_header)
if search_result: if search_result:
return search_result.group(1) return search_result.group(1)
search_result = re.search("\(Postfix\)\r\n\tid ([a-zA-Z0-9]{1,});", received_header) search_result = re.search(
r"\(Postfix\)\r\n\tid ([a-zA-Z0-9]{1,});", received_header
)
if search_result: if search_result:
return search_result.group(1) return search_result.group(1)
return None return None

View File

@ -90,7 +90,7 @@ def fake_data():
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="hey@google.com", website_email="hey@google.com",
reply_email="rep@sl.local", reply_email="rep@sl.lan",
commit=True, commit=True,
) )
EmailLog.create( EmailLog.create(
@ -166,7 +166,7 @@ def fake_data():
# user_id=user.id, # user_id=user.id,
# alias_id=a.id, # alias_id=a.id,
# website_email=f"contact{i}@example.com", # website_email=f"contact{i}@example.com",
# reply_email=f"rep{i}@sl.local", # reply_email=f"rep{i}@sl.lan",
# ) # )
# Session.commit() # Session.commit()
# for _ in range(3): # for _ in range(3):

View File

@ -12,6 +12,7 @@ import arrow
import sqlalchemy import sqlalchemy
from app import config from app import config
from app.constants import JobType
from app.db import Session from app.db import Session
from app.email import headers from app.email import headers
from app.email_utils import ( from app.email_utils import (
@ -174,7 +175,7 @@ class ExportUserDataJob:
jobs_in_db = ( jobs_in_db = (
Session.query(Job) Session.query(Job)
.filter( .filter(
Job.name == config.JOB_SEND_USER_REPORT, Job.name == JobType.SEND_USER_REPORT.value,
Job.payload.op("->")("user_id").cast(sqlalchemy.TEXT) Job.payload.op("->")("user_id").cast(sqlalchemy.TEXT)
== str(self._user.id), == str(self._user.id),
Job.taken.is_(False), Job.taken.is_(False),
@ -184,7 +185,7 @@ class ExportUserDataJob:
if jobs_in_db > 0: if jobs_in_db > 0:
return None return None
return Job.create( return Job.create(
name=config.JOB_SEND_USER_REPORT, name=JobType.SEND_USER_REPORT.value,
payload={"user_id": self._user.id}, payload={"user_id": self._user.id},
run_at=arrow.now(), run_at=arrow.now(),
commit=True, commit=True,

View File

@ -5,7 +5,7 @@ from typing import Optional
import arrow import arrow
from app import config from app.constants import JobType
from app.errors import ProtonPartnerNotSetUp from app.errors import ProtonPartnerNotSetUp
from app.events.generated import event_pb2 from app.events.generated import event_pb2
from app.events.generated.event_pb2 import EventContent from app.events.generated.event_pb2 import EventContent
@ -57,14 +57,16 @@ class SendEventToWebhookJob:
return SendEventToWebhookJob(user=user, event=event) return SendEventToWebhookJob(user=user, event=event)
def store_job_in_db(self, run_at: Optional[arrow.Arrow]) -> Job: def store_job_in_db(
self, run_at: Optional[arrow.Arrow], commit: bool = True
) -> Job:
stub = self._event.SerializeToString() stub = self._event.SerializeToString()
return Job.create( return Job.create(
name=config.JOB_SEND_EVENT_TO_WEBHOOK, name=JobType.SEND_EVENT_TO_WEBHOOK.value,
payload={ payload={
"user_id": self._user.id, "user_id": self._user.id,
"event": base64.b64encode(stub).decode("utf-8"), "event": base64.b64encode(stub).decode("utf-8"),
}, },
run_at=run_at if run_at is not None else arrow.now(), run_at=run_at if run_at is not None else arrow.now(),
commit=True, commit=commit,
) )

View File

@ -7,7 +7,7 @@ import arrow
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from app import config from app import config
from app.config import JOB_DELETE_MAILBOX from app.constants import JobType
from app.db import Session from app.db import Session
from app.email_utils import ( from app.email_utils import (
mailbox_already_used, mailbox_already_used,
@ -156,7 +156,7 @@ def delete_mailbox(
f"User {user} has scheduled delete mailbox job for {mailbox.id} with transfer to mailbox {transfer_mailbox_id}" f"User {user} has scheduled delete mailbox job for {mailbox.id} with transfer to mailbox {transfer_mailbox_id}"
) )
Job.create( Job.create(
name=JOB_DELETE_MAILBOX, name=JobType.DELETE_MAILBOX.value,
payload={ payload={
"mailbox_id": mailbox.id, "mailbox_id": mailbox.id,
"transfer_mailbox_id": transfer_mailbox_id "transfer_mailbox_id": transfer_mailbox_id

View File

@ -30,6 +30,7 @@ from sqlalchemy_utils import ArrowType
from app import config, rate_limiter from app import config, rate_limiter
from app import s3 from app import s3
from app.constants import JobType
from app.db import Session from app.db import Session
from app.dns_utils import get_mx_domains from app.dns_utils import get_mx_domains
from app.errors import ( from app.errors import (
@ -275,6 +276,12 @@ class AliasDeleteReason(EnumE):
CustomDomainDeleted = 5 CustomDomainDeleted = 5
class JobPriority(EnumE):
Low = 1
Default = 50
High = 100
class IntEnumType(sa.types.TypeDecorator): class IntEnumType(sa.types.TypeDecorator):
impl = sa.Integer impl = sa.Integer
@ -650,7 +657,7 @@ class User(Base, ModelMixin, UserMixin, PasswordOracle):
user.notification = False user.notification = False
user.trial_end = None user.trial_end = None
Job.create( Job.create(
name=config.JOB_SEND_PROTON_WELCOME_1, name=JobType.SEND_PROTON_WELCOME_1.value,
payload={"user_id": user.id}, payload={"user_id": user.id},
run_at=arrow.now(), run_at=arrow.now(),
) )
@ -676,17 +683,17 @@ class User(Base, ModelMixin, UserMixin, PasswordOracle):
# Schedule onboarding emails # Schedule onboarding emails
Job.create( Job.create(
name=config.JOB_ONBOARDING_1, name=JobType.ONBOARDING_1.value,
payload={"user_id": user.id}, payload={"user_id": user.id},
run_at=arrow.now().shift(days=1), run_at=arrow.now().shift(days=1),
) )
Job.create( Job.create(
name=config.JOB_ONBOARDING_2, name=JobType.ONBOARDING_2.value,
payload={"user_id": user.id}, payload={"user_id": user.id},
run_at=arrow.now().shift(days=2), run_at=arrow.now().shift(days=2),
) )
Job.create( Job.create(
name=config.JOB_ONBOARDING_4, name=JobType.ONBOARDING_4.value,
payload={"user_id": user.id}, payload={"user_id": user.id},
run_at=arrow.now().shift(days=3), run_at=arrow.now().shift(days=3),
) )
@ -2772,8 +2779,16 @@ class Job(Base, ModelMixin):
) )
attempts = sa.Column(sa.Integer, nullable=False, server_default="0", default=0) attempts = sa.Column(sa.Integer, nullable=False, server_default="0", default=0)
taken_at = sa.Column(ArrowType, nullable=True) taken_at = sa.Column(ArrowType, nullable=True)
priority = sa.Column(
IntEnumType(JobPriority),
default=JobPriority.Default,
server_default=str(JobPriority.Default.value),
nullable=False,
)
__table_args__ = (Index("ix_state_run_at_taken_at", state, run_at, taken_at),) __table_args__ = (
Index("ix_state_run_at_taken_at_priority", state, run_at, taken_at, priority),
)
def __repr__(self): def __repr__(self):
return f"<Job {self.id} {self.name} {self.payload}>" return f"<Job {self.id} {self.name} {self.payload}>"

View File

@ -3,7 +3,7 @@ from typing import Optional
import arrow import arrow
from arrow import Arrow from arrow import Arrow
from app import config from app.constants import JobType
from app.models import PartnerUser, PartnerSubscription, User, Job from app.models import PartnerUser, PartnerSubscription, User, Job
from app.user_audit_log_utils import emit_user_audit_log, UserAuditLogAction from app.user_audit_log_utils import emit_user_audit_log, UserAuditLogAction
@ -18,7 +18,7 @@ def create_partner_user(
external_user_id=external_user_id, external_user_id=external_user_id,
) )
Job.create( Job.create(
name=config.JOB_SEND_ALIAS_CREATION_EVENTS, name=JobType.SEND_ALIAS_CREATION_EVENTS.value,
payload={"user_id": user.id}, payload={"user_id": user.id},
run_at=arrow.now(), run_at=arrow.now(),
) )

View File

@ -1,6 +1,7 @@
"""Inspired from """Inspired from
https://github.com/petermat/spamassassin_client https://github.com/petermat/spamassassin_client
""" """
import logging import logging
import socket import socket
from io import BytesIO from io import BytesIO

View File

@ -369,8 +369,8 @@ For ex:
"is_premium": false "is_premium": false
}, },
{ {
"signed_suffix": ".yeah@sl.local.X6_7OQ.i8XL4xsMsn7dxDEWU8eF-Zap0qo", "signed_suffix": ".yeah@sl.lan.X6_7OQ.i8XL4xsMsn7dxDEWU8eF-Zap0qo",
"suffix": ".yeah@sl.local", "suffix": ".yeah@sl.lan",
"is_custom": true, "is_custom": true,
"is_premium": false "is_premium": false
} }
@ -465,7 +465,7 @@ Here's an example:
{ {
"creation_date": "2020-04-06 17:57:14+00:00", "creation_date": "2020-04-06 17:57:14+00:00",
"creation_timestamp": 1586195834, "creation_timestamp": 1586195834,
"email": "prefix1.cat@sl.local", "email": "prefix1.cat@sl.lan",
"name": "A Name", "name": "A Name",
"enabled": true, "enabled": true,
"id": 3, "id": 3,
@ -518,7 +518,7 @@ Alias info, use the same format as in /api/v2/aliases. For example:
{ {
"creation_date": "2020-04-06 17:57:14+00:00", "creation_date": "2020-04-06 17:57:14+00:00",
"creation_timestamp": 1586195834, "creation_timestamp": 1586195834,
"email": "prefix1.cat@sl.local", "email": "prefix1.cat@sl.lan",
"name": "A Name", "name": "A Name",
"enabled": true, "enabled": true,
"id": 3, "id": 3,
@ -608,7 +608,7 @@ If success, 200 with the list of activities, for example:
"activities": [ "activities": [
{ {
"action": "reply", "action": "reply",
"from": "yes_meo_chat@sl.local", "from": "yes_meo_chat@sl.lan",
"timestamp": 1580903760, "timestamp": 1580903760,
"to": "marketing@example.com", "to": "marketing@example.com",
"reverse_alias": "\"marketing at example.com\" <reply@a.b>", "reverse_alias": "\"marketing at example.com\" <reply@a.b>",
@ -703,7 +703,7 @@ Return 200 and `existed=true` if contact is already added.
"creation_timestamp": 1584186761, "creation_timestamp": 1584186761,
"last_email_sent_date": null, "last_email_sent_date": null,
"last_email_sent_timestamp": null, "last_email_sent_timestamp": null,
"reverse_alias": "First Last first@example.com <ra+qytyzjhrumrreuszrbjxqjlkh@sl.local>", "reverse_alias": "First Last first@example.com <ra+qytyzjhrumrreuszrbjxqjlkh@sl.lan>",
"reverse_alias_address": "reply+bzvpazcdedcgcpztehxzgjgzmxskqa@sl.co", "reverse_alias_address": "reply+bzvpazcdedcgcpztehxzgjgzmxskqa@sl.co",
"existed": false "existed": false
} }
@ -992,7 +992,7 @@ Return user setting.
{ {
"alias_generator": "word", "alias_generator": "word",
"notification": true, "notification": true,
"random_alias_default_domain": "sl.local", "random_alias_default_domain": "sl.lan",
"sender_format": "AT", "sender_format": "AT",
"random_alias_suffix": "random_string" "random_alias_suffix": "random_string"
} }
@ -1029,7 +1029,7 @@ Return domains that user can use to create random alias
"is_custom": false "is_custom": false
}, },
{ {
"domain": "sl.local", "domain": "sl.lan",
"is_custom": false "is_custom": false
}, },
{ {

View File

@ -30,6 +30,7 @@ It should contain the following info:
""" """
import argparse import argparse
import email import email
import time import time
@ -1668,7 +1669,7 @@ def handle_bounce_reply_phase(envelope, msg: Message, email_log: EmailLog):
) )
Notification.create( Notification.create(
user_id=user.id, user_id=user.id,
title=f"Email cannot be sent to { contact.email } from your alias { alias.email }", title=f"Email cannot be sent to {contact.email} from your alias {alias.email}",
message=Notification.render( message=Notification.render(
"notification/bounce-reply-phase.html", "notification/bounce-reply-phase.html",
alias=alias, alias=alias,
@ -1681,7 +1682,7 @@ def handle_bounce_reply_phase(envelope, msg: Message, email_log: EmailLog):
user, user,
ALERT_BOUNCE_EMAIL_REPLY_PHASE, ALERT_BOUNCE_EMAIL_REPLY_PHASE,
mailbox.email, mailbox.email,
f"Email cannot be sent to { contact.email } from your alias { alias.email }", f"Email cannot be sent to {contact.email} from your alias {alias.email}",
render( render(
"transactional/bounce/bounce-email-reply-phase.txt", "transactional/bounce/bounce-email-reply-phase.txt",
user=user, user=user,

View File

@ -19,7 +19,7 @@ URL=http://localhost:7777
NOT_SEND_EMAIL=true NOT_SEND_EMAIL=true
# domain used to create alias # domain used to create alias
EMAIL_DOMAIN=sl.local EMAIL_DOMAIN=sl.lan
# Allow SimpleLogin to enforce SPF by using the extra headers from postfix # Allow SimpleLogin to enforce SPF by using the extra headers from postfix
# ENFORCE_SPF=true # ENFORCE_SPF=true
@ -37,18 +37,18 @@ EMAIL_DOMAIN=sl.local
# FIRST_ALIAS_DOMAIN = another-domain.com # FIRST_ALIAS_DOMAIN = another-domain.com
# transactional email is sent from this email address # transactional email is sent from this email address
SUPPORT_EMAIL=support@sl.local SUPPORT_EMAIL=support@sl.lan
SUPPORT_NAME=Son from SimpleLogin SUPPORT_NAME=Son from SimpleLogin
# To use VERP # To use VERP
# prefix must end with + and suffix must start with + # prefix must end with + and suffix must start with +
# BOUNCE_PREFIX = "bounces+" # BOUNCE_PREFIX = "bounces+"
# BOUNCE_SUFFIX = "+@sl.local" # BOUNCE_SUFFIX = "+@sl.lan"
# same as BOUNCE_PREFIX but used for reply phase. Note it doesn't have the plus sign (+) at the end. # same as BOUNCE_PREFIX but used for reply phase. Note it doesn't have the plus sign (+) at the end.
# BOUNCE_PREFIX_FOR_REPLY_PHASE = "bounce_reply" # BOUNCE_PREFIX_FOR_REPLY_PHASE = "bounce_reply"
# to receive general stats. # to receive general stats.
# ADMIN_EMAIL=admin@sl.local # ADMIN_EMAIL=admin@sl.lan
# Max number emails user can generate for free plan # Max number emails user can generate for free plan
# Set to 5 by default # Set to 5 by default

View File

@ -2,13 +2,18 @@
Run scheduled jobs. Run scheduled jobs.
Not meant for running job at precise time (+- 1h) Not meant for running job at precise time (+- 1h)
""" """
import time import time
from typing import List, Optional from typing import List, Optional
import arrow import arrow
import newrelic.agent
from sqlalchemy.orm import Query
from sqlalchemy.orm.exc import ObjectDeletedError
from sqlalchemy.sql.expression import or_, and_ from sqlalchemy.sql.expression import or_, and_
from app import config from app import config
from app.constants import JobType
from app.db import Session from app.db import Session
from app.email_utils import ( from app.email_utils import (
send_email, send_email,
@ -23,8 +28,11 @@ from app.log import LOG
from app.models import User, Job, BatchImport, Mailbox, CustomDomain, JobState from app.models import User, Job, BatchImport, Mailbox, CustomDomain, JobState
from app.monitor_utils import send_version_event from app.monitor_utils import send_version_event
from app.user_audit_log_utils import emit_user_audit_log, UserAuditLogAction from app.user_audit_log_utils import emit_user_audit_log, UserAuditLogAction
from events.event_sink import HttpEventSink
from server import create_light_app from server import create_light_app
_MAX_JOBS_PER_BATCH = 50
def onboarding_send_from_alias(user): def onboarding_send_from_alias(user):
comm_email, unsubscribe_link, via_email = user.get_communication_email() comm_email, unsubscribe_link, via_email = user.get_communication_email()
@ -191,7 +199,7 @@ SimpleLogin team.
def process_job(job: Job): def process_job(job: Job):
send_version_event("job_runner") send_version_event("job_runner")
if job.name == config.JOB_ONBOARDING_1: if job.name == JobType.ONBOARDING_1.value:
user_id = job.payload.get("user_id") user_id = job.payload.get("user_id")
user = User.get(user_id) user = User.get(user_id)
@ -200,7 +208,7 @@ def process_job(job: Job):
if user and user.notification and user.activated: if user and user.notification and user.activated:
LOG.d("send onboarding send-from-alias email to user %s", user) LOG.d("send onboarding send-from-alias email to user %s", user)
onboarding_send_from_alias(user) onboarding_send_from_alias(user)
elif job.name == config.JOB_ONBOARDING_2: elif job.name == JobType.ONBOARDING_2.value:
user_id = job.payload.get("user_id") user_id = job.payload.get("user_id")
user = User.get(user_id) user = User.get(user_id)
@ -209,7 +217,7 @@ def process_job(job: Job):
if user and user.notification and user.activated: if user and user.notification and user.activated:
LOG.d("send onboarding mailbox email to user %s", user) LOG.d("send onboarding mailbox email to user %s", user)
onboarding_mailbox(user) onboarding_mailbox(user)
elif job.name == config.JOB_ONBOARDING_4: elif job.name == JobType.ONBOARDING_4.value:
user_id = job.payload.get("user_id") user_id = job.payload.get("user_id")
user: User = User.get(user_id) user: User = User.get(user_id)
@ -224,11 +232,11 @@ def process_job(job: Job):
LOG.d("send onboarding pgp email to user %s", user) LOG.d("send onboarding pgp email to user %s", user)
onboarding_pgp(user) onboarding_pgp(user)
elif job.name == config.JOB_BATCH_IMPORT: elif job.name == JobType.BATCH_IMPORT.value:
batch_import_id = job.payload.get("batch_import_id") batch_import_id = job.payload.get("batch_import_id")
batch_import = BatchImport.get(batch_import_id) batch_import = BatchImport.get(batch_import_id)
handle_batch_import(batch_import) handle_batch_import(batch_import)
elif job.name == config.JOB_DELETE_ACCOUNT: elif job.name == JobType.DELETE_ACCOUNT.value:
user_id = job.payload.get("user_id") user_id = job.payload.get("user_id")
user = User.get(user_id) user = User.get(user_id)
@ -247,10 +255,10 @@ def process_job(job: Job):
) )
User.delete(user.id) User.delete(user.id)
Session.commit() Session.commit()
elif job.name == config.JOB_DELETE_MAILBOX: elif job.name == JobType.DELETE_MAILBOX.value:
delete_mailbox_job(job) delete_mailbox_job(job)
elif job.name == config.JOB_DELETE_DOMAIN: elif job.name == JobType.DELETE_DOMAIN.value:
custom_domain_id = job.payload.get("custom_domain_id") custom_domain_id = job.payload.get("custom_domain_id")
custom_domain: Optional[CustomDomain] = CustomDomain.get(custom_domain_id) custom_domain: Optional[CustomDomain] = CustomDomain.get(custom_domain_id)
if not custom_domain: if not custom_domain:
@ -287,17 +295,17 @@ def process_job(job: Job):
""", """,
retries=3, retries=3,
) )
elif job.name == config.JOB_SEND_USER_REPORT: elif job.name == JobType.SEND_USER_REPORT.value:
export_job = ExportUserDataJob.create_from_job(job) export_job = ExportUserDataJob.create_from_job(job)
if export_job: if export_job:
export_job.run() export_job.run()
elif job.name == config.JOB_SEND_PROTON_WELCOME_1: elif job.name == JobType.SEND_PROTON_WELCOME_1.value:
user_id = job.payload.get("user_id") user_id = job.payload.get("user_id")
user = User.get(user_id) user = User.get(user_id)
if user and user.activated: if user and user.activated:
LOG.d("Send proton welcome email to user %s", user) LOG.d("Send proton welcome email to user %s", user)
welcome_proton(user) welcome_proton(user)
elif job.name == config.JOB_SEND_ALIAS_CREATION_EVENTS: elif job.name == JobType.SEND_ALIAS_CREATION_EVENTS.value:
user_id = job.payload.get("user_id") user_id = job.payload.get("user_id")
user = User.get(user_id) user = User.get(user_id)
if user and user.activated: if user and user.activated:
@ -305,34 +313,68 @@ def process_job(job: Job):
send_alias_creation_events_for_user( send_alias_creation_events_for_user(
user, dispatcher=PostgresDispatcher.get() user, dispatcher=PostgresDispatcher.get()
) )
elif job.name == config.JOB_SEND_EVENT_TO_WEBHOOK: elif job.name == JobType.SEND_EVENT_TO_WEBHOOK.value:
send_job = SendEventToWebhookJob.create_from_job(job) send_job = SendEventToWebhookJob.create_from_job(job)
if send_job: if send_job:
send_job.run() send_job.run(HttpEventSink())
else: else:
LOG.e("Unknown job name %s", job.name) LOG.e("Unknown job name %s", job.name)
def get_jobs_to_run() -> List[Job]: def get_jobs_to_run_query(taken_before_time: arrow.Arrow) -> Query:
# Get jobs that match all conditions: # Get jobs that match all conditions:
# - Job.state == ready OR (Job.state == taken AND Job.taken_at < now - 30 mins AND Job.attempts < 5) # - Job.state == ready OR (Job.state == taken AND Job.taken_at < now - 30 mins AND Job.attempts < 5)
# - Job.run_at is Null OR Job.run_at < now + 10 mins # - Job.run_at is Null OR Job.run_at < now + 10 mins
taken_at_earliest = arrow.now().shift(minutes=-config.JOB_TAKEN_RETRY_WAIT_MINS)
run_at_earliest = arrow.now().shift(minutes=+10) run_at_earliest = arrow.now().shift(minutes=+10)
query = Job.filter( return Job.filter(
and_( and_(
or_( or_(
Job.state == JobState.ready.value, Job.state == JobState.ready.value,
and_( and_(
Job.state == JobState.taken.value, Job.state == JobState.taken.value,
Job.taken_at < taken_at_earliest, Job.taken_at < taken_before_time,
Job.attempts < config.JOB_MAX_ATTEMPTS, Job.attempts < config.JOB_MAX_ATTEMPTS,
), ),
), ),
or_(Job.run_at.is_(None), and_(Job.run_at <= run_at_earliest)), or_(Job.run_at.is_(None), and_(Job.run_at <= run_at_earliest)),
) )
) )
return query.all()
def get_jobs_to_run(taken_before_time: arrow.Arrow) -> List[Job]:
query = get_jobs_to_run_query(taken_before_time)
return (
query.order_by(Job.priority.desc())
.order_by(Job.run_at.asc())
.limit(_MAX_JOBS_PER_BATCH)
.all()
)
def take_job(job: Job, taken_before_time: arrow.Arrow) -> bool:
sql = """
UPDATE job
SET
taken_at = :taken_time,
attempts = attempts + 1,
state = :taken_state
WHERE id = :job_id
AND (state = :ready_state OR (state=:taken_state AND taken_at < :taken_before_time))
"""
args = {
"taken_time": arrow.now().datetime,
"job_id": job.id,
"ready_state": JobState.ready.value,
"taken_state": JobState.taken.value,
"taken_before_time": taken_before_time.datetime,
}
try:
res = Session.execute(sql, args)
Session.commit()
except ObjectDeletedError:
return False
return res.rowcount > 0
if __name__ == "__main__": if __name__ == "__main__":
@ -340,18 +382,42 @@ if __name__ == "__main__":
while True: while True:
# wrap in an app context to benefit from app setup like database cleanup, sentry integration, etc # wrap in an app context to benefit from app setup like database cleanup, sentry integration, etc
with create_light_app().app_context(): with create_light_app().app_context():
for job in get_jobs_to_run(): taken_before_time = arrow.now().shift(
minutes=-config.JOB_TAKEN_RETRY_WAIT_MINS
)
jobs_done = 0
for job in get_jobs_to_run(taken_before_time):
if not take_job(job, taken_before_time):
continue
LOG.d("Take job %s", job) LOG.d("Take job %s", job)
# mark the job as taken, whether it will be executed successfully or not try:
job.taken = True newrelic.agent.record_custom_event("ProcessJob", {"job": job.name})
job.taken_at = arrow.now()
job.state = JobState.taken.value
job.attempts += 1
Session.commit()
process_job(job) process_job(job)
job_result = "success"
job.state = JobState.done.value job.state = JobState.done.value
jobs_done += 1
except Exception as e:
LOG.warn(f"Error processing job (id={job.id} name={job.name}): {e}")
# Increment manually, as the attempts increment is done by the take_job but not
# updated in our instance
job_attempts = job.attempts + 1
if job_attempts >= config.JOB_MAX_ATTEMPTS:
LOG.warn(
f"Marking job (id={job.id} name={job.name} attempts={job_attempts}) as ERROR"
)
job.state = JobState.error.value
job_result = "error"
else:
job_result = "retry"
newrelic.agent.record_custom_event(
"JobProcessed", {"job": job.name, "result": job_result}
)
Session.commit() Session.commit()
if jobs_done == 0:
time.sleep(10) time.sleep(10)

View File

@ -0,0 +1,31 @@
"""job priorities
Revision ID: fd79503179dd
Revises: 20e7d3ca289a
Create Date: 2025-02-25 15:39:24.833973
"""
import sqlalchemy_utils
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'fd79503179dd'
down_revision = '20e7d3ca289a'
branch_labels = None
depends_on = None
def upgrade():
with op.get_context().autocommit_block():
op.add_column('job', sa.Column('priority', sa.Integer(), server_default='50', nullable=False))
op.create_index('ix_state_run_at_taken_at_priority', 'job', ['state', 'run_at', 'taken_at', 'priority'], unique=False, postgresql_concurrently=True)
op.drop_index('ix_state_run_at_taken_at', table_name='job', postgresql_concurrently=True)
def downgrade():
with op.get_context().autocommit_block():
op.drop_index('ix_state_run_at_taken_at_priority', table_name='job', postgresql_concurrently=True)
op.create_index('ix_state_run_at_taken_at', 'job', ['state', 'run_at', 'taken_at'], unique=False, postgresql_concurrently=True)
op.drop_column('job', 'priority')

View File

@ -7,8 +7,11 @@ from typing import List, Dict
import arrow import arrow
import newrelic.agent import newrelic.agent
from app.models import JobState
from app.config import JOB_MAX_ATTEMPTS, JOB_TAKEN_RETRY_WAIT_MINS
from app.db import Session from app.db import Session
from app.log import LOG from app.log import LOG
from job_runner import get_jobs_to_run_query
from monitor.metric_exporter import MetricExporter from monitor.metric_exporter import MetricExporter
# the number of consecutive fails # the number of consecutive fails
@ -154,6 +157,38 @@ def log_failed_events():
newrelic.agent.record_custom_metric("Custom/sync_events_failed", failed_events) newrelic.agent.record_custom_metric("Custom/sync_events_failed", failed_events)
@newrelic.agent.background_task()
def log_jobs_to_run():
taken_before_time = arrow.now().shift(minutes=-JOB_TAKEN_RETRY_WAIT_MINS)
query = get_jobs_to_run_query(taken_before_time)
count = query.count()
LOG.d(f"Pending jobs to run: {count}")
newrelic.agent.record_custom_metric("Custom/jobs_to_run", count)
@newrelic.agent.background_task()
def log_failed_jobs():
r = Session.execute(
"""
SELECT COUNT(*)
FROM job
WHERE (
state = :error_state
OR (state = :taken_state AND attempts >= :max_attempts)
)
""",
{
"error_state": JobState.error.value,
"taken_state": JobState.taken.value,
"max_attempts": JOB_MAX_ATTEMPTS,
},
)
failed_jobs = list(r)[0][0]
LOG.d(f"Failed jobs: {failed_jobs}")
newrelic.agent.record_custom_metric("Custom/failed_jobs", failed_jobs)
if __name__ == "__main__": if __name__ == "__main__":
exporter = MetricExporter(get_newrelic_license()) exporter = MetricExporter(get_newrelic_license())
while True: while True:
@ -163,6 +198,8 @@ if __name__ == "__main__":
log_events_pending_dead_letter() log_events_pending_dead_letter()
log_failed_events() log_failed_events()
log_nb_db_connection_by_app_name() log_nb_db_connection_by_app_name()
log_jobs_to_run()
log_failed_jobs()
Session.close() Session.close()
exporter.run() exporter.run()

View File

@ -5,6 +5,7 @@ The step-to-step guide can be found on https://simplelogin.io/docs/siwsl/app/
This example is based on This example is based on
https://requests-oauthlib.readthedocs.io/en/latest/examples/real_world_example.html https://requests-oauthlib.readthedocs.io/en/latest/examples/real_world_example.html
""" """
import os import os
from flask import Flask, request, redirect, session, url_for from flask import Flask, request, redirect, session, url_for

View File

@ -34,4 +34,4 @@ for i in range(tests):
end = time.time() end = time.time()
time_taken = end - start time_taken = end - start
print(f"Took {time_taken} -> {time_taken/tests} per test") print(f"Took {time_taken} -> {time_taken / tests} per test")

View File

@ -0,0 +1,123 @@
#!/usr/bin/env python3
import argparse
import sys
import time
from sqlalchemy import func
from typing import Optional
from app.jobs.send_event_job import SendEventToWebhookJob
from app.db import Session
from app.events.generated.event_pb2 import UserPlanChanged, EventContent
from app.models import PartnerUser, User
def process(start_pu_id: int, end_pu_id: int, step: int, only_lifetime: bool):
print(
f"Checking partner user {start_pu_id} to {end_pu_id} (step={step}) (only_lifetime={only_lifetime})"
)
start_time = time.time()
with_lifetime = 0
with_plan = 0
with_free = 0
for batch_start in range(start_pu_id, end_pu_id, step):
query = (
Session.query(User)
.join(PartnerUser, PartnerUser.user_id == User.id)
.filter(PartnerUser.id >= batch_start, PartnerUser.id < batch_start + step)
)
if only_lifetime:
query = query.filter(
User.lifetime == True, # noqa :E712
)
users = query.all()
for user in users:
# Just in case the == True cond is wonky
if user.lifetime:
event = UserPlanChanged(lifetime=True)
with_lifetime += 1
else:
plan_end = user.get_active_subscription_end(
include_partner_subscription=False
)
if plan_end:
event = UserPlanChanged(plan_end_time=plan_end.timestamp)
with_plan += 1
else:
event = UserPlanChanged()
with_free += 1
job = SendEventToWebhookJob(
user=user, event=EventContent(user_plan_change=event)
)
job.store_job_in_db(run_at=None, commit=False)
Session.flush()
Session.commit()
elapsed = time.time() - start_time
last_batch_id = batch_start + step
time_per_user = elapsed / last_batch_id
remaining = end_pu_id - last_batch_id
time_remaining = remaining / time_per_user
hours_remaining = time_remaining / 60.0
print(
f"PartnerUser {batch_start}/{end_pu_id} lifetime {with_lifetime} paid {with_plan} free {with_free} {hours_remaining:.2f} mins remaining"
)
print(f"Sent lifetime {with_lifetime} paid {with_plan} free {with_free}")
def main():
parser = argparse.ArgumentParser(
prog="Schedule Sync User Jobs", description="Create jobs to sync users"
)
parser.add_argument(
"-s", "--start_pu_id", default=0, type=int, help="Initial partner_user_id"
)
parser.add_argument(
"-e", "--end_pu_id", default=0, type=int, help="Last partner_user_id"
)
parser.add_argument("-t", "--step", default=10000, type=int, help="Step to use")
parser.add_argument("-u", "--user", default="", type=str, help="User to sync")
parser.add_argument(
"-l", "--lifetime", action="store_true", help="Only sync lifetime users"
)
args = parser.parse_args()
start_pu_id = args.start_pu_id
end_pu_id = args.end_pu_id
user_id = args.user
only_lifetime = args.lifetime
step = args.step
if not end_pu_id:
end_pu_id = Session.query(func.max(PartnerUser.id)).scalar()
if user_id:
try:
user_id = int(user_id)
except ValueError:
user = User.get_by(email=user_id)
if not user:
print(f"User {user_id} not found")
sys.exit(1)
user_id = user.id
print(f"Limiting to user {user_id}")
partner_user: Optional[PartnerUser] = PartnerUser.get_by(user_id=user_id)
if not partner_user:
print(f"Could not find PartnerUser for user_id={user_id}")
sys.exit(1)
# So we only have one loop
step = 1
start_pu_id = partner_user.id
end_pu_id = partner_user.id
process(
start_pu_id=start_pu_id,
end_pu_id=end_pu_id,
step=step,
only_lifetime=only_lifetime,
)
if __name__ == "__main__":
main()

View File

@ -12,7 +12,7 @@ packages = [
] ]
include = ["templates/*", "templates/**/*", "local_data/*.txt"] include = ["templates/*", "templates/**/*", "local_data/*.txt"]
requires-python = "~=3.10" requires-python = "~=3.12"
dependencies = [ dependencies = [
"flask ~= 1.1.2", "flask ~= 1.1.2",
@ -24,9 +24,9 @@ dependencies = [
"python-dotenv ~= 0.14.0", "python-dotenv ~= 0.14.0",
"ipython ~= 7.31.1", "ipython ~= 7.31.1",
"sqlalchemy_utils ~= 0.36.8", "sqlalchemy_utils ~= 0.36.8",
"psycopg2-binary ~= 2.9.3", "psycopg2-binary ~= 2.9.10",
"sentry_sdk ~= 2.20.0", "sentry_sdk ~= 2.20.0",
"blinker ~= 1.4", "blinker ~= 1.9.0",
"arrow ~= 0.16.0", "arrow ~= 0.16.0",
"Flask-WTF ~= 0.14.3", "Flask-WTF ~= 0.14.3",
"boto3 ~= 1.35.37", "boto3 ~= 1.35.37",
@ -36,16 +36,16 @@ dependencies = [
"watchtower ~= 0.8.0", "watchtower ~= 0.8.0",
"sqlalchemy-utils == 0.36.8", "sqlalchemy-utils == 0.36.8",
"jwcrypto ~= 0.8", "jwcrypto ~= 0.8",
"yacron~=0.11.2", "yacron~=0.19.0",
"flask-debugtoolbar ~= 0.11.0", "flask-debugtoolbar ~= 0.11.0",
"requests_oauthlib ~= 1.3.0", "requests_oauthlib ~= 1.3.0",
"pyopenssl ~= 19.1.0", "pyopenssl ~= 19.1.0",
"aiosmtpd ~= 1.2", "aiosmtpd ~= 1.2",
"dnspython==2.0.0", "dnspython ~= 2.7.0",
"coloredlogs ~= 14.0", "coloredlogs ~= 14.0",
"pycryptodome ~= 3.9.8", "pycryptodome ~= 3.9.8",
"phpserialize ~= 1.3", "phpserialize ~= 1.3",
"dkimpy ~= 1.0.5", "dkimpy == 1.0.5",
"pyotp ~= 2.4.0", "pyotp ~= 2.4.0",
"flask_profiler ~= 1.8.1", "flask_profiler ~= 1.8.1",
"facebook-sdk ~= 3.1.0", "facebook-sdk ~= 3.1.0",
@ -53,11 +53,15 @@ dependencies = [
"google-auth-httplib2 ~= 0.0.4", "google-auth-httplib2 ~= 0.0.4",
"python-gnupg ~= 0.4.6", "python-gnupg ~= 0.4.6",
"webauthn ~= 0.4.7", "webauthn ~= 0.4.7",
# Git dependency until pyspf creates a new release
#"pyspf @ git+https://github.com/sdgathman/pyspf.git@665a6df079485a9824be0829e7d71088453db7f6",
"pyspf ~= 2.0.14", "pyspf ~= 2.0.14",
"Flask-Limiter == 1.4",
"Flask-Limiter == 1.5",
"memory_profiler ~= 0.57.0", "memory_profiler ~= 0.57.0",
"gevent ~= 24.11.1", "gevent ~= 24.11.1",
"email-validator ~= 1.1.3", "email-validator ~= 2.2.0",
"PGPy == 0.5.4", "PGPy == 0.5.4",
"coinbase-commerce ~= 1.0.1", "coinbase-commerce ~= 1.0.1",
"requests ~= 2.25.1", "requests ~= 2.25.1",
@ -71,16 +75,18 @@ dependencies = [
"MarkupSafe~=1.1.1", "MarkupSafe~=1.1.1",
"cryptography ~= 37.0.1", "cryptography ~= 37.0.1",
"SQLAlchemy ~= 1.3.24", "SQLAlchemy ~= 1.3.24",
"redis==4.6.0", "redis==5.2.1",
"newrelic-telemetry-sdk ~= 0.5.0", "newrelic-telemetry-sdk ~= 0.5.0",
"aiospamc == 0.10", "aiospamc == 0.10",
"itsdangerous ~= 1.1.0", "itsdangerous ~= 1.1.0",
"werkzeug ~= 1.0.1", "werkzeug ~= 1.0.1",
"alembic ~= 1.4.3", "alembic ~= 1.4.3",
"limits ~= 4.0.1",
"strictyaml ~= 1.7.3",
] ]
[tool.black] [tool.black]
target-version = ['py310'] target-version = ['py312']
exclude = ''' exclude = '''
( (
/( /(
@ -101,8 +107,9 @@ exclude = '''
''' '''
[tool.ruff] [tool.ruff]
ignore-init-module-imports = true
exclude = [".venv", "migrations", "app/events/generated"] exclude = [".venv", "migrations", "app/events/generated"]
[tool.ruff.lint]
ignore-init-module-imports = true
[tool.djlint] [tool.djlint]
indent = 2 indent = 2
@ -127,7 +134,7 @@ ignore = "H006,H013,H016,H017,H019,H021,H025,H030,H031,T003,J004,J018,T001"
dev-dependencies = [ dev-dependencies = [
"pytest ~= 7.0.0", "pytest ~= 7.0.0",
"pytest-cov ~= 3.0.0", "pytest-cov ~= 3.0.0",
"pre-commit ~= 2.17.0", "pre-commit ~= 4.1.0",
"black ~= 22.1.0", "black ~= 22.1.0",
"djlint==1.34.1", "djlint==1.34.1",
"pylint ~= 2.14.4", "pylint ~= 2.14.4",

View File

@ -585,7 +585,8 @@ def local_main():
# enable flask toolbar # enable flask toolbar
from flask_debugtoolbar import DebugToolbarExtension from flask_debugtoolbar import DebugToolbarExtension
app.config["DEBUG_TB_PROFILER_ENABLED"] = True # Disabled in python 3.12 as it collides with the default CPython profiler
app.config["DEBUG_TB_PROFILER_ENABLED"] = False
app.config["DEBUG_TB_INTERCEPT_REDIRECTS"] = False app.config["DEBUG_TB_INTERCEPT_REDIRECTS"] = False
app.debug = True app.debug = True
DebugToolbarExtension(app) DebugToolbarExtension(app)

View File

@ -647,8 +647,8 @@ def test_get_alias(flask_client):
def test_is_reverse_alias(flask_client): def test_is_reverse_alias(flask_client):
assert is_reverse_alias("ra+abcd@sl.local") assert is_reverse_alias("ra+abcd@sl.lan")
assert is_reverse_alias("reply+abcd@sl.local") assert is_reverse_alias("reply+abcd@sl.lan")
assert not is_reverse_alias("ra+abcd@test.org") assert not is_reverse_alias("ra+abcd@test.org")
assert not is_reverse_alias("reply+abcd@test.org") assert not is_reverse_alias("reply+abcd@test.org")

View File

@ -1,5 +1,3 @@
from flask import g
from app import config from app import config
from app.alias_suffix import signer from app.alias_suffix import signer
from app.alias_utils import delete_alias from app.alias_utils import delete_alias
@ -7,7 +5,7 @@ from app.config import EMAIL_DOMAIN, MAX_NB_EMAIL_FREE_PLAN
from app.db import Session from app.db import Session
from app.models import Alias, CustomDomain, Mailbox, AliasUsedOn from app.models import Alias, CustomDomain, Mailbox, AliasUsedOn
from app.utils import random_word from app.utils import random_word
from tests.utils import login, random_domain, random_token from tests.utils import fix_rate_limit_after_request, login, random_domain, random_token
def test_v2(flask_client): def test_v2(flask_client):
@ -276,7 +274,7 @@ def test_too_many_requests(flask_client):
# to make flask-limiter work with unit test # to make flask-limiter work with unit test
# https://github.com/alisaifee/flask-limiter/issues/147#issuecomment-642683820 # https://github.com/alisaifee/flask-limiter/issues/147#issuecomment-642683820
g._rate_limiting_complete = False fix_rate_limit_after_request()
else: else:
# last request # last request
assert r.status_code == 429 assert r.status_code == 429

View File

@ -1,12 +1,12 @@
import uuid import uuid
from flask import url_for, g from flask import url_for
from app import config from app import config
from app.config import EMAIL_DOMAIN, MAX_NB_EMAIL_FREE_PLAN from app.config import EMAIL_DOMAIN, MAX_NB_EMAIL_FREE_PLAN
from app.db import Session from app.db import Session
from app.models import Alias, CustomDomain, AliasUsedOn from app.models import Alias, CustomDomain, AliasUsedOn
from tests.utils import login, random_domain from tests.utils import fix_rate_limit_after_request, login, random_domain
def test_with_hostname(flask_client): def test_with_hostname(flask_client):
@ -17,7 +17,7 @@ def test_with_hostname(flask_client):
) )
assert r.status_code == 201 assert r.status_code == 201
assert r.json["alias"].endswith("d1.test") assert r.json["alias"].endswith("d1.lan")
# make sure alias starts with the suggested prefix # make sure alias starts with the suggested prefix
assert r.json["alias"].startswith("test") assert r.json["alias"].startswith("test")
@ -133,7 +133,7 @@ def test_too_many_requests(flask_client):
) )
# to make flask-limiter work with unit test # to make flask-limiter work with unit test
# https://github.com/alisaifee/flask-limiter/issues/147#issuecomment-642683820 # https://github.com/alisaifee/flask-limiter/issues/147#issuecomment-642683820
g._rate_limiting_complete = False fix_rate_limit_after_request()
else: else:
# last request # last request
assert r.status_code == 429 assert r.status_code == 429

View File

@ -112,14 +112,14 @@ def test_get_alias_infos_with_pagination_v3_no_duplicate_when_empty_contact(
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email="rep@sl.local", reply_email="rep@sl.lan",
) )
Contact.create( Contact.create(
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact2@example.com", website_email="contact2@example.com",
reply_email="rep2@sl.local", reply_email="rep2@sl.lan",
) )
alias_infos = get_alias_infos_with_pagination_v3(user) alias_infos = get_alias_infos_with_pagination_v3(user)

View File

@ -15,7 +15,7 @@ def test_get_setting(flask_client):
assert r.json == { assert r.json == {
"alias_generator": "word", "alias_generator": "word",
"notification": True, "notification": True,
"random_alias_default_domain": "sl.local", "random_alias_default_domain": "sl.lan",
"sender_format": "AT", "sender_format": "AT",
"random_alias_suffix": "word", "random_alias_suffix": "word",
} }
@ -47,7 +47,7 @@ def test_update_settings_random_alias_default_domain(flask_client):
custom_domain = CustomDomain.create( custom_domain = CustomDomain.create(
domain=random_domain(), verified=True, user_id=user.id, flush=True domain=random_domain(), verified=True, user_id=user.id, flush=True
) )
assert user.default_random_alias_domain() == "sl.local" assert user.default_random_alias_domain() == "sl.lan"
r = flask_client.patch( r = flask_client.patch(
"/api/setting", json={"random_alias_default_domain": "invalid"} "/api/setting", json={"random_alias_default_domain": "invalid"}
@ -55,10 +55,10 @@ def test_update_settings_random_alias_default_domain(flask_client):
assert r.status_code == 400 assert r.status_code == 400
r = flask_client.patch( r = flask_client.patch(
"/api/setting", json={"random_alias_default_domain": "d1.test"} "/api/setting", json={"random_alias_default_domain": "d1.lan"}
) )
assert r.status_code == 200 assert r.status_code == 200
assert user.default_random_alias_domain() == "d1.test" assert user.default_random_alias_domain() == "d1.lan"
r = flask_client.patch( r = flask_client.patch(
"/api/setting", json={"random_alias_default_domain": custom_domain.domain} "/api/setting", json={"random_alias_default_domain": custom_domain.domain}

View File

@ -2,7 +2,7 @@ from random import random
from flask import url_for from flask import url_for
from app import config from app.constants import JobType
from app.db import Session from app.db import Session
from app.models import Job, ApiToCookieToken from app.models import Job, ApiToCookieToken
from tests.api.utils import get_new_user_and_api_key from tests.api.utils import get_new_user_and_api_key
@ -48,7 +48,7 @@ def test_delete_with_sudo(flask_client):
jobs = Job.all() jobs = Job.all()
assert len(jobs) == 1 assert len(jobs) == 1
job = jobs[0] job = jobs[0]
assert job.name == config.JOB_DELETE_ACCOUNT assert job.name == JobType.DELETE_ACCOUNT.value
assert job.payload == {"user_id": user.id} assert job.payload == {"user_id": user.id}

View File

@ -23,7 +23,7 @@ from init_app import add_sl_domains, add_proton_partner
app = create_app() app = create_app()
app.config["TESTING"] = True app.config["TESTING"] = True
app.config["WTF_CSRF_ENABLED"] = False app.config["WTF_CSRF_ENABLED"] = False
app.config["SERVER_NAME"] = "sl.test" app.config["SERVER_NAME"] = "sl.lan"
# enable pg_trgm extension # enable pg_trgm extension
with engine.connect() as conn: with engine.connect() as conn:

View File

@ -1,6 +1,6 @@
from random import random from random import random
from flask import url_for, g from flask import url_for
from app import config from app import config
from app.alias_suffix import ( from app.alias_suffix import (
@ -22,7 +22,12 @@ from app.models import (
DailyMetric, DailyMetric,
) )
from app.utils import random_word from app.utils import random_word
from tests.utils import login, random_domain, create_new_user from tests.utils import (
fix_rate_limit_after_request,
login,
random_domain,
create_new_user,
)
def test_add_alias_success(flask_client): def test_add_alias_success(flask_client):
@ -388,7 +393,7 @@ def test_too_many_requests(flask_client):
# to make flask-limiter work with unit test # to make flask-limiter work with unit test
# https://github.com/alisaifee/flask-limiter/issues/147#issuecomment-642683820 # https://github.com/alisaifee/flask-limiter/issues/147#issuecomment-642683820
g._rate_limiting_complete = False fix_rate_limit_after_request()
else: else:
# last request # last request
assert r.status_code == 429 assert r.status_code == 429

View File

@ -1,10 +1,10 @@
from flask import url_for, g from flask import url_for
from app import config from app import config
from app.models import ( from app.models import (
Alias, Alias,
) )
from tests.utils import login from tests.utils import fix_rate_limit_after_request, login
def test_create_random_alias_success(flask_client): def test_create_random_alias_success(flask_client):
@ -34,7 +34,7 @@ def test_too_many_requests(flask_client):
# to make flask-limiter work with unit test # to make flask-limiter work with unit test
# https://github.com/alisaifee/flask-limiter/issues/147#issuecomment-642683820 # https://github.com/alisaifee/flask-limiter/issues/147#issuecomment-642683820
g._rate_limiting_complete = False fix_rate_limit_after_request()
else: else:
# last request # last request
assert r.status_code == 429 assert r.status_code == 429

View File

@ -28,7 +28,7 @@ def test_rate_limited_forward_phase_for_alias(flask_client):
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email="rep@sl.local", reply_email="rep@sl.lan",
) )
Session.commit() Session.commit()
for _ in range(MAX_ACTIVITY_DURING_MINUTE_PER_ALIAS + 1): for _ in range(MAX_ACTIVITY_DURING_MINUTE_PER_ALIAS + 1):
@ -52,7 +52,7 @@ def test_rate_limited_forward_phase_for_mailbox(flask_client):
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email="rep@sl.local", reply_email="rep@sl.lan",
) )
Session.commit() Session.commit()
for _ in range(MAX_ACTIVITY_DURING_MINUTE_PER_MAILBOX + 1): for _ in range(MAX_ACTIVITY_DURING_MINUTE_PER_MAILBOX + 1):
@ -90,7 +90,7 @@ def test_rate_limited_reply_phase(flask_client):
alias = Alias.create_new_random(user) alias = Alias.create_new_random(user)
Session.commit() Session.commit()
reply_email = f"reply-{random.random()}@sl.local" reply_email = f"reply-{random.random()}@sl.lan"
contact = Contact.create( contact = Contact.create(
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,

View File

@ -37,7 +37,7 @@ def prepare_complaint(
contact = Contact.create( contact = Contact.create(
user_id=alias.user.id, user_id=alias.user.id,
alias_id=alias.id, alias_id=alias.id,
website_email=f"contact{random.random()}@mailbox.test", website_email=f"contact{random.random()}@mailbox.lan",
reply_email="d@e.f", reply_email="d@e.f",
commit=True, commit=True,
) )

View File

@ -27,7 +27,7 @@ def generate_unsub_block_contact_data() -> Iterable:
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email="rep@sl.local", reply_email="rep@sl.lan",
commit=True, commit=True,
) )
@ -86,7 +86,7 @@ def generate_unsub_disable_alias_data() -> Iterable:
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email="rep@sl.local", reply_email="rep@sl.lan",
commit=True, commit=True,
) )
@ -145,7 +145,7 @@ def generate_unsub_preserve_original_data() -> Iterable:
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email="rep@sl.local", reply_email="rep@sl.lan",
commit=True, commit=True,
) )
@ -215,7 +215,7 @@ def test_unsub_preserves_sl_unsubscriber():
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email="rep@sl.local", reply_email="rep@sl.lan",
commit=True, commit=True,
) )
message = Message() message = Message()

View File

@ -49,7 +49,7 @@ def test_old_subject_block_contact():
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email=f"{random()}@sl.local", reply_email=f"{random()}@sl.lan",
block_forward=False, block_forward=False,
commit=True, commit=True,
) )
@ -92,7 +92,7 @@ def test_new_subject_block_contact():
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email=f"{random()}@sl.local", reply_email=f"{random()}@sl.lan",
block_forward=False, block_forward=False,
commit=True, commit=True,
) )
@ -172,7 +172,7 @@ def test_request_disable_contact(flask_client):
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email=f"{random()}@sl.local", reply_email=f"{random()}@sl.lan",
block_forward=False, block_forward=False,
commit=True, commit=True,
) )

View File

@ -1,6 +1,6 @@
from sqlalchemy_utils.types.arrow import arrow from sqlalchemy_utils.types.arrow import arrow
from app.config import JOB_DELETE_MAILBOX from app.constants import JobType
from app.db import Session from app.db import Session
from app.mail_sender import mail_sender from app.mail_sender import mail_sender
from app.models import Alias, Mailbox, Job, AliasMailbox from app.models import Alias, Mailbox, Job, AliasMailbox
@ -21,7 +21,7 @@ def test_delete_mailbox_transfer_mailbox_primary(flask_client):
alias_id = Alias.create_new(user, "prefix", mailbox_id=m1.id).id alias_id = Alias.create_new(user, "prefix", mailbox_id=m1.id).id
AliasMailbox.create(alias_id=alias_id, mailbox_id=m2.id) AliasMailbox.create(alias_id=alias_id, mailbox_id=m2.id)
job = Job.create( job = Job.create(
name=JOB_DELETE_MAILBOX, name=JobType.DELETE_MAILBOX.value,
payload={"mailbox_id": m1.id, "transfer_mailbox_id": m2.id}, payload={"mailbox_id": m1.id, "transfer_mailbox_id": m2.id},
run_at=arrow.now(), run_at=arrow.now(),
commit=True, commit=True,
@ -43,7 +43,7 @@ def test_delete_mailbox_no_email(flask_client):
user_id=user.id, email=random_email(), verified=True, flush=True user_id=user.id, email=random_email(), verified=True, flush=True
) )
job = Job.create( job = Job.create(
name=JOB_DELETE_MAILBOX, name=JobType.DELETE_MAILBOX.value,
payload={"mailbox_id": m1.id, "transfer_mailbox_id": None, "send_mail": False}, payload={"mailbox_id": m1.id, "transfer_mailbox_id": None, "send_mail": False},
run_at=arrow.now(), run_at=arrow.now(),
commit=True, commit=True,
@ -70,7 +70,7 @@ def test_delete_mailbox_transfer_mailbox_in_list(flask_client):
alias_id = Alias.create_new(user, "prefix", mailbox_id=m1.id).id alias_id = Alias.create_new(user, "prefix", mailbox_id=m1.id).id
AliasMailbox.create(alias_id=alias_id, mailbox_id=m2.id) AliasMailbox.create(alias_id=alias_id, mailbox_id=m2.id)
job = Job.create( job = Job.create(
name=JOB_DELETE_MAILBOX, name=JobType.DELETE_MAILBOX.value,
payload={"mailbox_id": m2.id, "transfer_mailbox_id": m3.id}, payload={"mailbox_id": m2.id, "transfer_mailbox_id": m3.id},
run_at=arrow.now(), run_at=arrow.now(),
commit=True, commit=True,
@ -95,7 +95,7 @@ def test_delete_mailbox_no_transfer(flask_client):
alias_id = Alias.create_new(user, "prefix", mailbox_id=m1.id).id alias_id = Alias.create_new(user, "prefix", mailbox_id=m1.id).id
job = Job.create( job = Job.create(
name=JOB_DELETE_MAILBOX, name=JobType.DELETE_MAILBOX.value,
payload={"mailbox_id": m1.id}, payload={"mailbox_id": m1.id},
run_at=arrow.now(), run_at=arrow.now(),
commit=True, commit=True,

View File

@ -1,7 +1,7 @@
from app import config from app import config
from app.db import Session from app.db import Session
from job_runner import get_jobs_to_run from job_runner import get_jobs_to_run
from app.models import Job, JobState from app.models import Job, JobPriority, JobState
import arrow import arrow
@ -56,18 +56,65 @@ def test_get_jobs_to_run(flask_client):
run_at=now.shift(hours=3), run_at=now.shift(hours=3),
) )
# Job out of attempts # Job out of attempts
(
Job.create( Job.create(
name="", name="",
payload="", payload="",
state=JobState.taken.value, state=JobState.taken.value,
taken_at=now.shift(minutes=-(config.JOB_TAKEN_RETRY_WAIT_MINS + 10)), taken_at=now.shift(minutes=-(config.JOB_TAKEN_RETRY_WAIT_MINS + 10)),
attempts=config.JOB_MAX_ATTEMPTS + 1, attempts=config.JOB_MAX_ATTEMPTS + 1,
),
) )
# Job marked as error
Job.create(
name="",
payload="",
state=JobState.error.value,
taken_at=now.shift(minutes=-(config.JOB_TAKEN_RETRY_WAIT_MINS + 10)),
attempts=config.JOB_MAX_ATTEMPTS + 1,
)
Session.commit() Session.commit()
jobs = get_jobs_to_run() taken_before_time = arrow.now().shift(minutes=-config.JOB_TAKEN_RETRY_WAIT_MINS)
jobs = get_jobs_to_run(taken_before_time)
assert len(jobs) == len(expected_jobs_to_run) assert len(jobs) == len(expected_jobs_to_run)
job_ids = [job.id for job in jobs] job_ids = [job.id for job in jobs]
for job in expected_jobs_to_run: for job in expected_jobs_to_run:
assert job.id in job_ids assert job.id in job_ids
def test_get_jobs_to_run_respects_priority(flask_client):
now = arrow.now()
for job in Job.all():
Job.delete(job.id)
j1 = Job.create(
name="", payload="", run_at=now.shift(minutes=-1), priority=JobPriority.High
)
j2 = Job.create(
name="", payload="", run_at=now.shift(minutes=-2), priority=JobPriority.Default
)
j3 = Job.create(
name="", payload="", run_at=now.shift(minutes=-3), priority=JobPriority.Default
)
j4 = Job.create(
name="", payload="", run_at=now.shift(minutes=-4), priority=JobPriority.Low
)
j5 = Job.create(
name="", payload="", run_at=now.shift(minutes=-2), priority=JobPriority.High
)
Session.commit()
taken_before_time = arrow.now().shift(minutes=-config.JOB_TAKEN_RETRY_WAIT_MINS)
jobs = get_jobs_to_run(taken_before_time)
assert len(jobs) == 5
job_ids = [job.id for job in jobs]
# The expected outcome is:
# 1. j5 -> 2 mins ago and High
# 2. j1 -> 1 min ago and High
# --- The 2 above are high, so they should be the first ones. j5 is first as it's been pending for a longer time
# 3. j3 -> 3 mins ago and Default
# 4. j2 -> 2 mins ago and Default
# --- The 2 above are both default, and again, are sorted by run_at ascendingly
# 5. j4 -> 3 mins ago and Low. Even if it is the one that has been waiting the most, as it's Low, it's the last one
assert job_ids == [j5.id, j1.id, j3.id, j2.id, j4.id]

View File

@ -1,6 +1,6 @@
import arrow import arrow
from app import config from app.constants import JobType
from app.events.generated.event_pb2 import EventContent, AliasDeleted from app.events.generated.event_pb2 import EventContent, AliasDeleted
from app.jobs.send_event_job import SendEventToWebhookJob from app.jobs.send_event_job import SendEventToWebhookJob
from app.models import PartnerUser from app.models import PartnerUser
@ -17,7 +17,7 @@ def test_serialize_and_deserialize_job():
run_at = arrow.now().shift(hours=10) run_at = arrow.now().shift(hours=10)
db_job = SendEventToWebhookJob(user, event).store_job_in_db(run_at=run_at) db_job = SendEventToWebhookJob(user, event).store_job_in_db(run_at=run_at)
assert db_job.run_at == run_at assert db_job.run_at == run_at
assert db_job.name == config.JOB_SEND_EVENT_TO_WEBHOOK assert db_job.name == JobType.SEND_EVENT_TO_WEBHOOK.value
job = SendEventToWebhookJob.create_from_job(db_job) job = SendEventToWebhookJob.create_from_job(db_job)
assert job._user.id == user.id assert job._user.id == user.id
assert job._event.alias_deleted.id == alias_id assert job._event.alias_deleted.id == alias_id

View File

@ -1,5 +1,6 @@
import arrow import arrow
from app import config
from app.constants import JobType
from app.db import Session from app.db import Session
from app.models import User, Job, PartnerSubscription, PartnerUser, ManualSubscription from app.models import User, Job, PartnerSubscription, PartnerUser, ManualSubscription
from app.proton.proton_partner import get_proton_partner from app.proton.proton_partner import get_proton_partner
@ -16,7 +17,7 @@ def test_create_from_partner(flask_client):
assert user.newsletter_alias_id is None assert user.newsletter_alias_id is None
job = Session.query(Job).order_by(Job.id.desc()).first() job = Session.query(Job).order_by(Job.id.desc()).first()
assert job is not None assert job is not None
assert job.name == config.JOB_SEND_PROTON_WELCOME_1 assert job.name == JobType.SEND_PROTON_WELCOME_1.value
assert job.payload.get("user_id") == user.id assert job.payload.get("user_id") == user.id

View File

@ -140,13 +140,13 @@ def test_get_metrics():
records=[ records=[
UpcloudRecord( UpcloudRecord(
db_role="master", db_role="master",
label="test-1 " "(master)", label="test-1 (master)",
time="2022-01-21T13:12:00Z", time="2022-01-21T13:12:00Z",
value=3.275132296130991, value=3.275132296130991,
), ),
UpcloudRecord( UpcloudRecord(
db_role="standby", db_role="standby",
label="test-2 " "(standby)", label="test-2 (standby)",
time="2022-01-21T13:12:00Z", time="2022-01-21T13:12:00Z",
value=4.196249043309251, value=4.196249043309251,
), ),
@ -157,13 +157,13 @@ def test_get_metrics():
records=[ records=[
UpcloudRecord( UpcloudRecord(
db_role="master", db_role="master",
label="test-1 " "(master)", label="test-1 (master)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=5.654416415900109, value=5.654416415900109,
), ),
UpcloudRecord( UpcloudRecord(
db_role="standby", db_role="standby",
label="test-2 " "(standby)", label="test-2 (standby)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=5.58959125727556, value=5.58959125727556,
), ),
@ -174,13 +174,13 @@ def test_get_metrics():
records=[ records=[
UpcloudRecord( UpcloudRecord(
db_role="master", db_role="master",
label="test-1 " "(master)", label="test-1 (master)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=0, value=0,
), ),
UpcloudRecord( UpcloudRecord(
db_role="standby", db_role="standby",
label="test-2 " "(standby)", label="test-2 (standby)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=0, value=0,
), ),
@ -191,13 +191,13 @@ def test_get_metrics():
records=[ records=[
UpcloudRecord( UpcloudRecord(
db_role="master", db_role="master",
label="test-1 " "(master)", label="test-1 (master)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=4, value=4,
), ),
UpcloudRecord( UpcloudRecord(
db_role="standby", db_role="standby",
label="test-2 " "(standby)", label="test-2 (standby)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=3, value=3,
), ),
@ -208,13 +208,13 @@ def test_get_metrics():
records=[ records=[
UpcloudRecord( UpcloudRecord(
db_role="master", db_role="master",
label="test-1 " "(master)", label="test-1 (master)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=0.14, value=0.14,
), ),
UpcloudRecord( UpcloudRecord(
db_role="standby", db_role="standby",
label="test-2 " "(standby)", label="test-2 (standby)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=0.09, value=0.09,
), ),
@ -225,13 +225,13 @@ def test_get_metrics():
records=[ records=[
UpcloudRecord( UpcloudRecord(
db_role="master", db_role="master",
label="test-1 " "(master)", label="test-1 (master)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=11.488581675749048, value=11.488581675749048,
), ),
UpcloudRecord( UpcloudRecord(
db_role="standby", db_role="standby",
label="test-2 " "(standby)", label="test-2 (standby)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=12.272260458006759, value=12.272260458006759,
), ),
@ -242,13 +242,13 @@ def test_get_metrics():
records=[ records=[
UpcloudRecord( UpcloudRecord(
db_role="master", db_role="master",
label="test-1 " "(master)", label="test-1 (master)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=466, value=466,
), ),
UpcloudRecord( UpcloudRecord(
db_role="standby", db_role="standby",
label="test-2 " "(standby)", label="test-2 (standby)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=458, value=458,
), ),
@ -259,13 +259,13 @@ def test_get_metrics():
records=[ records=[
UpcloudRecord( UpcloudRecord(
db_role="master", db_role="master",
label="test-1 " "(master)", label="test-1 (master)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=694, value=694,
), ),
UpcloudRecord( UpcloudRecord(
db_role="standby", db_role="standby",
label="test-2 " "(standby)", label="test-2 (standby)",
time="2022-01-21T13:11:30Z", time="2022-01-21T13:11:30Z",
value=573, value=573,
), ),

View File

@ -1,10 +1,10 @@
from arrow import Arrow from arrow import Arrow
from app import config
from app.account_linking import ( from app.account_linking import (
SLPlan, SLPlan,
SLPlanType, SLPlanType,
) )
from app.constants import JobType
from app.proton.proton_client import ProtonClient, UserInformation from app.proton.proton_client import ProtonClient, UserInformation
from app.proton.proton_callback_handler import ( from app.proton.proton_callback_handler import (
ProtonCallbackHandler, ProtonCallbackHandler,
@ -28,7 +28,7 @@ class MockProtonClient(ProtonClient):
def check_initial_sync_job(user: User, expected: bool): def check_initial_sync_job(user: User, expected: bool):
found = False found = False
for job in Job.yield_per_query(10).filter_by( for job in Job.yield_per_query(10).filter_by(
name=config.JOB_SEND_ALIAS_CREATION_EVENTS, name=JobType.SEND_ALIAS_CREATION_EVENTS.value,
state=JobState.ready.value, state=JobState.ready.value,
): ):
if job.payload.get("user_id") == user.id: if job.payload.get("user_id") == user.id:

View File

@ -5,9 +5,9 @@ LOCAL_FILE_UPLOAD=1
# Email related settings # Email related settings
# Only print email content, not sending it # Only print email content, not sending it
NOT_SEND_EMAIL=true NOT_SEND_EMAIL=true
EMAIL_DOMAIN=sl.local EMAIL_DOMAIN=sl.lan
OTHER_ALIAS_DOMAINS=["d1.test", "d2.test", "sl.local"] OTHER_ALIAS_DOMAINS=["d1.lan", "d2.lan", "sl.lan"]
SUPPORT_EMAIL=support@sl.local SUPPORT_EMAIL=support@sl.lan
ADMIN_EMAIL=to_fill ADMIN_EMAIL=to_fill
# Max number emails user can generate for free plan # Max number emails user can generate for free plan
MAX_NB_EMAIL_FREE_PLAN=3 MAX_NB_EMAIL_FREE_PLAN=3

View File

@ -214,7 +214,7 @@ def test_avoid_add_to_header_already_present_in_cc():
def test_email_sent_to_noreply(flask_client): def test_email_sent_to_noreply(flask_client):
msg = EmailMessage() msg = EmailMessage()
envelope = Envelope() envelope = Envelope()
envelope.mail_from = "from@domain.test" envelope.mail_from = "from@domain.lan"
envelope.rcpt_tos = [config.NOREPLY] envelope.rcpt_tos = [config.NOREPLY]
result = email_handler.handle(envelope, msg) result = email_handler.handle(envelope, msg)
assert result == status.E200 assert result == status.E200
@ -223,10 +223,10 @@ def test_email_sent_to_noreply(flask_client):
def test_email_sent_to_noreplies(flask_client): def test_email_sent_to_noreplies(flask_client):
msg = EmailMessage() msg = EmailMessage()
envelope = Envelope() envelope = Envelope()
envelope.mail_from = "from@domain.test" envelope.mail_from = "from@domain.lan"
config.NOREPLIES = ["other-no-reply@sl.test"] config.NOREPLIES = ["other-no-reply@sl.lan"]
envelope.rcpt_tos = ["other-no-reply@sl.test"] envelope.rcpt_tos = ["other-no-reply@sl.lan"]
result = email_handler.handle(envelope, msg) result = email_handler.handle(envelope, msg)
assert result == status.E200 assert result == status.E200

View File

@ -78,17 +78,17 @@ def test_get_email_domain_part():
def test_email_belongs_to_alias_domains(): def test_email_belongs_to_alias_domains():
# default alias domain # default alias domain
assert can_create_directory_for_address("ab@sl.local") assert can_create_directory_for_address("ab@sl.lan")
assert not can_create_directory_for_address("ab@not-exist.local") assert not can_create_directory_for_address("ab@not-exist.lan")
assert can_create_directory_for_address("hey@d1.test") assert can_create_directory_for_address("hey@d1.lan")
assert not can_create_directory_for_address("hey@d3.test") assert not can_create_directory_for_address("hey@d3.lan")
def test_can_be_used_as_personal_email(flask_client): def test_can_be_used_as_personal_email(flask_client):
# default alias domain # default alias domain
assert not email_can_be_used_as_mailbox("ab@sl.local") assert not email_can_be_used_as_mailbox("ab@sl.lan")
assert not email_can_be_used_as_mailbox("hey@d1.test") assert not email_can_be_used_as_mailbox("hey@d1.lan")
# custom domain as SL domain # custom domain as SL domain
domain = random_domain() domain = random_domain()
@ -115,7 +115,7 @@ def test_can_be_used_as_personal_email(flask_client):
def test_disabled_user_prevents_email_from_being_used_as_mailbox(): def test_disabled_user_prevents_email_from_being_used_as_mailbox():
email = f"user_{random_token(10)}@mailbox.test" email = f"user_{random_token(10)}@mailbox.lan"
assert email_can_be_used_as_mailbox(email) assert email_can_be_used_as_mailbox(email)
user = create_new_user(email) user = create_new_user(email)
user.disabled = True user.disabled = True
@ -124,7 +124,7 @@ def test_disabled_user_prevents_email_from_being_used_as_mailbox():
def test_disabled_user_with_secondary_mailbox_prevents_email_from_being_used_as_mailbox(): def test_disabled_user_with_secondary_mailbox_prevents_email_from_being_used_as_mailbox():
email = f"user_{random_token(10)}@mailbox.test" email = f"user_{random_token(10)}@mailbox.lan"
assert email_can_be_used_as_mailbox(email) assert email_can_be_used_as_mailbox(email)
user = create_new_user() user = create_new_user()
Mailbox.create(user_id=user.id, email=email) Mailbox.create(user_id=user.id, email=email)
@ -592,8 +592,8 @@ def test_generate_reply_email_include_sender_in_reverse_alias(flask_client):
def test_normalize_reply_email(flask_client): def test_normalize_reply_email(flask_client):
assert normalize_reply_email("re+abcd@sl.local") == "re+abcd@sl.local" assert normalize_reply_email("re+abcd@sl.lan") == "re+abcd@sl.lan"
assert normalize_reply_email('re+"ab cd"@sl.local') == "re+_ab_cd_@sl.local" assert normalize_reply_email('re+"ab cd"@sl.lan') == "re+_ab_cd_@sl.lan"
def test_get_encoding(): def test_get_encoding():
@ -669,7 +669,7 @@ def test_should_disable(flask_client):
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email="rep@sl.local", reply_email="rep@sl.lan",
commit=True, commit=True,
) )
for _ in range(20): for _ in range(20):
@ -702,7 +702,7 @@ def test_should_disable_bounces_every_day(flask_client):
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email="rep@sl.local", reply_email="rep@sl.lan",
commit=True, commit=True,
) )
for i in range(9): for i in range(9):
@ -730,7 +730,7 @@ def test_should_disable_bounces_account(flask_client):
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email="rep@sl.local", reply_email="rep@sl.lan",
commit=True, commit=True,
) )
@ -758,7 +758,7 @@ def test_should_disable_bounce_consecutive_days(flask_client):
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email="contact@example.com", website_email="contact@example.com",
reply_email="rep@sl.local", reply_email="rep@sl.lan",
commit=True, commit=True,
) )

View File

@ -1,12 +1,10 @@
from http import HTTPStatus from http import HTTPStatus
from random import Random from random import Random
from flask import g
from app import config from app import config
from app.extensions import limiter from app.extensions import limiter
from tests.conftest import app as test_app from tests.conftest import app as test_app
from tests.utils import login from tests.utils import fix_rate_limit_after_request, login
# IMPORTANT NOTICE # IMPORTANT NOTICE
# ---------------- # ----------------
@ -34,10 +32,6 @@ def random_ip() -> str:
return ".".join(octets) return ".".join(octets)
def fix_rate_limit_after_request():
g._rate_limiting_complete = False
def request_headers(source_ip: str) -> dict: def request_headers(source_ip: str) -> dict:
return {"X-Forwarded-For": source_ip} return {"X-Forwarded-For": source_ip}

View File

@ -5,6 +5,7 @@ import arrow
import pytest import pytest
from app import mailbox_utils, config from app import mailbox_utils, config
from app.constants import JobType
from app.db import Session from app.db import Session
from app.mail_sender import mail_sender from app.mail_sender import mail_sender
from app.mailbox_utils import ( from app.mailbox_utils import (
@ -231,7 +232,7 @@ def test_delete_with_no_transfer():
mailbox_utils.delete_mailbox(user, mailbox.id, transfer_mailbox_id=None) mailbox_utils.delete_mailbox(user, mailbox.id, transfer_mailbox_id=None)
job = Session.query(Job).order_by(Job.id.desc()).first() job = Session.query(Job).order_by(Job.id.desc()).first()
assert job is not None assert job is not None
assert job.name == config.JOB_DELETE_MAILBOX assert job.name == JobType.DELETE_MAILBOX.value
assert job.payload["mailbox_id"] == mailbox.id assert job.payload["mailbox_id"] == mailbox.id
assert job.payload["transfer_mailbox_id"] is None assert job.payload["transfer_mailbox_id"] is None
@ -252,13 +253,13 @@ def test_delete_with_transfer():
) )
job = Session.query(Job).order_by(Job.id.desc()).first() job = Session.query(Job).order_by(Job.id.desc()).first()
assert job is not None assert job is not None
assert job.name == config.JOB_DELETE_MAILBOX assert job.name == JobType.DELETE_MAILBOX.value
assert job.payload["mailbox_id"] == mailbox.id assert job.payload["mailbox_id"] == mailbox.id
assert job.payload["transfer_mailbox_id"] == transfer_mailbox.id assert job.payload["transfer_mailbox_id"] == transfer_mailbox.id
mailbox_utils.delete_mailbox(user, mailbox.id, transfer_mailbox_id=None) mailbox_utils.delete_mailbox(user, mailbox.id, transfer_mailbox_id=None)
job = Session.query(Job).order_by(Job.id.desc()).first() job = Session.query(Job).order_by(Job.id.desc()).first()
assert job is not None assert job is not None
assert job.name == config.JOB_DELETE_MAILBOX assert job.name == JobType.DELETE_MAILBOX.value
assert job.payload["mailbox_id"] == mailbox.id assert job.payload["mailbox_id"] == mailbox.id
assert job.payload["transfer_mailbox_id"] is None assert job.payload["transfer_mailbox_id"] is None

View File

@ -36,7 +36,9 @@ def test_generate_email(flask_client):
def test_profile_picture_url(flask_client): def test_profile_picture_url(flask_client):
user = create_new_user() user = create_new_user()
assert user.profile_picture_url() == "http://sl.test/static/default-avatar.png" assert (
user.profile_picture_url() == f"http://{EMAIL_DOMAIN}/static/default-avatar.png"
)
def test_suggested_emails_for_user_who_cannot_create_new_alias(flask_client): def test_suggested_emails_for_user_who_cannot_create_new_alias(flask_client):
@ -303,7 +305,7 @@ def test_create_contact_for_noreply(flask_client):
Contact.create( Contact.create(
user_id=user.id, user_id=user.id,
alias_id=alias.id, alias_id=alias.id,
website_email=f"{random.random()}@contact.test", website_email=f"{random.random()}@contact.lan",
reply_email=NOREPLY, reply_email=NOREPLY,
commit=True, commit=True,
) )

View File

@ -1,5 +1,6 @@
import arrow import arrow
from app.config import EMAIL_DOMAIN
from app.db import Session from app.db import Session
from app.models import CoinbaseSubscription from app.models import CoinbaseSubscription
from app.payments.coinbase import handle_coinbase_event from app.payments.coinbase import handle_coinbase_event
@ -11,7 +12,7 @@ def test_redirect_login_page(flask_client):
rv = flask_client.get("/") rv = flask_client.get("/")
assert rv.status_code == 302 assert rv.status_code == 302
assert rv.location == "http://sl.test/auth/login" assert rv.location == f"http://{EMAIL_DOMAIN}/auth/login"
def test_coinbase_webhook(flask_client): def test_coinbase_webhook(flask_client):

View File

@ -16,7 +16,7 @@ from app.utils import random_string
def create_new_user(email: Optional[str] = None, name: Optional[str] = None) -> User: def create_new_user(email: Optional[str] = None, name: Optional[str] = None) -> User:
if not email: if not email:
email = f"user_{random_token(10)}@mailbox.test" email = f"user_{random_token(10)}@mailbox.lan"
if not name: if not name:
name = "Test User" name = "Test User"
# new user has a different email address # new user has a different email address
@ -60,7 +60,7 @@ def login(flask_client, user: Optional[User] = None) -> User:
def random_domain() -> str: def random_domain() -> str:
return random_token() + ".test" return random_token() + ".lan"
def random_token(length: int = 10) -> str: def random_token(length: int = 10) -> str:
@ -89,3 +89,11 @@ def load_eml_file(
def random_email() -> str: def random_email() -> str:
return "{rand}@{rand}.com".format(rand=random_string(20)) return "{rand}@{rand}.com".format(rand=random_string(20))
def fix_rate_limit_after_request():
from flask import g
from app.extensions import limiter
g._rate_limiting_complete = False
setattr(g, "%s_rate_limiting_complete" % limiter._key_prefix, False)

635
app/uv.lock generated
View File

@ -1,51 +1,62 @@
version = 1 version = 1
requires-python = ">=3.10, <4" requires-python = ">=3.12, <4"
[[package]]
name = "aiohappyeyeballs"
version = "2.4.6"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/08/07/508f9ebba367fc3370162e53a3cfd12f5652ad79f0e0bfdf9f9847c6f159/aiohappyeyeballs-2.4.6.tar.gz", hash = "sha256:9b05052f9042985d32ecbe4b59a77ae19c006a78f1344d7fdad69d28ded3d0b0", size = 21726 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/44/4c/03fb05f56551828ec67ceb3665e5dc51638042d204983a03b0a1541475b6/aiohappyeyeballs-2.4.6-py3-none-any.whl", hash = "sha256:147ec992cf873d74f5062644332c539fcd42956dc69453fe5204195e560517e1", size = 14543 },
]
[[package]] [[package]]
name = "aiohttp" name = "aiohttp"
version = "3.8.4" version = "3.11.13"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "aiohappyeyeballs" },
{ name = "aiosignal" }, { name = "aiosignal" },
{ name = "async-timeout" },
{ name = "attrs" }, { name = "attrs" },
{ name = "charset-normalizer" },
{ name = "frozenlist" }, { name = "frozenlist" },
{ name = "multidict" }, { name = "multidict" },
{ name = "propcache" },
{ name = "yarl" }, { name = "yarl" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/c2/fd/1ff4da09ca29d8933fda3f3514980357e25419ce5e0f689041edb8f17dab/aiohttp-3.8.4.tar.gz", hash = "sha256:bf2e1a9162c1e441bf805a1fd166e249d574ca04e03b34f97e2928769e91ab5c", size = 7338512 } sdist = { url = "https://files.pythonhosted.org/packages/b3/3f/c4a667d184c69667b8f16e0704127efc5f1e60577df429382b4d95fd381e/aiohttp-3.11.13.tar.gz", hash = "sha256:8ce789231404ca8fff7f693cdce398abf6d90fd5dae2b1847477196c243b1fbb", size = 7674284 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/ed/18/43720f71f5496544e69f8723534d8b5fa6de8b1ad2f64a5d7e797c4ee6e7/aiohttp-3.8.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5ce45967538fb747370308d3145aa68a074bdecb4f3a300869590f725ced69c1", size = 512619 }, { url = "https://files.pythonhosted.org/packages/9a/a9/6657664a55f78db8767e396cc9723782ed3311eb57704b0a5dacfa731916/aiohttp-3.11.13-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2eabb269dc3852537d57589b36d7f7362e57d1ece308842ef44d9830d2dc3c90", size = 705054 },
{ url = "https://files.pythonhosted.org/packages/8a/92/1ce3215bcde9cb1da929bf78742269ed2371e5c22190e2886df4bc0251ca/aiohttp-3.8.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b744c33b6f14ca26b7544e8d8aadff6b765a80ad6164fb1a430bbadd593dfb1a", size = 358131 }, { url = "https://files.pythonhosted.org/packages/3b/06/f7df1fe062d16422f70af5065b76264f40b382605cf7477fa70553a9c9c1/aiohttp-3.11.13-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7b77ee42addbb1c36d35aca55e8cc6d0958f8419e458bb70888d8c69a4ca833d", size = 464440 },
{ url = "https://files.pythonhosted.org/packages/bf/9c/f2fc160f21fd3ea98f00da1f285bb6b24c53863ee30e67901f92b8a8f6c6/aiohttp-3.8.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a45865451439eb320784918617ba54b7a377e3501fb70402ab84d38c2cd891b", size = 336858 }, { url = "https://files.pythonhosted.org/packages/22/3a/8773ea866735754004d9f79e501fe988bdd56cfac7fdecbc8de17fc093eb/aiohttp-3.11.13-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55789e93c5ed71832e7fac868167276beadf9877b85697020c46e9a75471f55f", size = 456394 },
{ url = "https://files.pythonhosted.org/packages/6b/33/68ba7406db6ea62f34cfacdb86eecbef1e3fc81f5f8335f0c8e11157ddbc/aiohttp-3.8.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86d42d7cba1cec432d47ab13b6637bee393a10f664c425ea7b305d1301ca1a3", size = 1004069 }, { url = "https://files.pythonhosted.org/packages/7f/61/8e2f2af2327e8e475a2b0890f15ef0bbfd117e321cce1e1ed210df81bbac/aiohttp-3.11.13-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c929f9a7249a11e4aa5c157091cfad7f49cc6b13f4eecf9b747104befd9f56f2", size = 1682752 },
{ url = "https://files.pythonhosted.org/packages/c7/b8/e886ff5e85698200d8b9667908a6f0e0439dc4fd165c4875b6efbbfeedd1/aiohttp-3.8.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee3c36df21b5714d49fc4580247947aa64bcbe2939d1b77b4c8dcb8f6c9faecc", size = 1019148 }, { url = "https://files.pythonhosted.org/packages/24/ed/84fce816bc8da39aa3f6c1196fe26e47065fea882b1a67a808282029c079/aiohttp-3.11.13-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d33851d85537bbf0f6291ddc97926a754c8f041af759e0aa0230fe939168852b", size = 1737375 },
{ url = "https://files.pythonhosted.org/packages/c9/6e/c68d4618e2f15248deddc992ce35d979b52df9a9b8ecbc00ae9ed83c6316/aiohttp-3.8.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:176a64b24c0935869d5bbc4c96e82f89f643bcdf08ec947701b9dbb3c956b7dd", size = 1073573 }, { url = "https://files.pythonhosted.org/packages/d9/de/35a5ba9e3d21ebfda1ebbe66f6cc5cbb4d3ff9bd6a03e5e8a788954f8f27/aiohttp-3.11.13-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9229d8613bd8401182868fe95688f7581673e1c18ff78855671a4b8284f47bcb", size = 1793660 },
{ url = "https://files.pythonhosted.org/packages/81/97/90debed02e5be15d4e63fb96ba930e35b66d4e518fa7065dd442345a448b/aiohttp-3.8.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c844fd628851c0bc309f3c801b3a3d58ce430b2ce5b359cd918a5a76d0b20cb5", size = 1000618 }, { url = "https://files.pythonhosted.org/packages/ff/fe/0f650a8c7c72c8a07edf8ab164786f936668acd71786dd5885fc4b1ca563/aiohttp-3.11.13-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:669dd33f028e54fe4c96576f406ebb242ba534dd3a981ce009961bf49960f117", size = 1692233 },
{ url = "https://files.pythonhosted.org/packages/b1/f2/81258cc72112956bca0bcf9f539cd6f503e1a631f5bf9307ae3cf21e05a5/aiohttp-3.8.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5393fb786a9e23e4799fec788e7e735de18052f83682ce2dfcabaf1c00c2c08e", size = 971166 }, { url = "https://files.pythonhosted.org/packages/a8/20/185378b3483f968c6303aafe1e33b0da0d902db40731b2b2b2680a631131/aiohttp-3.11.13-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c1b20a1ace54af7db1f95af85da530fe97407d9063b7aaf9ce6a32f44730778", size = 1619708 },
{ url = "https://files.pythonhosted.org/packages/3a/42/57dc93de564725208a1ea729a717f2608f0091a11e34ecd2e23863b9ef35/aiohttp-3.8.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e4b09863aae0dc965c3ef36500d891a3ff495a2ea9ae9171e4519963c12ceefd", size = 1017966 }, { url = "https://files.pythonhosted.org/packages/a4/f9/d9c181750980b17e1e13e522d7e82a8d08d3d28a2249f99207ef5d8d738f/aiohttp-3.11.13-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5724cc77f4e648362ebbb49bdecb9e2b86d9b172c68a295263fa072e679ee69d", size = 1641802 },
{ url = "https://files.pythonhosted.org/packages/88/5f/4fec6a1238fda86716374910aa5a1a4953eca4cf30b582c94efce9058729/aiohttp-3.8.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:adfbc22e87365a6e564c804c58fc44ff7727deea782d175c33602737b7feadb6", size = 985792 }, { url = "https://files.pythonhosted.org/packages/50/c7/1cb46b72b1788710343b6e59eaab9642bd2422f2d87ede18b1996e0aed8f/aiohttp-3.11.13-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:aa36c35e94ecdb478246dd60db12aba57cfcd0abcad43c927a8876f25734d496", size = 1684678 },
{ url = "https://files.pythonhosted.org/packages/25/b4/4373590c8bd438ccca4c916bb6a65dc3366e4f030a17359f4adb0ff605ce/aiohttp-3.8.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:147ae376f14b55f4f3c2b118b95be50a369b89b38a971e80a17c3fd623f280c9", size = 1036137 }, { url = "https://files.pythonhosted.org/packages/71/87/89b979391de840c5d7c34e78e1148cc731b8aafa84b6a51d02f44b4c66e2/aiohttp-3.11.13-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9b5b37c863ad5b0892cc7a4ceb1e435e5e6acd3f2f8d3e11fa56f08d3c67b820", size = 1646921 },
{ url = "https://files.pythonhosted.org/packages/5c/c5/26cd1522e373484b1648da913be6f084ce4d7473ecebe503533a3bb85536/aiohttp-3.8.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:eafb3e874816ebe2a92f5e155f17260034c8c341dad1df25672fb710627c6949", size = 1084638 }, { url = "https://files.pythonhosted.org/packages/a7/db/a463700ac85b72f8cf68093e988538faaf4e865e3150aa165cf80ee29d6e/aiohttp-3.11.13-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e06cf4852ce8c4442a59bae5a3ea01162b8fcb49ab438d8548b8dc79375dad8a", size = 1702493 },
{ url = "https://files.pythonhosted.org/packages/29/6e/a15e39b2ae4305336bfc00540bde991fff73c60e7e8390b9e82a6ec485f2/aiohttp-3.8.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6cc15d58053c76eacac5fa9152d7d84b8d67b3fde92709195cb984cfb3475ea", size = 1013223 }, { url = "https://files.pythonhosted.org/packages/b8/32/1084e65da3adfb08c7e1b3e94f3e4ded8bd707dee265a412bc377b7cd000/aiohttp-3.11.13-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5194143927e494616e335d074e77a5dac7cd353a04755330c9adc984ac5a628e", size = 1735004 },
{ url = "https://files.pythonhosted.org/packages/66/90/1c0ff493317bae426c1aec5da9cbcd9baea4a8d526e4beae892896aefa64/aiohttp-3.8.4-cp310-cp310-win32.whl", hash = "sha256:59f029a5f6e2d679296db7bee982bb3d20c088e52a2977e3175faf31d6fb75d1", size = 304642 }, { url = "https://files.pythonhosted.org/packages/a0/bb/a634cbdd97ce5d05c2054a9a35bfc32792d7e4f69d600ad7e820571d095b/aiohttp-3.11.13-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:afcb6b275c2d2ba5d8418bf30a9654fa978b4f819c2e8db6311b3525c86fe637", size = 1694964 },
{ url = "https://files.pythonhosted.org/packages/8e/cd/f8f8d801fa5c0cd1d6259fa71c9394437c5c14f8936aeff6f6c3233fd596/aiohttp-3.8.4-cp310-cp310-win_amd64.whl", hash = "sha256:fe7ba4a51f33ab275515f66b0a236bcde4fb5561498fe8f898d4e549b2e4509f", size = 319844 }, { url = "https://files.pythonhosted.org/packages/fd/cf/7d29db4e5c28ec316e5d2ac9ac9df0e2e278e9ea910e5c4205b9b64c2c42/aiohttp-3.11.13-cp312-cp312-win32.whl", hash = "sha256:7104d5b3943c6351d1ad7027d90bdd0ea002903e9f610735ac99df3b81f102ee", size = 411746 },
{ url = "https://files.pythonhosted.org/packages/84/18/86e01032e305637d991b23b37bb39170ebaf8b8c4d0ea458b75f4302ed86/aiohttp-3.8.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d8ef1a630519a26d6760bc695842579cb09e373c5f227a21b67dc3eb16cfea4", size = 505614 }, { url = "https://files.pythonhosted.org/packages/65/a9/13e69ad4fd62104ebd94617f9f2be58231b50bb1e6bac114f024303ac23b/aiohttp-3.11.13-cp312-cp312-win_amd64.whl", hash = "sha256:47dc018b1b220c48089b5b9382fbab94db35bef2fa192995be22cbad3c5730c8", size = 438078 },
{ url = "https://files.pythonhosted.org/packages/91/71/99cd9ebe197cbebf46ba1f00573120802ace2869e1f63ff0b00acc5b4982/aiohttp-3.8.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b3f2e06a512e94722886c0827bee9807c86a9f698fac6b3aee841fab49bbfb4", size = 355149 }, { url = "https://files.pythonhosted.org/packages/87/dc/7d58d33cec693f1ddf407d4ab975445f5cb507af95600f137b81683a18d8/aiohttp-3.11.13-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9862d077b9ffa015dbe3ce6c081bdf35135948cb89116e26667dd183550833d1", size = 698372 },
{ url = "https://files.pythonhosted.org/packages/08/30/3dafa445e7f6358aa1c5ffde987ca4eba6bd7b9038e07ec01732933312fb/aiohttp-3.8.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a80464982d41b1fbfe3154e440ba4904b71c1a53e9cd584098cd41efdb188ef", size = 332872 }, { url = "https://files.pythonhosted.org/packages/84/e7/5d88514c9e24fbc8dd6117350a8ec4a9314f4adae6e89fe32e3e639b0c37/aiohttp-3.11.13-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fbfef0666ae9e07abfa2c54c212ac18a1f63e13e0760a769f70b5717742f3ece", size = 461057 },
{ url = "https://files.pythonhosted.org/packages/88/41/2a8453255ebb0864d81745d24bee03fff71b7b76ed2f846126a6f5930ee4/aiohttp-3.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b631e26df63e52f7cce0cce6507b7a7f1bc9b0c501fcde69742130b32e8782f", size = 1035384 }, { url = "https://files.pythonhosted.org/packages/96/1a/8143c48a929fa00c6324f85660cb0f47a55ed9385f0c1b72d4b8043acf8e/aiohttp-3.11.13-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:93a1f7d857c4fcf7cabb1178058182c789b30d85de379e04f64c15b7e88d66fb", size = 453340 },
{ url = "https://files.pythonhosted.org/packages/fc/51/962b938a296eaf08d1cfa80ad5d42670b15aa868f897c0e71ea1cf9d1f0e/aiohttp-3.8.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f43255086fe25e36fd5ed8f2ee47477408a73ef00e804cb2b5cba4bf2ac7f5e", size = 1045448 }, { url = "https://files.pythonhosted.org/packages/2f/1c/b8010e4d65c5860d62681088e5376f3c0a940c5e3ca8989cae36ce8c3ea8/aiohttp-3.11.13-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba40b7ae0f81c7029583a338853f6607b6d83a341a3dcde8bed1ea58a3af1df9", size = 1665561 },
{ url = "https://files.pythonhosted.org/packages/33/a7/c2304859f11531f6be5c464e3d8cdd85cbc196f0754e0c450ef76c297c7c/aiohttp-3.8.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d347a172f866cd1d93126d9b239fcbe682acb39b48ee0873c73c933dd23bd0f", size = 1102557 }, { url = "https://files.pythonhosted.org/packages/19/ed/a68c3ab2f92fdc17dfc2096117d1cfaa7f7bdded2a57bacbf767b104165b/aiohttp-3.11.13-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5b95787335c483cd5f29577f42bbe027a412c5431f2f80a749c80d040f7ca9f", size = 1718335 },
{ url = "https://files.pythonhosted.org/packages/a0/e4/a383cb4b68324b39f7d95cdfebdc8a66a88201c3646a87a00140d778c5ba/aiohttp-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3fec6a4cb5551721cdd70473eb009d90935b4063acc5f40905d40ecfea23e05", size = 1026820 }, { url = "https://files.pythonhosted.org/packages/27/4f/3a0b6160ce663b8ebdb65d1eedff60900cd7108838c914d25952fe2b909f/aiohttp-3.11.13-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7d474c5c1f0b9405c1565fafdc4429fa7d986ccbec7ce55bc6a330f36409cad", size = 1775522 },
{ url = "https://files.pythonhosted.org/packages/68/28/e46516d7ca64146e50e595e0364530e4080da0d9f7640b43b687836ebd2f/aiohttp-3.8.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80a37fe8f7c1e6ce8f2d9c411676e4bc633a8462844e38f46156d07a7d401654", size = 985493 }, { url = "https://files.pythonhosted.org/packages/0b/58/9da09291e19696c452e7224c1ce8c6d23a291fe8cd5c6b247b51bcda07db/aiohttp-3.11.13-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e83fb1991e9d8982b3b36aea1e7ad27ea0ce18c14d054c7a404d68b0319eebb", size = 1677566 },
{ url = "https://files.pythonhosted.org/packages/e6/4a/ad8fde32ba6bab15c15eaf770f10a10d0bfe8dd575fc96981ad1b615f509/aiohttp-3.8.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d1e6a862b76f34395a985b3cd39a0d949ca80a70b6ebdea37d3ab39ceea6698a", size = 1046399 }, { url = "https://files.pythonhosted.org/packages/3d/18/6184f2bf8bbe397acbbbaa449937d61c20a6b85765f48e5eddc6d84957fe/aiohttp-3.11.13-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4586a68730bd2f2b04a83e83f79d271d8ed13763f64b75920f18a3a677b9a7f0", size = 1603590 },
{ url = "https://files.pythonhosted.org/packages/d9/b8/5225fbcca70348708eaf939d6821f21cbbfa12290d6314b02608a94cc38c/aiohttp-3.8.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cd468460eefef601ece4428d3cf4562459157c0f6523db89365202c31b6daebb", size = 1004400 }, { url = "https://files.pythonhosted.org/packages/04/94/91e0d1ca0793012ccd927e835540aa38cca98bdce2389256ab813ebd64a3/aiohttp-3.11.13-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fe4eb0e7f50cdb99b26250d9328faef30b1175a5dbcfd6d0578d18456bac567", size = 1618688 },
{ url = "https://files.pythonhosted.org/packages/ab/9d/3bdb23a925d7ba67acc8a6158191fe8874b1dda6745bb67ee40f493480e4/aiohttp-3.8.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:618c901dd3aad4ace71dfa0f5e82e88b46ef57e3239fc7027773cb6d4ed53531", size = 1065370 }, { url = "https://files.pythonhosted.org/packages/71/85/d13c3ea2e48a10b43668305d4903838834c3d4112e5229177fbcc23a56cd/aiohttp-3.11.13-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2a8a6bc19818ac3e5596310ace5aa50d918e1ebdcc204dc96e2f4d505d51740c", size = 1658053 },
{ url = "https://files.pythonhosted.org/packages/8a/06/be76e45900b729964a595246b1a9cd7b7d22ca015203b4b74847b4424ee9/aiohttp-3.8.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:652b1bff4f15f6287550b4670546a2947f2a4575b6c6dff7760eafb22eacbf0b", size = 1112366 }, { url = "https://files.pythonhosted.org/packages/12/6a/3242a35100de23c1e8d9e05e8605e10f34268dee91b00d9d1e278c58eb80/aiohttp-3.11.13-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7f27eec42f6c3c1df09cfc1f6786308f8b525b8efaaf6d6bd76c1f52c6511f6a", size = 1616917 },
{ url = "https://files.pythonhosted.org/packages/40/4d/49cfd9cd450196601facd6f1f6ea551856dcd41b2061851c06c66885cca2/aiohttp-3.8.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80575ba9377c5171407a06d0196b2310b679dc752d02a1fcaa2bc20b235dbf24", size = 1038406 }, { url = "https://files.pythonhosted.org/packages/f5/b3/3f99b6f0a9a79590a7ba5655dbde8408c685aa462247378c977603464d0a/aiohttp-3.11.13-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:2a4a13dfbb23977a51853b419141cd0a9b9573ab8d3a1455c6e63561387b52ff", size = 1685872 },
{ url = "https://files.pythonhosted.org/packages/c8/6d/96781308f03ad27d849524053f63285cd53dc178b9018e8db148ed46a8c6/aiohttp-3.8.4-cp311-cp311-win32.whl", hash = "sha256:bbcf1a76cf6f6dacf2c7f4d2ebd411438c275faa1dc0c68e46eb84eebd05dd7d", size = 304029 }, { url = "https://files.pythonhosted.org/packages/8a/2e/99672181751f280a85e24fcb9a2c2469e8b1a0de1746b7b5c45d1eb9a999/aiohttp-3.11.13-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:02876bf2f69b062584965507b07bc06903c2dc93c57a554b64e012d636952654", size = 1715719 },
{ url = "https://files.pythonhosted.org/packages/c5/22/6bd9f9a90807ef11e4c4a3ec19099e24f2b6f4040ee568f71ed0e5fdb6d1/aiohttp-3.8.4-cp311-cp311-win_amd64.whl", hash = "sha256:6e74dd54f7239fcffe07913ff8b964e28b712f09846e20de78676ce2a3dc0bfc", size = 317232 }, { url = "https://files.pythonhosted.org/packages/7a/cd/68030356eb9a7d57b3e2823c8a852709d437abb0fbff41a61ebc351b7625/aiohttp-3.11.13-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b992778d95b60a21c4d8d4a5f15aaab2bd3c3e16466a72d7f9bfd86e8cea0d4b", size = 1673166 },
{ url = "https://files.pythonhosted.org/packages/03/61/425397a9a2839c609d09fdb53d940472f316a2dbeaa77a35b2628dae6284/aiohttp-3.11.13-cp313-cp313-win32.whl", hash = "sha256:507ab05d90586dacb4f26a001c3abf912eb719d05635cbfad930bdbeb469b36c", size = 410615 },
{ url = "https://files.pythonhosted.org/packages/9c/54/ebb815bc0fe057d8e7a11c086c479e972e827082f39aeebc6019dd4f0862/aiohttp-3.11.13-cp313-cp313-win_amd64.whl", hash = "sha256:5ceb81a4db2decdfa087381b5fc5847aa448244f973e5da232610304e199e7b2", size = 436452 },
] ]
[[package]] [[package]]
@ -147,15 +158,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b6/38/1b2188bea6b5346ea2f97f063c99fdadb36707a7b3a95ff4fe73e242c33c/astroid-2.11.6-py3-none-any.whl", hash = "sha256:ba33a82a9a9c06a5ceed98180c5aab16e29c285b828d94696bf32d6015ea82a9", size = 251042 }, { url = "https://files.pythonhosted.org/packages/b6/38/1b2188bea6b5346ea2f97f063c99fdadb36707a7b3a95ff4fe73e242c33c/astroid-2.11.6-py3-none-any.whl", hash = "sha256:ba33a82a9a9c06a5ceed98180c5aab16e29c285b828d94696bf32d6015ea82a9", size = 251042 },
] ]
[[package]]
name = "async-timeout"
version = "4.0.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/54/6e/9678f7b2993537452710ffb1750c62d2c26df438aa621ad5fa9d1507a43a/async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15", size = 8221 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d6/c1/8991e7c5385b897b8c020cdaad718c5b087a6626d1d11a23e1ea87e325a7/async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c", size = 5763 },
]
[[package]] [[package]]
name = "atomicwrites" name = "atomicwrites"
version = "1.4.1" version = "1.4.1"
@ -220,19 +222,17 @@ dependencies = [
] ]
sdist = { url = "https://files.pythonhosted.org/packages/42/58/8a3443a5034685152270f9012a9d196c9f165791ed3f2777307708b15f6c/black-22.1.0.tar.gz", hash = "sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5", size = 559521 } sdist = { url = "https://files.pythonhosted.org/packages/42/58/8a3443a5034685152270f9012a9d196c9f165791ed3f2777307708b15f6c/black-22.1.0.tar.gz", hash = "sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5", size = 559521 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/fd/ae/c401710dabb32bac39d799417ab25bd59ffb1336652bcb04f4bdd7126b79/black-22.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6", size = 2391069 },
{ url = "https://files.pythonhosted.org/packages/40/4e/fa8299630a4957f543675b2d8999a80428a7e35a66ec21e8a7d250c97dab/black-22.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2ff96450d3ad9ea499fc4c60e425a1439c2120cbbc1ab959ff20f7c76ec7e866", size = 1341037 },
{ url = "https://files.pythonhosted.org/packages/b5/cb/d9799d8bd5f95e36ea4a04a80a0a48c24c638734a257d3b22fa16ec9a4ac/black-22.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e21e1f1efa65a50e3960edd068b6ae6d64ad6235bd8bfea116a03b21836af71", size = 1214880 },
{ url = "https://files.pythonhosted.org/packages/b3/4b/e490650ee69bd53bad29956969346fa9d345422eb9ed9e201ec9533688eb/black-22.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2f69158a7d120fd641d1fa9a921d898e20d52e44a74a6fbbcc570a62a6bc8ab", size = 1476248 },
{ url = "https://files.pythonhosted.org/packages/28/2d/fbc5948cfca9f6e8ccb4f97d27eb96f70a6884fc6b71a8c64b89b96be3de/black-22.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:228b5ae2c8e3d6227e4bde5920d2fc66cc3400fde7bcc74f480cb07ef0b570d5", size = 1140556 },
{ url = "https://files.pythonhosted.org/packages/a5/59/bd6d44da2b364fd2bd7a0b2ce2edfe200b79faad1cde14ce5ef13d504393/black-22.1.0-py3-none-any.whl", hash = "sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d", size = 160408 }, { url = "https://files.pythonhosted.org/packages/a5/59/bd6d44da2b364fd2bd7a0b2ce2edfe200b79faad1cde14ce5ef13d504393/black-22.1.0-py3-none-any.whl", hash = "sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d", size = 160408 },
] ]
[[package]] [[package]]
name = "blinker" name = "blinker"
version = "1.4" version = "1.9.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/1b/51/e2a9f3b757eb802f61dc1f2b09c8c99f6eb01cf06416c0671253536517b6/blinker-1.4.tar.gz", hash = "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6", size = 111476 } sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458 },
]
[[package]] [[package]]
name = "boto3" name = "boto3"
@ -295,30 +295,6 @@ dependencies = [
] ]
sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/90/07/f44ca684db4e4f08a3fdc6eeb9a0d15dc6883efc7b8c90357fdbf74e186c/cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", size = 182191 },
{ url = "https://files.pythonhosted.org/packages/08/fd/cc2fedbd887223f9f5d170c96e57cbf655df9831a6546c1727ae13fa977a/cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", size = 178592 },
{ url = "https://files.pythonhosted.org/packages/de/cc/4635c320081c78d6ffc2cab0a76025b691a91204f4aa317d568ff9280a2d/cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", size = 426024 },
{ url = "https://files.pythonhosted.org/packages/b6/7b/3b2b250f3aab91abe5f8a51ada1b717935fdaec53f790ad4100fe2ec64d1/cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", size = 448188 },
{ url = "https://files.pythonhosted.org/packages/d3/48/1b9283ebbf0ec065148d8de05d647a986c5f22586b18120020452fff8f5d/cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", size = 455571 },
{ url = "https://files.pythonhosted.org/packages/40/87/3b8452525437b40f39ca7ff70276679772ee7e8b394934ff60e63b7b090c/cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", size = 436687 },
{ url = "https://files.pythonhosted.org/packages/8d/fb/4da72871d177d63649ac449aec2e8a29efe0274035880c7af59101ca2232/cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", size = 446211 },
{ url = "https://files.pythonhosted.org/packages/ab/a0/62f00bcb411332106c02b663b26f3545a9ef136f80d5df746c05878f8c4b/cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", size = 461325 },
{ url = "https://files.pythonhosted.org/packages/36/83/76127035ed2e7e27b0787604d99da630ac3123bfb02d8e80c633f218a11d/cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", size = 438784 },
{ url = "https://files.pythonhosted.org/packages/21/81/a6cd025db2f08ac88b901b745c163d884641909641f9b826e8cb87645942/cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", size = 461564 },
{ url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804 },
{ url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299 },
{ url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264 },
{ url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651 },
{ url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259 },
{ url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200 },
{ url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235 },
{ url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721 },
{ url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242 },
{ url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999 },
{ url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242 },
{ url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604 },
{ url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727 },
{ url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400 },
{ url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 }, { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 },
{ url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 }, { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 },
{ url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 }, { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 },
@ -361,15 +337,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691", size = 133356 }, { url = "https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691", size = 133356 },
] ]
[[package]]
name = "charset-normalizer"
version = "2.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/93/1d/d9392056df6670ae2a29fcb04cfa5cee9f6fbde7311a1bb511d4115e9b7a/charset-normalizer-2.1.0.tar.gz", hash = "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413", size = 81769 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/94/69/64b11e8c2fb21f08634468caef885112e682b0ebe2908e74d3616eb1c113/charset_normalizer-2.1.0-py3-none-any.whl", hash = "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5", size = 39548 },
]
[[package]] [[package]]
name = "click" name = "click"
version = "8.0.3" version = "8.0.3"
@ -421,23 +388,6 @@ name = "coverage"
version = "6.4.2" version = "6.4.2"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ea/34/5a4f7a48da3be173273cd9b866c998eb59e234da2ee4a30c1068e85c0e99/coverage-6.4.2.tar.gz", hash = "sha256:6c3ccfe89c36f3e5b9837b9ee507472310164f352c9fe332120b764c9d60adbe", size = 721847 } sdist = { url = "https://files.pythonhosted.org/packages/ea/34/5a4f7a48da3be173273cd9b866c998eb59e234da2ee4a30c1068e85c0e99/coverage-6.4.2.tar.gz", hash = "sha256:6c3ccfe89c36f3e5b9837b9ee507472310164f352c9fe332120b764c9d60adbe", size = 721847 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/68/8d/8218b3604ca937f2d1a4b05033de4c5dc92adfc0262e54636ad21c67a132/coverage-6.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a9032f9b7d38bdf882ac9f66ebde3afb8145f0d4c24b2e600bc4c6304aafb87e", size = 184295 },
{ url = "https://files.pythonhosted.org/packages/97/16/d27ebd964fa8099ece60a66bd9766c906a3c017462060799ede33905900a/coverage-6.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e0524adb49c716ca763dbc1d27bedce36b14f33e6b8af6dba56886476b42957c", size = 184513 },
{ url = "https://files.pythonhosted.org/packages/11/89/8d8ab7adfef71d9c7da1672328d34ec6c733bf12eeddd6aab880596b50eb/coverage-6.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4548be38a1c810d79e097a38107b6bf2ff42151900e47d49635be69943763d8", size = 213103 },
{ url = "https://files.pythonhosted.org/packages/aa/21/01d0421d493eddfc5bfd4cb25902c5c685f2355474da98a9232971a2e7f5/coverage-6.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f23876b018dfa5d3e98e96f5644b109090f16a4acb22064e0f06933663005d39", size = 211426 },
{ url = "https://files.pythonhosted.org/packages/96/1d/0b615e00ab0f78474112b9ef63605d7b0053900746a5c2592f011e850b93/coverage-6.4.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fe75dcfcb889b6800f072f2af5a331342d63d0c1b3d2bf0f7b4f6c353e8c9c0", size = 212295 },
{ url = "https://files.pythonhosted.org/packages/a8/b6/3a235f3c2a186039d5d1ea30e538b9a759e43fad9221c26b79c6f06c6bf1/coverage-6.4.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2f8553878a24b00d5ab04b7a92a2af50409247ca5c4b7a2bf4eabe94ed20d3ee", size = 218219 },
{ url = "https://files.pythonhosted.org/packages/35/1d/9b01738822e5f472ded472904b3feed4eb7354f724ae5d48ca10608d30ff/coverage-6.4.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d774d9e97007b018a651eadc1b3970ed20237395527e22cbeb743d8e73e0563d", size = 216464 },
{ url = "https://files.pythonhosted.org/packages/ec/0b/7eff35443ce30d957e582ea7d4040d1d107e5e392ad68e4ce2a01d20525e/coverage-6.4.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d56f105592188ce7a797b2bd94b4a8cb2e36d5d9b0d8a1d2060ff2a71e6b9bbc", size = 217675 },
{ url = "https://files.pythonhosted.org/packages/05/48/d5f97f5cef736aedefcca7534f600ca8434224018fb33009d333d008e6f5/coverage-6.4.2-cp310-cp310-win32.whl", hash = "sha256:d230d333b0be8042ac34808ad722eabba30036232e7a6fb3e317c49f61c93386", size = 186623 },
{ url = "https://files.pythonhosted.org/packages/58/7a/1c2eb46936a3a6f5be715d6b40775f675ef424137010fb58634eeba08aab/coverage-6.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:5ef42e1db047ca42827a85e34abe973971c635f83aed49611b7f3ab49d0130f0", size = 187537 },
]
[package.optional-dependencies]
toml = [
{ name = "tomli", marker = "python_full_version <= '3.11'" },
]
[[package]] [[package]]
name = "crontab" name = "crontab"
@ -532,7 +482,6 @@ dependencies = [
{ name = "pathspec" }, { name = "pathspec" },
{ name = "pyyaml" }, { name = "pyyaml" },
{ name = "regex" }, { name = "regex" },
{ name = "tomli", marker = "python_full_version < '3.11'" },
{ name = "tqdm" }, { name = "tqdm" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/c4/a8/b8ed0b5e924985d3b4272940f785a7bf5baa41713dc30a0c087939aaf7c8/djlint-1.34.1.tar.gz", hash = "sha256:db93fa008d19eaadb0454edf1704931d14469d48508daba2df9941111f408346", size = 44066 } sdist = { url = "https://files.pythonhosted.org/packages/c4/a8/b8ed0b5e924985d3b4272940f785a7bf5baa41713dc30a0c087939aaf7c8/djlint-1.34.1.tar.gz", hash = "sha256:db93fa008d19eaadb0454edf1704931d14469d48508daba2df9941111f408346", size = 44066 }
@ -551,11 +500,11 @@ sdist = { url = "https://files.pythonhosted.org/packages/b5/33/9c60f3a34d4d7237e
[[package]] [[package]]
name = "dnspython" name = "dnspython"
version = "2.0.0" version = "2.7.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/67/d0/639a9b5273103a18c5c68a7a9fc02b01cffa3403e72d553acec444f85d5b/dnspython-2.0.0.zip", hash = "sha256:044af09374469c3a39eeea1a146e8cac27daec951f1f1f157b1962fc7cb9d1b7", size = 324706 } sdist = { url = "https://files.pythonhosted.org/packages/b5/4a/263763cb2ba3816dd94b08ad3a33d5fdae34ecb856678773cc40a3605829/dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1", size = 345197 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/90/49/cb426577c28ca3e35332815b795a99e467523843fc83cc85ca0d6be2515a/dnspython-2.0.0-py3-none-any.whl", hash = "sha256:40bb3c24b9d4ec12500f0124288a65df232a3aa749bb0c39734b782873a2544d", size = 208262 }, { url = "https://files.pythonhosted.org/packages/68/1b/e0a87d256e40e8c888847551b20a017a6b98139178505dc7ffb96f04e954/dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86", size = 313632 },
] ]
[[package]] [[package]]
@ -569,15 +518,15 @@ wheels = [
[[package]] [[package]]
name = "email-validator" name = "email-validator"
version = "1.1.3" version = "2.2.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "dnspython" }, { name = "dnspython" },
{ name = "idna" }, { name = "idna" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/25/f3/017ab4619ee83e79fc1c9572ac601671cf9cfb33a0523021b46851b4d9a4/email_validator-1.1.3.tar.gz", hash = "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7", size = 24484 } sdist = { url = "https://files.pythonhosted.org/packages/48/ce/13508a1ec3f8bb981ae4ca79ea40384becc868bfae97fd1c942bb3a001b1/email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7", size = 48967 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/9e/e4/e01e92092fdac940f10fa4c8ac3481bf70fc74023a76f5c72020c9445e68/email_validator-1.1.3-py2.py3-none-any.whl", hash = "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b", size = 18318 }, { url = "https://files.pythonhosted.org/packages/d7/ee/bf0adb559ad3c786f12bcbc9296b3f5675f529199bef03e2df281fa1fadb/email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631", size = 33521 },
] ]
[[package]] [[package]]
@ -700,16 +649,16 @@ wheels = [
[[package]] [[package]]
name = "flask-limiter" name = "flask-limiter"
version = "1.4" version = "1.5"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "flask" }, { name = "flask" },
{ name = "limits" }, { name = "limits" },
{ name = "six" }, { name = "six" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/5e/ad/44302ae83d88091df2001eb9243df615d064736d45c13c867f1d892159fa/Flask-Limiter-1.4.tar.gz", hash = "sha256:021279c905a1e24f181377ab3be711be7541734b494f4e6db2b8edeba7601e48", size = 95593 } sdist = { url = "https://files.pythonhosted.org/packages/c1/a0/fd3203cb6186a58a275f2ad01ca715bc42a65876a128cc9931b0ba0f46ed/Flask-Limiter-1.5.tar.gz", hash = "sha256:f5816ebd606d41df39479b4f6f9b770d98d47a0801c8a513198aa436bb4139e7", size = 94964 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/1c/66/1bc848a3d37bed2a4c6cea7b7e39b830b2cd848dc7dde759926bb896f8e8/Flask_Limiter-1.4-py3-none-any.whl", hash = "sha256:f8a65a7874f48ff8df2ea5e86d5b85b48fcbae065ebeb5271b317fe68fcfa979", size = 15500 }, { url = "https://files.pythonhosted.org/packages/e4/ff/f2f922af0058561243f68c47fe90a34532883d29101543c518df5f7f79c8/Flask_Limiter-1.5-py3-none-any.whl", hash = "sha256:7cb3b4350874b2da8d3ff440413d16c4bfd1a26aedf3ad9ea68a1669945ae515", size = 15630 },
] ]
[[package]] [[package]]
@ -781,40 +730,41 @@ wheels = [
[[package]] [[package]]
name = "frozenlist" name = "frozenlist"
version = "1.3.3" version = "1.5.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e9/10/d629476346112b85c912527b9080944fd2c39a816c2225413dbc0bb6fcc0/frozenlist-1.3.3.tar.gz", hash = "sha256:58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a", size = 66571 } sdist = { url = "https://files.pythonhosted.org/packages/8f/ed/0f4cec13a93c02c47ec32d81d11c0c1efbadf4a471e3f3ce7cad366cbbd3/frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817", size = 39930 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/64/08/2e192aa0a8e4741da0284559e983d22f02d12ca2cc18598948b99414c4b6/frozenlist-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff8bf625fe85e119553b5383ba0fb6aa3d0ec2ae980295aaefa552374926b3f4", size = 61164 }, { url = "https://files.pythonhosted.org/packages/79/73/fa6d1a96ab7fd6e6d1c3500700963eab46813847f01ef0ccbaa726181dd5/frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21", size = 94026 },
{ url = "https://files.pythonhosted.org/packages/d7/4c/ada057ae7c93a60239945b9ef1ed1ad0a01fcdb7924e93efeb9932391768/frozenlist-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dfbac4c2dfcc082fcf8d942d1e49b6aa0766c19d3358bd86e2000bf0fa4a9cf0", size = 35975 }, { url = "https://files.pythonhosted.org/packages/ab/04/ea8bf62c8868b8eada363f20ff1b647cf2e93377a7b284d36062d21d81d1/frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d", size = 54150 },
{ url = "https://files.pythonhosted.org/packages/23/2f/2f2b21b5c45bdd17d4ea40648a9681a8a1fd32d4d50e56f77fb8fff6cb97/frozenlist-1.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b1c63e8d377d039ac769cd0926558bb7068a1f7abb0f003e3717ee003ad85530", size = 34534 }, { url = "https://files.pythonhosted.org/packages/d0/9a/8e479b482a6f2070b26bda572c5e6889bb3ba48977e81beea35b5ae13ece/frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e", size = 51927 },
{ url = "https://files.pythonhosted.org/packages/9f/89/6e073bbc2f48acbba807a30c09908408f556ba4c488bd3ff5be8e5cf0818/frozenlist-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fdfc24dcfce5b48109867c13b4cb15e4660e7bd7661741a391f821f23dfdca7", size = 148133 }, { url = "https://files.pythonhosted.org/packages/e3/12/2aad87deb08a4e7ccfb33600871bbe8f0e08cb6d8224371387f3303654d7/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a", size = 282647 },
{ url = "https://files.pythonhosted.org/packages/41/f1/03124919e61f2e46a13d51ccc5148fee54a80a5cb18b0e7a638e955d9705/frozenlist-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c926450857408e42f0bbc295e84395722ce74bae69a3b2aa2a65fe22cb14b99", size = 155019 }, { url = "https://files.pythonhosted.org/packages/77/f2/07f06b05d8a427ea0060a9cef6e63405ea9e0d761846b95ef3fb3be57111/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a", size = 289052 },
{ url = "https://files.pythonhosted.org/packages/df/a5/34eb83e73106b056454b6dee05d736ae462671e813212bfee2241f554f1b/frozenlist-1.3.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1841e200fdafc3d51f974d9d377c079a0694a8f06de2e67b48150328d66d5483", size = 151686 }, { url = "https://files.pythonhosted.org/packages/bd/9f/8bf45a2f1cd4aa401acd271b077989c9267ae8463e7c8b1eb0d3f561b65e/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee", size = 291719 },
{ url = "https://files.pythonhosted.org/packages/33/73/1dcadea68aaa904c9278f67e334bb88591c05a52a122536c41021d2a9ff5/frozenlist-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f470c92737afa7d4c3aacc001e335062d582053d4dbe73cda126f2d7031068dd", size = 142308 }, { url = "https://files.pythonhosted.org/packages/41/d1/1f20fd05a6c42d3868709b7604c9f15538a29e4f734c694c6bcfc3d3b935/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6", size = 267433 },
{ url = "https://files.pythonhosted.org/packages/49/0e/c57ad9178618cf81be0fbb8430f17cf05423403143819d3631c7c09744c2/frozenlist-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:783263a4eaad7c49983fe4b2e7b53fa9770c136c270d2d4bbb6d2192bf4d9caf", size = 149571 }, { url = "https://files.pythonhosted.org/packages/af/f2/64b73a9bb86f5a89fb55450e97cd5c1f84a862d4ff90d9fd1a73ab0f64a5/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e", size = 283591 },
{ url = "https://files.pythonhosted.org/packages/fd/b8/9ed4ed37b2c3269660a86a10a09b2fe49dbbd6973ac684804ece7b51b63f/frozenlist-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:924620eef691990dfb56dc4709f280f40baee568c794b5c1885800c3ecc69816", size = 151599 }, { url = "https://files.pythonhosted.org/packages/29/e2/ffbb1fae55a791fd6c2938dd9ea779509c977435ba3940b9f2e8dc9d5316/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9", size = 273249 },
{ url = "https://files.pythonhosted.org/packages/d2/fb/7421f3af6932d34a5856742324cda86a3434601eec5852cf62bfcea0c4a8/frozenlist-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae4dc05c465a08a866b7a1baf360747078b362e6a6dbeb0c57f234db0ef88ae0", size = 145468 }, { url = "https://files.pythonhosted.org/packages/2e/6e/008136a30798bb63618a114b9321b5971172a5abddff44a100c7edc5ad4f/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039", size = 271075 },
{ url = "https://files.pythonhosted.org/packages/d4/8a/5dc2e402311f67f6e8e76a01fd506d85ead034bf6e06c44c08e293deebcb/frozenlist-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bed331fe18f58d844d39ceb398b77d6ac0b010d571cba8267c2e7165806b00ce", size = 157687 }, { url = "https://files.pythonhosted.org/packages/ae/f0/4e71e54a026b06724cec9b6c54f0b13a4e9e298cc8db0f82ec70e151f5ce/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784", size = 285398 },
{ url = "https://files.pythonhosted.org/packages/bd/06/5184652df91c1948393bcb7978b7bdaca731b3201bbae2e8597136cdaba1/frozenlist-1.3.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:02c9ac843e3390826a265e331105efeab489ffaf4dd86384595ee8ce6d35ae7f", size = 155482 }, { url = "https://files.pythonhosted.org/packages/4d/36/70ec246851478b1c0b59f11ef8ade9c482ff447c1363c2bd5fad45098b12/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631", size = 294445 },
{ url = "https://files.pythonhosted.org/packages/2b/64/cc02fb54dd400fb33e5a4318debbcc38558f0fdbb97de77c0c51ee94122e/frozenlist-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9545a33965d0d377b0bc823dcabf26980e77f1b6a7caa368a365a9497fb09420", size = 152497 }, { url = "https://files.pythonhosted.org/packages/37/e0/47f87544055b3349b633a03c4d94b405956cf2437f4ab46d0928b74b7526/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f", size = 280569 },
{ url = "https://files.pythonhosted.org/packages/8d/0a/33cf0eef25ea53faf75e3f8992a9a9c25a00a7c02fcfb7221e1d6a40b771/frozenlist-1.3.3-cp310-cp310-win32.whl", hash = "sha256:d5cd3ab21acbdb414bb6c31958d7b06b85eeb40f66463c264a9b343a4e238642", size = 30595 }, { url = "https://files.pythonhosted.org/packages/f9/7c/490133c160fb6b84ed374c266f42800e33b50c3bbab1652764e6e1fc498a/frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8", size = 44721 },
{ url = "https://files.pythonhosted.org/packages/39/29/1b35650abaea3ad54a031757645e2f8a5d2b5971bf94b7cde4daebbdbb47/frozenlist-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:b756072364347cb6aa5b60f9bc18e94b2f79632de3b0190253ad770c5df17db1", size = 33309 }, { url = "https://files.pythonhosted.org/packages/b1/56/4e45136ffc6bdbfa68c29ca56ef53783ef4c2fd395f7cbf99a2624aa9aaa/frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f", size = 51329 },
{ url = "https://files.pythonhosted.org/packages/2d/39/82eb234c1a80c4d2d7b071173d7b01f79e93f285d072f4370b019849c9b4/frozenlist-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4395e2f8d83fbe0c627b2b696acce67868793d7d9750e90e39592b3626691b7", size = 60735 }, { url = "https://files.pythonhosted.org/packages/da/3b/915f0bca8a7ea04483622e84a9bd90033bab54bdf485479556c74fd5eaf5/frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953", size = 91538 },
{ url = "https://files.pythonhosted.org/packages/58/d2/2a991a3f49054f51e7cf30c4f5ce6f9fcd6df0fcf781db46d5af8d0c24ad/frozenlist-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14143ae966a6229350021384870458e4777d1eae4c28d1a7aa47f24d030e6678", size = 35840 }, { url = "https://files.pythonhosted.org/packages/c7/d1/a7c98aad7e44afe5306a2b068434a5830f1470675f0e715abb86eb15f15b/frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0", size = 52849 },
{ url = "https://files.pythonhosted.org/packages/09/cf/3a150d94c772a44cfc83fb1fcd5c59164047c00d20490ebcc33105bda39a/frozenlist-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d8860749e813a6f65bad8285a0520607c9500caa23fea6ee407e63debcdbef6", size = 34289 }, { url = "https://files.pythonhosted.org/packages/3a/c8/76f23bf9ab15d5f760eb48701909645f686f9c64fbb8982674c241fbef14/frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2", size = 50583 },
{ url = "https://files.pythonhosted.org/packages/01/a3/a3c18bfd7bd2a56831b985140f98eb6dda684a2d8b2a54b1077b45c7f9d9/frozenlist-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23d16d9f477bb55b6154654e0e74557040575d9d19fe78a161bd33d7d76808e8", size = 153264 }, { url = "https://files.pythonhosted.org/packages/1f/22/462a3dd093d11df623179d7754a3b3269de3b42de2808cddef50ee0f4f48/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f", size = 265636 },
{ url = "https://files.pythonhosted.org/packages/a9/3a/f5905a1a9eaff25745f3eeb25ecb6ba4d3be101ad6fa3e6d3d084f18dc2d/frozenlist-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb82dbba47a8318e75f679690190c10a5e1f447fbf9df41cbc4c3afd726d88cb", size = 159371 }, { url = "https://files.pythonhosted.org/packages/80/cf/e075e407fc2ae7328155a1cd7e22f932773c8073c1fc78016607d19cc3e5/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608", size = 270214 },
{ url = "https://files.pythonhosted.org/packages/fa/a1/d0822eb2f827f209c8fcf19ff1c9eb30ae08e25b710cf432b1013ea23429/frozenlist-1.3.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9309869032abb23d196cb4e4db574232abe8b8be1339026f489eeb34a4acfd91", size = 157191 }, { url = "https://files.pythonhosted.org/packages/a1/58/0642d061d5de779f39c50cbb00df49682832923f3d2ebfb0fedf02d05f7f/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b", size = 273905 },
{ url = "https://files.pythonhosted.org/packages/13/40/0d0ff24ac7289fc7af004df73e6a06e0e90fca88ca6e515bf61b06905df7/frozenlist-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a97b4fe50b5890d36300820abd305694cb865ddb7885049587a5678215782a6b", size = 145856 }, { url = "https://files.pythonhosted.org/packages/ab/66/3fe0f5f8f2add5b4ab7aa4e199f767fd3b55da26e3ca4ce2cc36698e50c4/frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840", size = 250542 },
{ url = "https://files.pythonhosted.org/packages/f1/bc/fbd3300dc8219a7de5d2b6b4e0fff4b884da66046c15bb223696c0c05aa0/frozenlist-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c188512b43542b1e91cadc3c6c915a82a5eb95929134faf7fd109f14f9892ce4", size = 154331 }, { url = "https://files.pythonhosted.org/packages/f6/b8/260791bde9198c87a465224e0e2bb62c4e716f5d198fc3a1dacc4895dbd1/frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439", size = 267026 },
{ url = "https://files.pythonhosted.org/packages/51/1b/1d6dc83f1b30e6bbbf062d5df60037b954c7cd9f3cdb21d1e603bfcca819/frozenlist-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:303e04d422e9b911a09ad499b0368dc551e8c3cd15293c99160c7f1f07b59a48", size = 154699 }, { url = "https://files.pythonhosted.org/packages/2e/a4/3d24f88c527f08f8d44ade24eaee83b2627793fa62fa07cbb7ff7a2f7d42/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de", size = 257690 },
{ url = "https://files.pythonhosted.org/packages/7f/0b/0309aaa07910bdde804decf6827883feadcec55146e3c0e708758c74b406/frozenlist-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0771aed7f596c7d73444c847a1c16288937ef988dc04fb9f7be4b2aa91db609d", size = 147699 }, { url = "https://files.pythonhosted.org/packages/de/9a/d311d660420b2beeff3459b6626f2ab4fb236d07afbdac034a4371fe696e/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641", size = 253893 },
{ url = "https://files.pythonhosted.org/packages/60/45/14e6898edb6872c64014b432cf2f5408ffd317e72ee2b29426303bbc66e2/frozenlist-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:66080ec69883597e4d026f2f71a231a1ee9887835902dbe6b6467d5a89216cf6", size = 160515 }, { url = "https://files.pythonhosted.org/packages/c6/23/e491aadc25b56eabd0f18c53bb19f3cdc6de30b2129ee0bc39cd387cd560/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e", size = 267006 },
{ url = "https://files.pythonhosted.org/packages/c9/cb/d62c14c4354fdd593182efe25af33af086a54126a518dba0f9496fdbed89/frozenlist-1.3.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:41fe21dc74ad3a779c3d73a2786bdf622ea81234bdd4faf90b8b03cad0c2c0b4", size = 158812 }, { url = "https://files.pythonhosted.org/packages/08/c4/ab918ce636a35fb974d13d666dcbe03969592aeca6c3ab3835acff01f79c/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9", size = 276157 },
{ url = "https://files.pythonhosted.org/packages/55/71/5fb91c250a1fa82a38f8b1ce2b3016f44b1c210c4d0c4b2e39c7e53e42b7/frozenlist-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f20380df709d91525e4bee04746ba612a4df0972c1b8f8e1e8af997e678c7b81", size = 155396 }, { url = "https://files.pythonhosted.org/packages/c0/29/3b7a0bbbbe5a34833ba26f686aabfe982924adbdcafdc294a7a129c31688/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03", size = 264642 },
{ url = "https://files.pythonhosted.org/packages/da/38/06f3d82def80a49390b148414f19c23ae9c2920033ac0bad8f7c5cab494a/frozenlist-1.3.3-cp311-cp311-win32.whl", hash = "sha256:f30f1928162e189091cf4d9da2eac617bfe78ef907a761614ff577ef4edfb3c8", size = 30359 }, { url = "https://files.pythonhosted.org/packages/ab/42/0595b3dbffc2e82d7fe658c12d5a5bafcd7516c6bf2d1d1feb5387caa9c1/frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c", size = 44914 },
{ url = "https://files.pythonhosted.org/packages/30/d5/6fdf60f2a3af80dd824357d70d06f13e8c1c756eec2778b66dca4e28a3da/frozenlist-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a6394d7dadd3cfe3f4b3b186e54d5d8504d44f2d58dcc89d693698e8b7132b32", size = 32639 }, { url = "https://files.pythonhosted.org/packages/17/c4/b7db1206a3fea44bf3b838ca61deb6f74424a8a5db1dd53ecb21da669be6/frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28", size = 51167 },
{ url = "https://files.pythonhosted.org/packages/c6/c8/a5be5b7550c10858fcf9b0ea054baccab474da77d37f1e828ce043a3a5d4/frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3", size = 11901 },
] ]
[[package]] [[package]]
@ -835,22 +785,6 @@ dependencies = [
] ]
sdist = { url = "https://files.pythonhosted.org/packages/ab/75/a53f1cb732420f5e5d79b2563fc3504d22115e7ecfe7966e5cf9b3582ae7/gevent-24.11.1.tar.gz", hash = "sha256:8bd1419114e9e4a3ed33a5bad766afff9a3cf765cb440a582a1b3a9bc80c1aca", size = 5976624 } sdist = { url = "https://files.pythonhosted.org/packages/ab/75/a53f1cb732420f5e5d79b2563fc3504d22115e7ecfe7966e5cf9b3582ae7/gevent-24.11.1.tar.gz", hash = "sha256:8bd1419114e9e4a3ed33a5bad766afff9a3cf765cb440a582a1b3a9bc80c1aca", size = 5976624 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/36/7d/27ed3603f4bf96b36fb2746e923e033bc600c6684de8fe164d64eb8c4dcc/gevent-24.11.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:92fe5dfee4e671c74ffaa431fd7ffd0ebb4b339363d24d0d944de532409b935e", size = 2998254 },
{ url = "https://files.pythonhosted.org/packages/a8/03/a8f6c70f50a644a79e75d9f15e6f1813115d34c3c55528e4669a9316534d/gevent-24.11.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7bfcfe08d038e1fa6de458891bca65c1ada6d145474274285822896a858c870", size = 4817711 },
{ url = "https://files.pythonhosted.org/packages/f0/05/4f9bc565520a18f107464d40ac15a91708431362c797e77fbb5e7ff26e64/gevent-24.11.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7398c629d43b1b6fd785db8ebd46c0a353880a6fab03d1cf9b6788e7240ee32e", size = 4934468 },
{ url = "https://files.pythonhosted.org/packages/4a/7d/f15561eeebecbebc0296dd7bebea10ac4af0065d98249e3d8c4998e68edd/gevent-24.11.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d7886b63ebfb865178ab28784accd32f287d5349b3ed71094c86e4d3ca738af5", size = 5014067 },
{ url = "https://files.pythonhosted.org/packages/67/c1/07eff117a600fc3c9bd4e3a1ff3b726f146ee23ce55981156547ccae0c85/gevent-24.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9ca80711e6553880974898d99357fb649e062f9058418a92120ca06c18c3c59", size = 6625531 },
{ url = "https://files.pythonhosted.org/packages/4b/72/43f76ab6b18e5e56b1003c844829971f3044af08b39b3c9040559be00a2b/gevent-24.11.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e24181d172f50097ac8fc272c8c5b030149b630df02d1c639ee9f878a470ba2b", size = 5249671 },
{ url = "https://files.pythonhosted.org/packages/6b/fc/1a847ada0757cc7690f83959227514b1a52ff6de504619501c81805fa1da/gevent-24.11.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1d4fadc319b13ef0a3c44d2792f7918cf1bca27cacd4d41431c22e6b46668026", size = 6773903 },
{ url = "https://files.pythonhosted.org/packages/3b/9d/254dcf455f6659ab7e36bec0bc11f51b18ea25eac2de69185e858ccf3c30/gevent-24.11.1-cp310-cp310-win_amd64.whl", hash = "sha256:3d882faa24f347f761f934786dde6c73aa6c9187ee710189f12dcc3a63ed4a50", size = 1560443 },
{ url = "https://files.pythonhosted.org/packages/ea/fd/86a170f77ef51a15297573c50dbec4cc67ddc98b677cc2d03cc7f2927f4c/gevent-24.11.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:351d1c0e4ef2b618ace74c91b9b28b3eaa0dd45141878a964e03c7873af09f62", size = 2951424 },
{ url = "https://files.pythonhosted.org/packages/7f/0a/987268c9d446f61883bc627c77c5ed4a97869c0f541f76661a62b2c411f6/gevent-24.11.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5efe72e99b7243e222ba0c2c2ce9618d7d36644c166d63373af239da1036bab", size = 4878504 },
{ url = "https://files.pythonhosted.org/packages/dc/d4/2f77ddd837c0e21b4a4460bcb79318b6754d95ef138b7a29f3221c7e9993/gevent-24.11.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d3b249e4e1f40c598ab8393fc01ae6a3b4d51fc1adae56d9ba5b315f6b2d758", size = 5007668 },
{ url = "https://files.pythonhosted.org/packages/80/a0/829e0399a1f9b84c344b72d2be9aa60fe2a64e993cac221edcc14f069679/gevent-24.11.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81d918e952954675f93fb39001da02113ec4d5f4921bf5a0cc29719af6824e5d", size = 5067055 },
{ url = "https://files.pythonhosted.org/packages/1e/67/0e693f9ddb7909c2414f8fcfc2409aa4157884c147bc83dab979e9cf717c/gevent-24.11.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9c935b83d40c748b6421625465b7308d87c7b3717275acd587eef2bd1c39546", size = 6761883 },
{ url = "https://files.pythonhosted.org/packages/fa/b6/b69883fc069d7148dd23c5dda20826044e54e7197f3c8e72b8cc2cd4035a/gevent-24.11.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff96c5739834c9a594db0e12bf59cb3fa0e5102fc7b893972118a3166733d61c", size = 5440802 },
{ url = "https://files.pythonhosted.org/packages/32/4e/b00094d995ff01fd88b3cf6b9d1d794f935c31c645c431e65cd82d808c9c/gevent-24.11.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d6c0a065e31ef04658f799215dddae8752d636de2bed61365c358f9c91e7af61", size = 6866992 },
{ url = "https://files.pythonhosted.org/packages/37/ed/58dbe9fb09d36f6477ff8db0459ebd3be9a77dc05ae5d96dc91ad657610d/gevent-24.11.1-cp311-cp311-win_amd64.whl", hash = "sha256:97e2f3999a5c0656f42065d02939d64fffaf55861f7d62b0107a08f52c984897", size = 1543736 },
{ url = "https://files.pythonhosted.org/packages/dd/32/301676f67ffa996ff1c4175092fb0c48c83271cc95e5c67650b87156b6cf/gevent-24.11.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:a3d75fa387b69c751a3d7c5c3ce7092a171555126e136c1d21ecd8b50c7a6e46", size = 2956467 }, { url = "https://files.pythonhosted.org/packages/dd/32/301676f67ffa996ff1c4175092fb0c48c83271cc95e5c67650b87156b6cf/gevent-24.11.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:a3d75fa387b69c751a3d7c5c3ce7092a171555126e136c1d21ecd8b50c7a6e46", size = 2956467 },
{ url = "https://files.pythonhosted.org/packages/6b/84/aef1a598123cef2375b6e2bf9d17606b961040f8a10e3dcc3c3dd2a99f05/gevent-24.11.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:beede1d1cff0c6fafae3ab58a0c470d7526196ef4cd6cc18e7769f207f2ea4eb", size = 5136486 }, { url = "https://files.pythonhosted.org/packages/6b/84/aef1a598123cef2375b6e2bf9d17606b961040f8a10e3dcc3c3dd2a99f05/gevent-24.11.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:beede1d1cff0c6fafae3ab58a0c470d7526196ef4cd6cc18e7769f207f2ea4eb", size = 5136486 },
{ url = "https://files.pythonhosted.org/packages/92/7b/04f61187ee1df7a913b3fca63b0a1206c29141ab4d2a57e7645237b6feb5/gevent-24.11.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:85329d556aaedced90a993226d7d1186a539c843100d393f2349b28c55131c85", size = 5299718 }, { url = "https://files.pythonhosted.org/packages/92/7b/04f61187ee1df7a913b3fca63b0a1206c29141ab4d2a57e7645237b6feb5/gevent-24.11.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:85329d556aaedced90a993226d7d1186a539c843100d393f2349b28c55131c85", size = 5299718 },
@ -867,7 +801,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/ed/6e/b2eed8dec617264f0046d50a13a42d3f0a06c50071b9fc1eae00285a03f1/gevent-24.11.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:58851f23c4bdb70390f10fc020c973ffcf409eb1664086792c8b1e20f25eef43", size = 5449436 }, { url = "https://files.pythonhosted.org/packages/ed/6e/b2eed8dec617264f0046d50a13a42d3f0a06c50071b9fc1eae00285a03f1/gevent-24.11.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:58851f23c4bdb70390f10fc020c973ffcf409eb1664086792c8b1e20f25eef43", size = 5449436 },
{ url = "https://files.pythonhosted.org/packages/63/c2/eca6b95fbf9af287fa91c327494e4b74a8d5bfa0156cd87b233f63f118dc/gevent-24.11.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:1ea50009ecb7f1327347c37e9eb6561bdbc7de290769ee1404107b9a9cba7cf1", size = 6866470 }, { url = "https://files.pythonhosted.org/packages/63/c2/eca6b95fbf9af287fa91c327494e4b74a8d5bfa0156cd87b233f63f118dc/gevent-24.11.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:1ea50009ecb7f1327347c37e9eb6561bdbc7de290769ee1404107b9a9cba7cf1", size = 6866470 },
{ url = "https://files.pythonhosted.org/packages/b7/e6/51824bd1f2c1ce70aa01495aa6ffe04ab789fa819fa7e6f0ad2388fb03c6/gevent-24.11.1-cp313-cp313-win_amd64.whl", hash = "sha256:ec68e270543ecd532c4c1d70fca020f90aa5486ad49c4f3b8b2e64a66f5c9274", size = 1540088 }, { url = "https://files.pythonhosted.org/packages/b7/e6/51824bd1f2c1ce70aa01495aa6ffe04ab789fa819fa7e6f0ad2388fb03c6/gevent-24.11.1-cp313-cp313-win_amd64.whl", hash = "sha256:ec68e270543ecd532c4c1d70fca020f90aa5486ad49c4f3b8b2e64a66f5c9274", size = 1540088 },
{ url = "https://files.pythonhosted.org/packages/86/63/197aa67250943b508b34995c2aa6b46402e7e6f11785487740c2057bfb20/gevent-24.11.1-pp310-pypy310_pp73-macosx_11_0_universal2.whl", hash = "sha256:f43f47e702d0c8e1b8b997c00f1601486f9f976f84ab704f8f11536e3fa144c9", size = 1271676 },
] ]
[[package]] [[package]]
@ -954,24 +887,6 @@ version = "3.1.1"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/2f/ff/df5fede753cc10f6a5be0931204ea30c35fa2f2ea7a35b25bdaf4fe40e46/greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467", size = 186022 } sdist = { url = "https://files.pythonhosted.org/packages/2f/ff/df5fede753cc10f6a5be0931204ea30c35fa2f2ea7a35b25bdaf4fe40e46/greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467", size = 186022 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/25/90/5234a78dc0ef6496a6eb97b67a42a8e96742a56f7dc808cb954a85390448/greenlet-3.1.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563", size = 271235 },
{ url = "https://files.pythonhosted.org/packages/7c/16/cd631fa0ab7d06ef06387135b7549fdcc77d8d859ed770a0d28e47b20972/greenlet-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83", size = 637168 },
{ url = "https://files.pythonhosted.org/packages/2f/b1/aed39043a6fec33c284a2c9abd63ce191f4f1a07319340ffc04d2ed3256f/greenlet-3.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0", size = 648826 },
{ url = "https://files.pythonhosted.org/packages/76/25/40e0112f7f3ebe54e8e8ed91b2b9f970805143efef16d043dfc15e70f44b/greenlet-3.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120", size = 644443 },
{ url = "https://files.pythonhosted.org/packages/fb/2f/3850b867a9af519794784a7eeed1dd5bc68ffbcc5b28cef703711025fd0a/greenlet-3.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc", size = 643295 },
{ url = "https://files.pythonhosted.org/packages/cf/69/79e4d63b9387b48939096e25115b8af7cd8a90397a304f92436bcb21f5b2/greenlet-3.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617", size = 599544 },
{ url = "https://files.pythonhosted.org/packages/46/1d/44dbcb0e6c323bd6f71b8c2f4233766a5faf4b8948873225d34a0b7efa71/greenlet-3.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7", size = 1125456 },
{ url = "https://files.pythonhosted.org/packages/e0/1d/a305dce121838d0278cee39d5bb268c657f10a5363ae4b726848f833f1bb/greenlet-3.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6", size = 1149111 },
{ url = "https://files.pythonhosted.org/packages/96/28/d62835fb33fb5652f2e98d34c44ad1a0feacc8b1d3f1aecab035f51f267d/greenlet-3.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80", size = 298392 },
{ url = "https://files.pythonhosted.org/packages/28/62/1c2665558618553c42922ed47a4e6d6527e2fa3516a8256c2f431c5d0441/greenlet-3.1.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70", size = 272479 },
{ url = "https://files.pythonhosted.org/packages/76/9d/421e2d5f07285b6e4e3a676b016ca781f63cfe4a0cd8eaecf3fd6f7a71ae/greenlet-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159", size = 640404 },
{ url = "https://files.pythonhosted.org/packages/e5/de/6e05f5c59262a584e502dd3d261bbdd2c97ab5416cc9c0b91ea38932a901/greenlet-3.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e", size = 652813 },
{ url = "https://files.pythonhosted.org/packages/49/93/d5f93c84241acdea15a8fd329362c2c71c79e1a507c3f142a5d67ea435ae/greenlet-3.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1", size = 648517 },
{ url = "https://files.pythonhosted.org/packages/15/85/72f77fc02d00470c86a5c982b8daafdf65d38aefbbe441cebff3bf7037fc/greenlet-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383", size = 647831 },
{ url = "https://files.pythonhosted.org/packages/f7/4b/1c9695aa24f808e156c8f4813f685d975ca73c000c2a5056c514c64980f6/greenlet-3.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a", size = 602413 },
{ url = "https://files.pythonhosted.org/packages/76/70/ad6e5b31ef330f03b12559d19fda2606a522d3849cde46b24f223d6d1619/greenlet-3.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511", size = 1129619 },
{ url = "https://files.pythonhosted.org/packages/f4/fb/201e1b932e584066e0f0658b538e73c459b34d44b4bd4034f682423bc801/greenlet-3.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395", size = 1155198 },
{ url = "https://files.pythonhosted.org/packages/12/da/b9ed5e310bb8b89661b80cbcd4db5a067903bbcd7fc854923f5ebb4144f0/greenlet-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39", size = 298930 },
{ url = "https://files.pythonhosted.org/packages/7d/ec/bad1ac26764d26aa1353216fcbfa4670050f66d445448aafa227f8b16e80/greenlet-3.1.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d", size = 274260 }, { url = "https://files.pythonhosted.org/packages/7d/ec/bad1ac26764d26aa1353216fcbfa4670050f66d445448aafa227f8b16e80/greenlet-3.1.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d", size = 274260 },
{ url = "https://files.pythonhosted.org/packages/66/d4/c8c04958870f482459ab5956c2942c4ec35cac7fe245527f1039837c17a9/greenlet-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79", size = 649064 }, { url = "https://files.pythonhosted.org/packages/66/d4/c8c04958870f482459ab5956c2942c4ec35cac7fe245527f1039837c17a9/greenlet-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79", size = 649064 },
{ url = "https://files.pythonhosted.org/packages/51/41/467b12a8c7c1303d20abcca145db2be4e6cd50a951fa30af48b6ec607581/greenlet-3.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa", size = 663420 }, { url = "https://files.pythonhosted.org/packages/51/41/467b12a8c7c1303d20abcca145db2be4e6cd50a951fa30af48b6ec607581/greenlet-3.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa", size = 663420 },
@ -1199,24 +1114,20 @@ name = "lazy-object-proxy"
version = "1.7.1" version = "1.7.1"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/75/93/3fc1cc28f71dd10b87a53b9d809602d7730e84cc4705a062def286232a9c/lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4", size = 41995 } sdist = { url = "https://files.pythonhosted.org/packages/75/93/3fc1cc28f71dd10b87a53b9d809602d7730e84cc4705a062def286232a9c/lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4", size = 41995 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/97/0d/c722b060a46b9b87701896759fa0ccc4a8c19f13b4a6ed4df7f4b2fdfbec/lazy_object_proxy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b", size = 22251 },
{ url = "https://files.pythonhosted.org/packages/3c/bb/ecf283b044c6ac5d6a7182792861b2e12f1bc905b8ae2d1d52f403f3e1dc/lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36", size = 62985 },
{ url = "https://files.pythonhosted.org/packages/fd/80/60d6ef4fd8736e743a2b91b84de0e16448dbc6ba08fa2ee071830bc36bb1/lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb", size = 62296 },
{ url = "https://files.pythonhosted.org/packages/54/da/022607b44f7476f0f387041b7c26329b5219b13d6c23e8d4405df217e18e/lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443", size = 65057 },
{ url = "https://files.pythonhosted.org/packages/0d/0c/4a96799cec6daae24c991ee62b57ee7935273cfbdafb92cf68ba304be79a/lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b", size = 64620 },
{ url = "https://files.pythonhosted.org/packages/92/b9/c6cf39ca616369cc1e83a93411f035cfa305651118e0e41bbeebd8d275a5/lazy_object_proxy-1.7.1-cp310-cp310-win32.whl", hash = "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9", size = 21042 },
{ url = "https://files.pythonhosted.org/packages/12/c1/90d8fad7008684eb101788b85f86d46146500108bc34c1e9ff14c1265acb/lazy_object_proxy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd", size = 23008 },
]
[[package]] [[package]]
name = "limits" name = "limits"
version = "1.5.1" version = "4.0.1"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "six" }, { name = "deprecated" },
{ name = "packaging" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/bc/03/91618859fc967fd727a3ecce5f7d9b0322152fa81c4a1bdd1f8afcfc5185/limits-4.0.1.tar.gz", hash = "sha256:a54f5c058dfc965319ae3ee78faf222294659e371b46d22cd7456761f7e46d5a", size = 70787 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8e/7a/6d84edd5a6bf666cdb14f8aaa3363c341271e0fa19e645e575ac0afd26d1/limits-4.0.1-py3-none-any.whl", hash = "sha256:67667e669f570cf7be4e2c2bc52f763b3f93bdf66ea945584360bc1a3f251901", size = 45753 },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/3f/a5/05c7c11f7c9f02d8f58959c036ea02da1f62ac9da686a25232c2d1dd79ed/limits-1.5.1.tar.gz", hash = "sha256:f0c3319f032c4bfad68438ed1325c0fac86dac64582c7c25cddc87a0b658fa20", size = 37893 }
[[package]] [[package]]
name = "loguru" name = "loguru"
@ -1299,12 +1210,6 @@ name = "newrelic"
version = "8.8.0" version = "8.8.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/0b/73/9c78820ecf2da85b30beca9f926a29cfd05c6cac7df2d9e05991b9c85734/newrelic-8.8.0.tar.gz", hash = "sha256:84d1f71284efa5f1cae696161e0c3cb65eaa2f53116fe5e7c5a62be7d15d9536", size = 919778 } sdist = { url = "https://files.pythonhosted.org/packages/0b/73/9c78820ecf2da85b30beca9f926a29cfd05c6cac7df2d9e05991b9c85734/newrelic-8.8.0.tar.gz", hash = "sha256:84d1f71284efa5f1cae696161e0c3cb65eaa2f53116fe5e7c5a62be7d15d9536", size = 919778 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ee/aa/208f4eedd3d5e750bbbd1a6e50848104be440db6d115f8a9d883c117aca1/newrelic-8.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b4db0e7544232d4e6e835a02ee28637970576f8dce82ffcaa3d675246e822d5", size = 752214 },
{ url = "https://files.pythonhosted.org/packages/44/3f/8a5cd001ab5a2dc0f6416afbdeabfb988912f2c345661ec737be256b757b/newrelic-8.8.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9355f209ba8d82fd0f9d78d7cc1d9bef0ae4677b3cfed7b7aaec521adbe87559", size = 750707 },
{ url = "https://files.pythonhosted.org/packages/7e/47/515de1ee4f706188b7ee376bdeac96d4358bff976b97842d98ffe80f2ff4/newrelic-8.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4a0556c6ece49132ab1c32bfe398047a8311f9a8b6862b482495d132fcb0ad4", size = 752756 },
{ url = "https://files.pythonhosted.org/packages/06/eb/9226b7d12a768ba6e8f2372733c66b4146b3bcfa30f2a75a699b9997934e/newrelic-8.8.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caccdf201735df80b470ddf772f60a154f2c07c0c1b2b3f6e999d55e79ce601e", size = 751279 },
]
[[package]] [[package]]
name = "newrelic-telemetry-sdk" name = "newrelic-telemetry-sdk"
@ -1338,15 +1243,11 @@ wheels = [
[[package]] [[package]]
name = "packaging" name = "packaging"
version = "20.4" version = "24.2"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 }
{ name = "pyparsing" },
{ name = "six" },
]
sdist = { url = "https://files.pythonhosted.org/packages/55/fd/fc1aca9cf51ed2f2c11748fa797370027babd82f87829c7a8e6dbe720145/packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", size = 74402 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/46/19/c5ab91b1b05cfe63cccd5cfc971db9214c6dd6ced54e33c30d5af1d2bc43/packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181", size = 37620 }, { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 },
] ]
[[package]] [[package]]
@ -1437,19 +1338,18 @@ wheels = [
[[package]] [[package]]
name = "pre-commit" name = "pre-commit"
version = "2.17.0" version = "4.1.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "cfgv" }, { name = "cfgv" },
{ name = "identify" }, { name = "identify" },
{ name = "nodeenv" }, { name = "nodeenv" },
{ name = "pyyaml" }, { name = "pyyaml" },
{ name = "toml" },
{ name = "virtualenv" }, { name = "virtualenv" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/32/ea/13bb25c70e6d04b5788c42e0d3fcc82b06bc89f5d44c3c5606ef1af5a7cc/pre_commit-2.17.0.tar.gz", hash = "sha256:c1a8040ff15ad3d648c70cc3e55b93e4d2d5b687320955505587fd79bbaed06a", size = 170517 } sdist = { url = "https://files.pythonhosted.org/packages/2a/13/b62d075317d8686071eb843f0bb1f195eb332f48869d3c31a4c6f1e063ac/pre_commit-4.1.0.tar.gz", hash = "sha256:ae3f018575a588e30dfddfab9a05448bfbd6b73d78709617b5a2b853549716d4", size = 193330 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/d6/a0/9c06353771c8dae6db437dd513a885eccdb1566cb332569130484eddf4e7/pre_commit-2.17.0-py2.py3-none-any.whl", hash = "sha256:725fa7459782d7bec5ead072810e47351de01709be838c2ce1726b9591dad616", size = 195663 }, { url = "https://files.pythonhosted.org/packages/43/b3/df14c580d82b9627d173ceea305ba898dca135feb360b6d84019d0803d3b/pre_commit-4.1.0-py2.py3-none-any.whl", hash = "sha256:d29e7cb346295bcc1cc75fc3e92e343495e3ea0196c9ec6ba53f49f10ab6ae7b", size = 220560 },
] ]
[[package]] [[package]]
@ -1464,6 +1364,63 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/2b/c1/53ac685833200eb77ef485c2220dac5bfc255418e660790a9eb5cf3abf25/prompt_toolkit-3.0.7-py3-none-any.whl", hash = "sha256:83074ee28ad4ba6af190593d4d4c607ff525272a504eb159199b6dd9f950c950", size = 355098 }, { url = "https://files.pythonhosted.org/packages/2b/c1/53ac685833200eb77ef485c2220dac5bfc255418e660790a9eb5cf3abf25/prompt_toolkit-3.0.7-py3-none-any.whl", hash = "sha256:83074ee28ad4ba6af190593d4d4c607ff525272a504eb159199b6dd9f950c950", size = 355098 },
] ]
[[package]]
name = "propcache"
version = "0.3.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/92/76/f941e63d55c0293ff7829dd21e7cf1147e90a526756869a9070f287a68c9/propcache-0.3.0.tar.gz", hash = "sha256:a8fd93de4e1d278046345f49e2238cdb298589325849b2645d4a94c53faeffc5", size = 42722 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8d/2c/921f15dc365796ec23975b322b0078eae72995c7b4d49eba554c6a308d70/propcache-0.3.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e53d19c2bf7d0d1e6998a7e693c7e87300dd971808e6618964621ccd0e01fe4e", size = 79867 },
{ url = "https://files.pythonhosted.org/packages/11/a5/4a6cc1a559d1f2fb57ea22edc4245158cdffae92f7f92afcee2913f84417/propcache-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a61a68d630e812b67b5bf097ab84e2cd79b48c792857dc10ba8a223f5b06a2af", size = 46109 },
{ url = "https://files.pythonhosted.org/packages/e1/6d/28bfd3af3a567ad7d667348e7f46a520bda958229c4d545ba138a044232f/propcache-0.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fb91d20fa2d3b13deea98a690534697742029f4fb83673a3501ae6e3746508b5", size = 45635 },
{ url = "https://files.pythonhosted.org/packages/73/20/d75b42eaffe5075eac2f4e168f6393d21c664c91225288811d85451b2578/propcache-0.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67054e47c01b7b349b94ed0840ccae075449503cf1fdd0a1fdd98ab5ddc2667b", size = 242159 },
{ url = "https://files.pythonhosted.org/packages/a5/fb/4b537dd92f9fd4be68042ec51c9d23885ca5fafe51ec24c58d9401034e5f/propcache-0.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:997e7b8f173a391987df40f3b52c423e5850be6f6df0dcfb5376365440b56667", size = 248163 },
{ url = "https://files.pythonhosted.org/packages/e7/af/8a9db04ac596d531ca0ef7dde518feaadfcdabef7b17d6a5ec59ee3effc2/propcache-0.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d663fd71491dde7dfdfc899d13a067a94198e90695b4321084c6e450743b8c7", size = 248794 },
{ url = "https://files.pythonhosted.org/packages/9d/c4/ecfc988879c0fd9db03228725b662d76cf484b6b46f7e92fee94e4b52490/propcache-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8884ba1a0fe7210b775106b25850f5e5a9dc3c840d1ae9924ee6ea2eb3acbfe7", size = 243912 },
{ url = "https://files.pythonhosted.org/packages/04/a2/298dd27184faa8b7d91cc43488b578db218b3cc85b54d912ed27b8c5597a/propcache-0.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa806bbc13eac1ab6291ed21ecd2dd426063ca5417dd507e6be58de20e58dfcf", size = 229402 },
{ url = "https://files.pythonhosted.org/packages/be/0d/efe7fec316ca92dbf4bc4a9ba49ca889c43ca6d48ab1d6fa99fc94e5bb98/propcache-0.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6f4d7a7c0aff92e8354cceca6fe223973ddf08401047920df0fcb24be2bd5138", size = 226896 },
{ url = "https://files.pythonhosted.org/packages/60/63/72404380ae1d9c96d96e165aa02c66c2aae6072d067fc4713da5cde96762/propcache-0.3.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9be90eebc9842a93ef8335291f57b3b7488ac24f70df96a6034a13cb58e6ff86", size = 221447 },
{ url = "https://files.pythonhosted.org/packages/9d/18/b8392cab6e0964b67a30a8f4dadeaff64dc7022b5a34bb1d004ea99646f4/propcache-0.3.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bf15fc0b45914d9d1b706f7c9c4f66f2b7b053e9517e40123e137e8ca8958b3d", size = 222440 },
{ url = "https://files.pythonhosted.org/packages/6f/be/105d9ceda0f97eff8c06bac1673448b2db2a497444de3646464d3f5dc881/propcache-0.3.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5a16167118677d94bb48bfcd91e420088854eb0737b76ec374b91498fb77a70e", size = 234104 },
{ url = "https://files.pythonhosted.org/packages/cb/c9/f09a4ec394cfcce4053d8b2a04d622b5f22d21ba9bb70edd0cad061fa77b/propcache-0.3.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:41de3da5458edd5678b0f6ff66691507f9885f5fe6a0fb99a5d10d10c0fd2d64", size = 239086 },
{ url = "https://files.pythonhosted.org/packages/ea/aa/96f7f9ed6def82db67c972bdb7bd9f28b95d7d98f7e2abaf144c284bf609/propcache-0.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:728af36011bb5d344c4fe4af79cfe186729efb649d2f8b395d1572fb088a996c", size = 230991 },
{ url = "https://files.pythonhosted.org/packages/5a/11/bee5439de1307d06fad176f7143fec906e499c33d7aff863ea8428b8e98b/propcache-0.3.0-cp312-cp312-win32.whl", hash = "sha256:6b5b7fd6ee7b54e01759f2044f936dcf7dea6e7585f35490f7ca0420fe723c0d", size = 40337 },
{ url = "https://files.pythonhosted.org/packages/e4/17/e5789a54a0455a61cb9efc4ca6071829d992220c2998a27c59aeba749f6f/propcache-0.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:2d15bc27163cd4df433e75f546b9ac31c1ba7b0b128bfb1b90df19082466ff57", size = 44404 },
{ url = "https://files.pythonhosted.org/packages/3a/0f/a79dd23a0efd6ee01ab0dc9750d8479b343bfd0c73560d59d271eb6a99d4/propcache-0.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a2b9bf8c79b660d0ca1ad95e587818c30ccdb11f787657458d6f26a1ea18c568", size = 77287 },
{ url = "https://files.pythonhosted.org/packages/b8/51/76675703c90de38ac75adb8deceb3f3ad99b67ff02a0fa5d067757971ab8/propcache-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b0c1a133d42c6fc1f5fbcf5c91331657a1ff822e87989bf4a6e2e39b818d0ee9", size = 44923 },
{ url = "https://files.pythonhosted.org/packages/01/9b/fd5ddbee66cf7686e73c516227c2fd9bf471dbfed0f48329d095ea1228d3/propcache-0.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bb2f144c6d98bb5cbc94adeb0447cfd4c0f991341baa68eee3f3b0c9c0e83767", size = 44325 },
{ url = "https://files.pythonhosted.org/packages/13/1c/6961f11eb215a683b34b903b82bde486c606516c1466bf1fa67f26906d51/propcache-0.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1323cd04d6e92150bcc79d0174ce347ed4b349d748b9358fd2e497b121e03c8", size = 225116 },
{ url = "https://files.pythonhosted.org/packages/ef/ea/f8410c40abcb2e40dffe9adeed017898c930974650a63e5c79b886aa9f73/propcache-0.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b812b3cb6caacd072276ac0492d249f210006c57726b6484a1e1805b3cfeea0", size = 229905 },
{ url = "https://files.pythonhosted.org/packages/ef/5a/a9bf90894001468bf8e6ea293bb00626cc9ef10f8eb7996e9ec29345c7ed/propcache-0.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:742840d1d0438eb7ea4280f3347598f507a199a35a08294afdcc560c3739989d", size = 233221 },
{ url = "https://files.pythonhosted.org/packages/dd/ce/fffdddd9725b690b01d345c1156b4c2cc6dca09ab5c23a6d07b8f37d6e2f/propcache-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c6e7e4f9167fddc438cd653d826f2222222564daed4116a02a184b464d3ef05", size = 227627 },
{ url = "https://files.pythonhosted.org/packages/58/ae/45c89a5994a334735a3032b48e8e4a98c05d9536ddee0719913dc27da548/propcache-0.3.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a94ffc66738da99232ddffcf7910e0f69e2bbe3a0802e54426dbf0714e1c2ffe", size = 214217 },
{ url = "https://files.pythonhosted.org/packages/01/84/bc60188c3290ff8f5f4a92b9ca2d93a62e449c8daf6fd11ad517ad136926/propcache-0.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3c6ec957025bf32b15cbc6b67afe233c65b30005e4c55fe5768e4bb518d712f1", size = 212921 },
{ url = "https://files.pythonhosted.org/packages/14/b3/39d60224048feef7a96edabb8217dc3f75415457e5ebbef6814f8b2a27b5/propcache-0.3.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:549722908de62aa0b47a78b90531c022fa6e139f9166be634f667ff45632cc92", size = 208200 },
{ url = "https://files.pythonhosted.org/packages/9d/b3/0a6720b86791251273fff8a01bc8e628bc70903513bd456f86cde1e1ef84/propcache-0.3.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5d62c4f6706bff5d8a52fd51fec6069bef69e7202ed481486c0bc3874912c787", size = 208400 },
{ url = "https://files.pythonhosted.org/packages/e9/4f/bb470f3e687790547e2e78105fb411f54e0cdde0d74106ccadd2521c6572/propcache-0.3.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:24c04f8fbf60094c531667b8207acbae54146661657a1b1be6d3ca7773b7a545", size = 218116 },
{ url = "https://files.pythonhosted.org/packages/34/71/277f7f9add469698ac9724c199bfe06f85b199542121a71f65a80423d62a/propcache-0.3.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7c5f5290799a3f6539cc5e6f474c3e5c5fbeba74a5e1e5be75587746a940d51e", size = 222911 },
{ url = "https://files.pythonhosted.org/packages/92/e3/a7b9782aef5a2fc765b1d97da9ec7aed2f25a4e985703608e73232205e3f/propcache-0.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4fa0e7c9c3cf7c276d4f6ab9af8adddc127d04e0fcabede315904d2ff76db626", size = 216563 },
{ url = "https://files.pythonhosted.org/packages/ab/76/0583ca2c551aa08ffcff87b2c6849c8f01c1f6fb815a5226f0c5c202173e/propcache-0.3.0-cp313-cp313-win32.whl", hash = "sha256:ee0bd3a7b2e184e88d25c9baa6a9dc609ba25b76daae942edfb14499ac7ec374", size = 39763 },
{ url = "https://files.pythonhosted.org/packages/80/ec/c6a84f9a36f608379b95f0e786c111d5465926f8c62f12be8cdadb02b15c/propcache-0.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c8f7d896a16da9455f882870a507567d4f58c53504dc2d4b1e1d386dfe4588a", size = 43650 },
{ url = "https://files.pythonhosted.org/packages/ee/95/7d32e3560f5bf83fc2f2a4c1b0c181d327d53d5f85ebd045ab89d4d97763/propcache-0.3.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e560fd75aaf3e5693b91bcaddd8b314f4d57e99aef8a6c6dc692f935cc1e6bbf", size = 82140 },
{ url = "https://files.pythonhosted.org/packages/86/89/752388f12e6027a5e63f5d075f15291ded48e2d8311314fff039da5a9b11/propcache-0.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:65a37714b8ad9aba5780325228598a5b16c47ba0f8aeb3dc0514701e4413d7c0", size = 47296 },
{ url = "https://files.pythonhosted.org/packages/1b/4c/b55c98d586c69180d3048984a57a5ea238bdeeccf82dbfcd598e935e10bb/propcache-0.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:07700939b2cbd67bfb3b76a12e1412405d71019df00ca5697ce75e5ef789d829", size = 46724 },
{ url = "https://files.pythonhosted.org/packages/0f/b6/67451a437aed90c4e951e320b5b3d7eb584ade1d5592f6e5e8f678030989/propcache-0.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c0fdbdf6983526e269e5a8d53b7ae3622dd6998468821d660d0daf72779aefa", size = 291499 },
{ url = "https://files.pythonhosted.org/packages/ee/ff/e4179facd21515b24737e1e26e02615dfb5ed29416eed4cf5bc6ac5ce5fb/propcache-0.3.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:794c3dd744fad478b6232289c866c25406ecdfc47e294618bdf1697e69bd64a6", size = 293911 },
{ url = "https://files.pythonhosted.org/packages/76/8d/94a8585992a064a23bd54f56c5e58c3b8bf0c0a06ae10e56f2353ae16c3d/propcache-0.3.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4544699674faf66fb6b4473a1518ae4999c1b614f0b8297b1cef96bac25381db", size = 293301 },
{ url = "https://files.pythonhosted.org/packages/b0/b8/2c860c92b4134f68c7716c6f30a0d723973f881c32a6d7a24c4ddca05fdf/propcache-0.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fddb8870bdb83456a489ab67c6b3040a8d5a55069aa6f72f9d872235fbc52f54", size = 281947 },
{ url = "https://files.pythonhosted.org/packages/cd/72/b564be7411b525d11757b713c757c21cd4dc13b6569c3b2b8f6d3c96fd5e/propcache-0.3.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f857034dc68d5ceb30fb60afb6ff2103087aea10a01b613985610e007053a121", size = 268072 },
{ url = "https://files.pythonhosted.org/packages/37/68/d94649e399e8d7fc051e5a4f2334efc567993525af083db145a70690a121/propcache-0.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:02df07041e0820cacc8f739510078f2aadcfd3fc57eaeeb16d5ded85c872c89e", size = 275190 },
{ url = "https://files.pythonhosted.org/packages/d8/3c/446e125f5bbbc1922964dd67cb541c01cdb678d811297b79a4ff6accc843/propcache-0.3.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f47d52fd9b2ac418c4890aad2f6d21a6b96183c98021f0a48497a904199f006e", size = 254145 },
{ url = "https://files.pythonhosted.org/packages/f4/80/fd3f741483dc8e59f7ba7e05eaa0f4e11677d7db2077522b92ff80117a2a/propcache-0.3.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9ff4e9ecb6e4b363430edf2c6e50173a63e0820e549918adef70515f87ced19a", size = 257163 },
{ url = "https://files.pythonhosted.org/packages/dc/cf/6292b5ce6ed0017e6a89024a827292122cc41b6259b30ada0c6732288513/propcache-0.3.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ecc2920630283e0783c22e2ac94427f8cca29a04cfdf331467d4f661f4072dac", size = 280249 },
{ url = "https://files.pythonhosted.org/packages/e8/f0/fd9b8247b449fe02a4f96538b979997e229af516d7462b006392badc59a1/propcache-0.3.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:c441c841e82c5ba7a85ad25986014be8d7849c3cfbdb6004541873505929a74e", size = 288741 },
{ url = "https://files.pythonhosted.org/packages/64/71/cf831fdc2617f86cfd7f414cfc487d018e722dac8acc098366ce9bba0941/propcache-0.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c929916cbdb540d3407c66f19f73387f43e7c12fa318a66f64ac99da601bcdf", size = 277061 },
{ url = "https://files.pythonhosted.org/packages/42/78/9432542a35d944abeca9e02927a0de38cd7a298466d8ffa171536e2381c3/propcache-0.3.0-cp313-cp313t-win32.whl", hash = "sha256:0c3e893c4464ebd751b44ae76c12c5f5c1e4f6cbd6fbf67e3783cd93ad221863", size = 42252 },
{ url = "https://files.pythonhosted.org/packages/6f/45/960365f4f8978f48ebb56b1127adf33a49f2e69ecd46ac1f46d6cf78a79d/propcache-0.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:75e872573220d1ee2305b35c9813626e620768248425f58798413e9c39741f46", size = 46425 },
{ url = "https://files.pythonhosted.org/packages/b5/35/6c4c6fc8774a9e3629cd750dc24a7a4fb090a25ccd5c3246d127b70f9e22/propcache-0.3.0-py3-none-any.whl", hash = "sha256:67dda3c7325691c2081510e92c561f465ba61b975f481735aefdfc845d2cd043", size = 12101 },
]
[[package]] [[package]]
name = "protobuf" name = "protobuf"
version = "5.27.1" version = "5.27.1"
@ -1486,22 +1443,33 @@ sdist = { url = "https://files.pythonhosted.org/packages/aa/3e/d18f2c04cf2b528e1
[[package]] [[package]]
name = "psycopg2-binary" name = "psycopg2-binary"
version = "2.9.3" version = "2.9.10"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d7/1c/8d042630c5ff3c3e6d93c992bd7ecf516d577803b96781c6caa649bbf6e5/psycopg2-binary-2.9.3.tar.gz", hash = "sha256:761df5313dc15da1502b21453642d7599d26be88bff659382f8f9747c7ebea4e", size = 380632 } sdist = { url = "https://files.pythonhosted.org/packages/cb/0e/bdc8274dc0585090b4e3432267d7be4dfbfd8971c0fa59167c711105a6bf/psycopg2-binary-2.9.10.tar.gz", hash = "sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2", size = 385764 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/83/8f/748aa34614899181c5e420850281c18efec93f260a013d568020b38320e3/psycopg2_binary-2.9.3-cp310-cp310-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:539b28661b71da7c0e428692438efbcd048ca21ea81af618d845e06ebfd29478", size = 2192819 }, { url = "https://files.pythonhosted.org/packages/49/7d/465cc9795cf76f6d329efdafca74693714556ea3891813701ac1fee87545/psycopg2_binary-2.9.10-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:880845dfe1f85d9d5f7c412efea7a08946a46894537e4e5d091732eb1d34d9a0", size = 3044771 },
{ url = "https://files.pythonhosted.org/packages/2f/73/9cb4d4a927eec8ee835e2bc594c7473e51497616cc36818d463e601888d9/psycopg2_binary-2.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2f2534ab7dc7e776a263b463a16e189eb30e85ec9bbe1bff9e78dae802608932", size = 2012108 }, { url = "https://files.pythonhosted.org/packages/8b/31/6d225b7b641a1a2148e3ed65e1aa74fc86ba3fee850545e27be9e1de893d/psycopg2_binary-2.9.10-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9440fa522a79356aaa482aa4ba500b65f28e5d0e63b801abf6aa152a29bd842a", size = 3275336 },
{ url = "https://files.pythonhosted.org/packages/2b/20/2f1fc936f8ee4828b348aba3efacab2731995b21da0a955a25a398c0b57b/psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e82d38390a03da28c7985b394ec3f56873174e2c88130e6966cb1c946508e65", size = 3046018 }, { url = "https://files.pythonhosted.org/packages/30/b7/a68c2b4bff1cbb1728e3ec864b2d92327c77ad52edcd27922535a8366f68/psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3923c1d9870c49a2d44f795df0c889a22380d36ef92440ff618ec315757e539", size = 2851637 },
{ url = "https://files.pythonhosted.org/packages/ac/84/d01b8a9aebeae783b84f8ee09d07ee861da2f8e260772ef7f3878549bf17/psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57804fc02ca3ce0dbfbef35c4b3a4a774da66d66ea20f4bda601294ad2ea6092", size = 2988331 }, { url = "https://files.pythonhosted.org/packages/0b/b1/cfedc0e0e6f9ad61f8657fd173b2f831ce261c02a08c0b09c652b127d813/psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b2c956c028ea5de47ff3a8d6b3cc3330ab45cf0b7c3da35a2d6ff8420896526", size = 3082097 },
{ url = "https://files.pythonhosted.org/packages/7f/07/71dd915057d7ce28bc0167d3dff17166a821913085556df3fedf7968897d/psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:083a55275f09a62b8ca4902dd11f4b33075b743cf0d360419e2051a8a5d5ff76", size = 3369515 }, { url = "https://files.pythonhosted.org/packages/18/ed/0a8e4153c9b769f59c02fb5e7914f20f0b2483a19dae7bf2db54b743d0d0/psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f758ed67cab30b9a8d2833609513ce4d3bd027641673d4ebc9c067e4d208eec1", size = 3264776 },
{ url = "https://files.pythonhosted.org/packages/97/87/a73b2f93009bf66fc9b5a9aa1b8bdf94e462657bcb0a99c259d88683d217/psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:0a29729145aaaf1ad8bafe663131890e2111f13416b60e460dae0a96af5905c9", size = 3525876 }, { url = "https://files.pythonhosted.org/packages/10/db/d09da68c6a0cdab41566b74e0a6068a425f077169bed0946559b7348ebe9/psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cd9b4f2cfab88ed4a9106192de509464b75a906462fb846b936eabe45c2063e", size = 3020968 },
{ url = "https://files.pythonhosted.org/packages/62/cf/9e510ea668a22be01e3ba25deff03b9fa9a34598e6eabc714e67e868e0fb/psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a79d622f5206d695d7824cbf609a4f5b88ea6d6dab5f7c147fc6d333a8787e4", size = 1782890 }, { url = "https://files.pythonhosted.org/packages/94/28/4d6f8c255f0dfffb410db2b3f9ac5218d959a66c715c34cac31081e19b95/psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dc08420625b5a20b53551c50deae6e231e6371194fa0651dbe0fb206452ae1f", size = 2872334 },
{ url = "https://files.pythonhosted.org/packages/46/9f/536f052c80e71d37edcb8902bef319c1f8d6e7f4ba49d4a999b6cea87589/psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:090f3348c0ab2cceb6dfbe6bf721ef61262ddf518cd6cc6ecc7d334996d64efa", size = 1926105 }, { url = "https://files.pythonhosted.org/packages/05/f7/20d7bf796593c4fea95e12119d6cc384ff1f6141a24fbb7df5a668d29d29/psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d7cd730dfa7c36dbe8724426bf5612798734bff2d3c3857f36f2733f5bfc7c00", size = 2822722 },
{ url = "https://files.pythonhosted.org/packages/23/db/2383e85ceff06a2279001c027bb75406baf53d94a75c7648cb5d3b2a23d1/psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a9e1f75f96ea388fbcef36c70640c4efbe4650658f3d6a2967b4cc70e907352e", size = 1886254 }, { url = "https://files.pythonhosted.org/packages/4d/e4/0c407ae919ef626dbdb32835a03b6737013c3cc7240169843965cada2bdf/psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:155e69561d54d02b3c3209545fb08938e27889ff5a10c19de8d23eb5a41be8a5", size = 2920132 },
{ url = "https://files.pythonhosted.org/packages/cd/7f/05c6036e6482b7cddf3a12904344655defd7fc16b008d7f17f28d25d2f2a/psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c3ae8e75eb7160851e59adc77b3a19a976e50622e44fd4fd47b8b18208189d42", size = 1891250 }, { url = "https://files.pythonhosted.org/packages/2d/70/aa69c9f69cf09a01da224909ff6ce8b68faeef476f00f7ec377e8f03be70/psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3cc28a6fd5a4a26224007712e79b81dbaee2ffb90ff406256158ec4d7b52b47", size = 2959312 },
{ url = "https://files.pythonhosted.org/packages/f6/56/4c1186774f1dd75b1492e3fabc8b5c57d213ebc412e7d38de2813918bad4/psycopg2_binary-2.9.3-cp310-cp310-win32.whl", hash = "sha256:7b1e9b80afca7b7a386ef087db614faebbf8839b7f4db5eb107d0f1a53225029", size = 1025822 }, { url = "https://files.pythonhosted.org/packages/d3/bd/213e59854fafe87ba47814bf413ace0dcee33a89c8c8c814faca6bc7cf3c/psycopg2_binary-2.9.10-cp312-cp312-win32.whl", hash = "sha256:ec8a77f521a17506a24a5f626cb2aee7850f9b69a0afe704586f63a464f3cd64", size = 1025191 },
{ url = "https://files.pythonhosted.org/packages/44/4a/6b17a2907d1fd0e891f61784d916c39945a85d855badd609c87bc2d9021e/psycopg2_binary-2.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:8b344adbb9a862de0c635f4f0425b7958bf5a4b927c8594e6e8d261775796d53", size = 1167339 }, { url = "https://files.pythonhosted.org/packages/92/29/06261ea000e2dc1e22907dbbc483a1093665509ea586b29b8986a0e56733/psycopg2_binary-2.9.10-cp312-cp312-win_amd64.whl", hash = "sha256:18c5ee682b9c6dd3696dad6e54cc7ff3a1a9020df6a5c0f861ef8bfd338c3ca0", size = 1164031 },
{ url = "https://files.pythonhosted.org/packages/3e/30/d41d3ba765609c0763505d565c4d12d8f3c79793f0d0f044ff5a28bf395b/psycopg2_binary-2.9.10-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:26540d4a9a4e2b096f1ff9cce51253d0504dca5a85872c7f7be23be5a53eb18d", size = 3044699 },
{ url = "https://files.pythonhosted.org/packages/35/44/257ddadec7ef04536ba71af6bc6a75ec05c5343004a7ec93006bee66c0bc/psycopg2_binary-2.9.10-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e217ce4d37667df0bc1c397fdcd8de5e81018ef305aed9415c3b093faaeb10fb", size = 3275245 },
{ url = "https://files.pythonhosted.org/packages/1b/11/48ea1cd11de67f9efd7262085588790a95d9dfcd9b8a687d46caf7305c1a/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:245159e7ab20a71d989da00f280ca57da7641fa2cdcf71749c193cea540a74f7", size = 2851631 },
{ url = "https://files.pythonhosted.org/packages/62/e0/62ce5ee650e6c86719d621a761fe4bc846ab9eff8c1f12b1ed5741bf1c9b/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c4ded1a24b20021ebe677b7b08ad10bf09aac197d6943bfe6fec70ac4e4690d", size = 3082140 },
{ url = "https://files.pythonhosted.org/packages/27/ce/63f946c098611f7be234c0dd7cb1ad68b0b5744d34f68062bb3c5aa510c8/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3abb691ff9e57d4a93355f60d4f4c1dd2d68326c968e7db17ea96df3c023ef73", size = 3264762 },
{ url = "https://files.pythonhosted.org/packages/43/25/c603cd81402e69edf7daa59b1602bd41eb9859e2824b8c0855d748366ac9/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8608c078134f0b3cbd9f89b34bd60a943b23fd33cc5f065e8d5f840061bd0673", size = 3020967 },
{ url = "https://files.pythonhosted.org/packages/5f/d6/8708d8c6fca531057fa170cdde8df870e8b6a9b136e82b361c65e42b841e/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:230eeae2d71594103cd5b93fd29d1ace6420d0b86f4778739cb1a5a32f607d1f", size = 2872326 },
{ url = "https://files.pythonhosted.org/packages/ce/ac/5b1ea50fc08a9df82de7e1771537557f07c2632231bbab652c7e22597908/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909", size = 2822712 },
{ url = "https://files.pythonhosted.org/packages/c4/fc/504d4503b2abc4570fac3ca56eb8fed5e437bf9c9ef13f36b6621db8ef00/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1", size = 2920155 },
{ url = "https://files.pythonhosted.org/packages/b2/d1/323581e9273ad2c0dbd1902f3fb50c441da86e894b6e25a73c3fda32c57e/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567", size = 2959356 },
{ url = "https://files.pythonhosted.org/packages/08/50/d13ea0a054189ae1bc21af1d85b6f8bb9bbc5572991055d70ad9006fe2d6/psycopg2_binary-2.9.10-cp313-cp313-win_amd64.whl", hash = "sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142", size = 2569224 },
] ]
[[package]] [[package]]
@ -1587,7 +1555,6 @@ dependencies = [
{ name = "isort" }, { name = "isort" },
{ name = "mccabe" }, { name = "mccabe" },
{ name = "platformdirs" }, { name = "platformdirs" },
{ name = "tomli", marker = "python_full_version < '3.11'" },
{ name = "tomlkit" }, { name = "tomlkit" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/9c/90/28c6afd89c67ee3338108641f34809e4b8dfc4fd51128c82ff2c46edfc91/pylint-2.14.4.tar.gz", hash = "sha256:47705453aa9dce520e123a7d51843d5f0032cbfa06870f89f00927aa1f735a4a", size = 394082 } sdist = { url = "https://files.pythonhosted.org/packages/9c/90/28c6afd89c67ee3338108641f34809e4b8dfc4fd51128c82ff2c46edfc91/pylint-2.14.4.tar.gz", hash = "sha256:47705453aa9dce520e123a7d51843d5f0032cbfa06870f89f00927aa1f735a4a", size = 394082 }
@ -1668,7 +1635,7 @@ name = "pytest-cov"
version = "3.0.0" version = "3.0.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "coverage", extra = ["toml"] }, { name = "coverage" },
{ name = "pytest" }, { name = "pytest" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/61/41/e046526849972555928a6d31c2068410e47a31fb5ab0a77f868596811329/pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470", size = 61440 } sdist = { url = "https://files.pythonhosted.org/packages/61/41/e046526849972555928a6d31c2068410e47a31fb5ab0a77f868596811329/pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470", size = 61440 }
@ -1726,36 +1693,37 @@ wheels = [
[[package]] [[package]]
name = "pyyaml" name = "pyyaml"
version = "6.0" version = "6.0.2"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/36/2b/61d51a2c4f25ef062ae3f74576b01638bebad5e045f747ff12643df63844/PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", size = 124996 } sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/44/e5/4fea13230bcebf24b28c0efd774a2dd65a0937a2d39e94a4503438b078ed/PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", size = 197589 }, { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 },
{ url = "https://files.pythonhosted.org/packages/91/49/d46d7b15cddfa98533e89f3832f391aedf7e31f37b4d4df3a7a7855a7073/PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", size = 173975 }, { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 },
{ url = "https://files.pythonhosted.org/packages/5e/f4/7b4bb01873be78fc9fde307f38f62e380b7111862c165372cf094ca2b093/PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", size = 733711 }, { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 },
{ url = "https://files.pythonhosted.org/packages/ef/ad/b443cce94539e57e1a745a845f95c100ad7b97593d7e104051e43f730ecd/PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", size = 757857 }, { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 },
{ url = "https://files.pythonhosted.org/packages/02/25/6ba9f6bb50a3d4fbe22c1a02554dc670682a07c8701d1716d19ddea2c940/PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5", size = 682157 }, { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 },
{ url = "https://files.pythonhosted.org/packages/0f/93/5f81d1925ce3b531f5ff215376445ec220887cd1c9a8bde23759554dbdfd/PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", size = 138123 }, { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 },
{ url = "https://files.pythonhosted.org/packages/b7/09/2f6f4851bbca08642fef087bade095edc3c47f28d1e7bff6b20de5262a77/PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", size = 151651 }, { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 },
{ url = "https://files.pythonhosted.org/packages/f8/54/799b059314b13e1063473f76e908f44106014d18f54b16c83a16edccd5ec/PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358", size = 188559 }, { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 },
{ url = "https://files.pythonhosted.org/packages/cb/5f/05dd91f5046e2256e35d885f3b8f0f280148568f08e1bf20421887523e9a/PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1", size = 167479 }, { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 },
{ url = "https://files.pythonhosted.org/packages/7f/d9/6a0d14ac8d3b5605dc925d177c1d21ee9f0b7b39287799db1e50d197b2f4/PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d", size = 732352 }, { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 },
{ url = "https://files.pythonhosted.org/packages/68/3f/c027422e49433239267c62323fbc6320d6ac8d7d50cf0cb2a376260dad5f/PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f", size = 753020 }, { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 },
{ url = "https://files.pythonhosted.org/packages/56/8f/e8b49ad21d26111493dc2d5cae4d7efbd0e2e065440665f5023515f87f64/PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782", size = 757901 }, { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 },
{ url = "https://files.pythonhosted.org/packages/fc/48/531ecd926fe0a374346dd811bf1eda59a95583595bb80eadad511f3269b8/PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7", size = 129269 }, { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 },
{ url = "https://files.pythonhosted.org/packages/59/00/30e33fcd2a4562cd40c49c7740881009240c5cbbc0e41ca79ca4bba7c24b/PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", size = 143181 }, { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 },
{ url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 },
{ url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 },
{ url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 },
{ url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 },
] ]
[[package]] [[package]]
name = "redis" name = "redis"
version = "4.6.0" version = "5.2.1"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ sdist = { url = "https://files.pythonhosted.org/packages/47/da/d283a37303a995cd36f8b92db85135153dc4f7a8e4441aa827721b442cfb/redis-5.2.1.tar.gz", hash = "sha256:16f2e22dff21d5125e8481515e386711a34cbec50f0e44413dd7d9c060a54e0f", size = 4608355 }
{ name = "async-timeout", marker = "python_full_version <= '3.11.2'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/73/88/63d802c2b18dd9eaa5b846cbf18917c6b2882f20efda398cc16a7500b02c/redis-4.6.0.tar.gz", hash = "sha256:585dc516b9eb042a619ef0a39c3d7d55fe81bdb4df09a52c9cdde0d07bf1aa7d", size = 4561721 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/20/2e/409703d645363352a20c944f5d119bdae3eb3034051a53724a7c5fee12b8/redis-4.6.0-py3-none-any.whl", hash = "sha256:e2b03db868160ee4591de3cb90d40ebb50a90dd302138775937f6a42b7ed183c", size = 241149 }, { url = "https://files.pythonhosted.org/packages/3c/5f/fa26b9b2672cbe30e07d9a5bdf39cf16e3b80b42916757c5f92bca88e4ba/redis-5.2.1-py3-none-any.whl", hash = "sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4", size = 261502 },
] ]
[[package]] [[package]]
@ -1764,37 +1732,6 @@ version = "2023.12.25"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b5/39/31626e7e75b187fae7f121af3c538a991e725c744ac893cc2cfd70ce2853/regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5", size = 394706 } sdist = { url = "https://files.pythonhosted.org/packages/b5/39/31626e7e75b187fae7f121af3c538a991e725c744ac893cc2cfd70ce2853/regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5", size = 394706 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/59/d6/3d8fb38120053e4d7b196f32fa5c3a760f8349cdee02c021617e6e653e61/regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5", size = 497367 },
{ url = "https://files.pythonhosted.org/packages/8a/8d/8c70bce12045fa622949d3fd3e4e64a01b506a3e670dada8c5f9b3be1e34/regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8", size = 296412 },
{ url = "https://files.pythonhosted.org/packages/3d/d8/e5f7fcd33adaa3ce346ff5baf4319956873c49cbb0ed11566f921883096b/regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586", size = 291028 },
{ url = "https://files.pythonhosted.org/packages/2e/15/58c7b42d4ebc85b88696483c739d2c3b1db7234d7ab3c1aef50cf9b88d51/regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c", size = 774099 },
{ url = "https://files.pythonhosted.org/packages/40/ef/acde6b823da62186d4309de039e470e3f08311e5b40b754aec187d82939f/regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400", size = 814912 },
{ url = "https://files.pythonhosted.org/packages/7a/00/8b2322e246d0a392c91bdb43750bb900fab5d48d693c1497b3ea6656f851/regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e", size = 800527 },
{ url = "https://files.pythonhosted.org/packages/81/8a/96a62ce98e8ff1b16db56fde3debc8a571f6b7ea42ee137eb0d995cdfa26/regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4", size = 773955 },
{ url = "https://files.pythonhosted.org/packages/d6/3b/909ab8c13caf117cab2d494f4e0ba5c973a66014b15e8ccd5ec1a704f179/regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5", size = 762996 },
{ url = "https://files.pythonhosted.org/packages/3f/b1/df76e0c38fcb7b64b23bd86de820c1cfa7b3b35005122b468df8e93f2bfa/regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd", size = 690363 },
{ url = "https://files.pythonhosted.org/packages/a4/db/7d05718f5157257ee9f980d381f54efdaccb95c0db8e05071ce4d8ee3347/regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704", size = 743898 },
{ url = "https://files.pythonhosted.org/packages/2d/06/8c07ade57639bd30543b96715a0c1eef72d65aabdf7ff6f0b6b1f8bd371f/regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1", size = 731377 },
{ url = "https://files.pythonhosted.org/packages/05/3c/e77e4c13492d34171af2765c4263d35573b4b8d813f58bb33dae3da5c897/regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392", size = 764034 },
{ url = "https://files.pythonhosted.org/packages/b8/5d/d2f0a1091c00ee5a854199423609c69eaa8b48a8352a6626c0ae85265b6a/regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423", size = 768580 },
{ url = "https://files.pythonhosted.org/packages/b5/51/e884e1e021a8819251e09606354733a62decffd703ad6fd1ed9098a003a0/regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f", size = 744705 },
{ url = "https://files.pythonhosted.org/packages/ac/fc/b7b7da0eb7110d1c4529b9d74d5d1ba92f85f0ce32be72f490f5eebfcdab/regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630", size = 257749 },
{ url = "https://files.pythonhosted.org/packages/83/eb/144d2db5cf2ac3989d0ea4273040218d68bd67422133548da47043423594/regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105", size = 269481 },
{ url = "https://files.pythonhosted.org/packages/27/98/e2f151d958bea25682118c68f22e49fe98d8797aadfbf0d5df0288118c6d/regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6", size = 497418 },
{ url = "https://files.pythonhosted.org/packages/dc/c2/b3c89e9c8933ceb2a8f56fcd25f1133f21d8e490fbdbd76160dfc2c83a6e/regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97", size = 296466 },
{ url = "https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887", size = 291038 },
{ url = "https://files.pythonhosted.org/packages/9b/71/b55b5ffc75918a96ea99794783524609ac3ff9e2d8f51e7ece8648a968f6/regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb", size = 783871 },
{ url = "https://files.pythonhosted.org/packages/c1/69/b9671621092a1f9b16892bc638368efb3ce00648ce79b91d472feaa740c9/regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c", size = 823445 },
{ url = "https://files.pythonhosted.org/packages/8d/fc/8ade283909c52f795bdc9b9fe44f85c6da5417f9be84c3d245706406551e/regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b", size = 810161 },
{ url = "https://files.pythonhosted.org/packages/8d/6b/2f6478814954c07c04ba60b78d688d3d7bab10d786e0b6c1db607e4f6673/regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa", size = 785105 },
{ url = "https://files.pythonhosted.org/packages/2a/3a/9601d6e8a49ce7a124268c4c79d54f22416242e5096cd4fca07f7bfac46b/regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7", size = 772823 },
{ url = "https://files.pythonhosted.org/packages/c8/b5/882aa0697e46d29a9f796c91221e03b1beec3c29664718c7d26ce05e7fb8/regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0", size = 749953 },
{ url = "https://files.pythonhosted.org/packages/00/d4/d876ce23d76103db84f3b2aeb3cba7c6b9b5750a2e2125ef6bfa2be53deb/regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe", size = 738427 },
{ url = "https://files.pythonhosted.org/packages/70/0f/311ada39601c7bd7904b6ab3b01b414438a16efab5f2009f35a273999942/regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80", size = 770450 },
{ url = "https://files.pythonhosted.org/packages/e3/66/29a1feac5c69907fedd6b3d8562d5ddc7c28fdf8585da6484617fe4c0b5e/regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd", size = 776326 },
{ url = "https://files.pythonhosted.org/packages/97/33/101559f6506a98b55613efa484d072d23fdeca3ef6876d43a8c49c7ec65f/regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4", size = 752942 },
{ url = "https://files.pythonhosted.org/packages/92/2a/6431462df58f29515be33fa8b3800efa73b2be47664e71af557101e2a733/regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87", size = 257757 },
{ url = "https://files.pythonhosted.org/packages/a8/01/18232f93672c1d530834e2e0568a80eaab1df12d67ae499b1762ab462b5c/regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f", size = 269492 },
{ url = "https://files.pythonhosted.org/packages/8b/b8/14527ca54351156f65c90f8728ee62e646a484dbce0e4cbffb34489e5bb0/regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715", size = 500440 }, { url = "https://files.pythonhosted.org/packages/8b/b8/14527ca54351156f65c90f8728ee62e646a484dbce0e4cbffb34489e5bb0/regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715", size = 500440 },
{ url = "https://files.pythonhosted.org/packages/0b/d4/5498d06a7a05be1b3e1e553d60fb61292afe5ca9fdc2aea5283f30651f1b/regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d", size = 298103 }, { url = "https://files.pythonhosted.org/packages/0b/d4/5498d06a7a05be1b3e1e553d60fb61292afe5ca9fdc2aea5283f30651f1b/regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d", size = 298103 },
{ url = "https://files.pythonhosted.org/packages/66/65/90e759a89534b850fa20e533e587748e967c44f58333b40f6d62718df1b1/regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a", size = 292245 }, { url = "https://files.pythonhosted.org/packages/66/65/90e759a89534b850fa20e533e587748e967c44f58333b40f6d62718df1b1/regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a", size = 292245 },
@ -1867,11 +1804,11 @@ wheels = [
[[package]] [[package]]
name = "ruamel-yaml" name = "ruamel-yaml"
version = "0.16.12" version = "0.17.4"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/17/2f/f38332bf6ba751d1c8124ea70681d2b2326d69126d9058fbd9b4c434d268/ruamel.yaml-0.16.12.tar.gz", hash = "sha256:076cc0bc34f1966d920a49f18b52b6ad559fbe656a0748e3535cf7b3f29ebf9e", size = 147355 } sdist = { url = "https://files.pythonhosted.org/packages/62/cf/148028462ab88a71046ba0a30780357ae9e07125863ea9ca7808f1ea3798/ruamel.yaml-0.17.4.tar.gz", hash = "sha256:44bc6b54fddd45e4bc0619059196679f9e8b79c027f4131bb072e6a22f4d5e28", size = 119758 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/7e/39/186f14f3836ac5d2a6a042c8de69988770e8b9abb537610edc429e4914aa/ruamel.yaml-0.16.12-py2.py3-none-any.whl", hash = "sha256:012b9470a0ea06e4e44e99e7920277edf6b46eee0232a04487ea73a7386340a5", size = 111129 }, { url = "https://files.pythonhosted.org/packages/29/4e/c3105bbbbc662f6a671a505f00ec771e93b5254f09fbb06002af9087071a/ruamel.yaml-0.17.4-py3-none-any.whl", hash = "sha256:ac79fb25f5476e8e9ed1c53b8a2286d2c3f5dde49eb37dbcee5c7eb6a8415a22", size = 101915 },
] ]
[[package]] [[package]]
@ -1976,6 +1913,7 @@ dependencies = [
{ name = "ipython" }, { name = "ipython" },
{ name = "itsdangerous" }, { name = "itsdangerous" },
{ name = "jwcrypto" }, { name = "jwcrypto" },
{ name = "limits" },
{ name = "markupsafe" }, { name = "markupsafe" },
{ name = "memory-profiler" }, { name = "memory-profiler" },
{ name = "newrelic" }, { name = "newrelic" },
@ -1996,6 +1934,7 @@ dependencies = [
{ name = "sentry-sdk" }, { name = "sentry-sdk" },
{ name = "sqlalchemy" }, { name = "sqlalchemy" },
{ name = "sqlalchemy-utils" }, { name = "sqlalchemy-utils" },
{ name = "strictyaml" },
{ name = "tldextract" }, { name = "tldextract" },
{ name = "twilio" }, { name = "twilio" },
{ name = "unidecode" }, { name = "unidecode" },
@ -2024,15 +1963,15 @@ requires-dist = [
{ name = "alembic", specifier = "~=1.4.3" }, { name = "alembic", specifier = "~=1.4.3" },
{ name = "arrow", specifier = "~=0.16.0" }, { name = "arrow", specifier = "~=0.16.0" },
{ name = "bcrypt", specifier = "~=3.2.0" }, { name = "bcrypt", specifier = "~=3.2.0" },
{ name = "blinker", specifier = "~=1.4" }, { name = "blinker", specifier = "~=1.9.0" },
{ name = "boto3", specifier = "~=1.35.37" }, { name = "boto3", specifier = "~=1.35.37" },
{ name = "coinbase-commerce", specifier = "~=1.0.1" }, { name = "coinbase-commerce", specifier = "~=1.0.1" },
{ name = "coloredlogs", specifier = "~=14.0" }, { name = "coloredlogs", specifier = "~=14.0" },
{ name = "cryptography", specifier = "~=37.0.1" }, { name = "cryptography", specifier = "~=37.0.1" },
{ name = "deprecated", specifier = "~=1.2.13" }, { name = "deprecated", specifier = "~=1.2.13" },
{ name = "dkimpy", specifier = "~=1.0.5" }, { name = "dkimpy", specifier = "==1.0.5" },
{ name = "dnspython", specifier = "==2.0.0" }, { name = "dnspython", specifier = "~=2.7.0" },
{ name = "email-validator", specifier = "~=1.1.3" }, { name = "email-validator", specifier = "~=2.2.0" },
{ name = "facebook-sdk", specifier = "~=3.1.0" }, { name = "facebook-sdk", specifier = "~=3.1.0" },
{ name = "flanker", specifier = "~=0.9.11" }, { name = "flanker", specifier = "~=0.9.11" },
{ name = "flask", specifier = "~=1.1.2" }, { name = "flask", specifier = "~=1.1.2" },
@ -2040,7 +1979,7 @@ requires-dist = [
{ name = "flask-cors", specifier = "~=3.0.9" }, { name = "flask-cors", specifier = "~=3.0.9" },
{ name = "flask-debugtoolbar", specifier = "~=0.11.0" }, { name = "flask-debugtoolbar", specifier = "~=0.11.0" },
{ name = "flask-debugtoolbar-sqlalchemy", specifier = "~=0.2.0" }, { name = "flask-debugtoolbar-sqlalchemy", specifier = "~=0.2.0" },
{ name = "flask-limiter", specifier = "==1.4" }, { name = "flask-limiter", specifier = "==1.5" },
{ name = "flask-login", specifier = "~=0.5.0" }, { name = "flask-login", specifier = "~=0.5.0" },
{ name = "flask-migrate", specifier = "~=2.5.3" }, { name = "flask-migrate", specifier = "~=2.5.3" },
{ name = "flask-profiler", specifier = "~=1.8.1" }, { name = "flask-profiler", specifier = "~=1.8.1" },
@ -2052,13 +1991,14 @@ requires-dist = [
{ name = "ipython", specifier = "~=7.31.1" }, { name = "ipython", specifier = "~=7.31.1" },
{ name = "itsdangerous", specifier = "~=1.1.0" }, { name = "itsdangerous", specifier = "~=1.1.0" },
{ name = "jwcrypto", specifier = "~=0.8" }, { name = "jwcrypto", specifier = "~=0.8" },
{ name = "limits", specifier = "~=4.0.1" },
{ name = "markupsafe", specifier = "~=1.1.1" }, { name = "markupsafe", specifier = "~=1.1.1" },
{ name = "memory-profiler", specifier = "~=0.57.0" }, { name = "memory-profiler", specifier = "~=0.57.0" },
{ name = "newrelic", specifier = "~=8.8.0" }, { name = "newrelic", specifier = "~=8.8.0" },
{ name = "newrelic-telemetry-sdk", specifier = "~=0.5.0" }, { name = "newrelic-telemetry-sdk", specifier = "~=0.5.0" },
{ name = "pgpy", specifier = "==0.5.4" }, { name = "pgpy", specifier = "==0.5.4" },
{ name = "phpserialize", specifier = "~=1.3" }, { name = "phpserialize", specifier = "~=1.3" },
{ name = "psycopg2-binary", specifier = "~=2.9.3" }, { name = "psycopg2-binary", specifier = "~=2.9.10" },
{ name = "pycryptodome", specifier = "~=3.9.8" }, { name = "pycryptodome", specifier = "~=3.9.8" },
{ name = "pyopenssl", specifier = "~=19.1.0" }, { name = "pyopenssl", specifier = "~=19.1.0" },
{ name = "pyotp", specifier = "~=2.4.0" }, { name = "pyotp", specifier = "~=2.4.0" },
@ -2066,13 +2006,14 @@ requires-dist = [
{ name = "pyspf", specifier = "~=2.0.14" }, { name = "pyspf", specifier = "~=2.0.14" },
{ name = "python-dotenv", specifier = "~=0.14.0" }, { name = "python-dotenv", specifier = "~=0.14.0" },
{ name = "python-gnupg", specifier = "~=0.4.6" }, { name = "python-gnupg", specifier = "~=0.4.6" },
{ name = "redis", specifier = "==4.6.0" }, { name = "redis", specifier = "==5.2.1" },
{ name = "requests", specifier = "~=2.25.1" }, { name = "requests", specifier = "~=2.25.1" },
{ name = "requests-oauthlib", specifier = "~=1.3.0" }, { name = "requests-oauthlib", specifier = "~=1.3.0" },
{ name = "sentry-sdk", specifier = "~=2.20.0" }, { name = "sentry-sdk", specifier = "~=2.20.0" },
{ name = "sqlalchemy", specifier = "~=1.3.24" }, { name = "sqlalchemy", specifier = "~=1.3.24" },
{ name = "sqlalchemy-utils", specifier = "==0.36.8" }, { name = "sqlalchemy-utils", specifier = "==0.36.8" },
{ name = "sqlalchemy-utils", specifier = "~=0.36.8" }, { name = "sqlalchemy-utils", specifier = "~=0.36.8" },
{ name = "strictyaml", specifier = "~=1.7.3" },
{ name = "tldextract", specifier = "~=3.1.2" }, { name = "tldextract", specifier = "~=3.1.2" },
{ name = "twilio", specifier = "~=7.3.2" }, { name = "twilio", specifier = "~=7.3.2" },
{ name = "unidecode", specifier = "~=1.1.1" }, { name = "unidecode", specifier = "~=1.1.1" },
@ -2080,14 +2021,14 @@ requires-dist = [
{ name = "webauthn", specifier = "~=0.4.7" }, { name = "webauthn", specifier = "~=0.4.7" },
{ name = "werkzeug", specifier = "~=1.0.1" }, { name = "werkzeug", specifier = "~=1.0.1" },
{ name = "wtforms", specifier = "~=2.3.3" }, { name = "wtforms", specifier = "~=2.3.3" },
{ name = "yacron", specifier = "~=0.11.2" }, { name = "yacron", specifier = "~=0.19.0" },
] ]
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [ dev = [
{ name = "black", specifier = "~=22.1.0" }, { name = "black", specifier = "~=22.1.0" },
{ name = "djlint", specifier = "==1.34.1" }, { name = "djlint", specifier = "==1.34.1" },
{ name = "pre-commit", specifier = "~=2.17.0" }, { name = "pre-commit", specifier = "~=4.1.0" },
{ name = "pylint", specifier = "~=2.14.4" }, { name = "pylint", specifier = "~=2.14.4" },
{ name = "pytest", specifier = "~=7.0.0" }, { name = "pytest", specifier = "~=7.0.0" },
{ name = "pytest-cov", specifier = "~=3.0.0" }, { name = "pytest-cov", specifier = "~=3.0.0" },
@ -2096,11 +2037,11 @@ dev = [
[[package]] [[package]]
name = "six" name = "six"
version = "1.15.0" version = "1.17.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/6b/34/415834bfdafca3c5f451532e8a8d9ba89a21c9743a0c59fbd0205c7f9426/six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", size = 33917 } sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/ee/ff/48bde5c0f013094d729fe4b0316ba2a24774b3ff1c52d924a8a4cb04078a/six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced", size = 10963 }, { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 },
] ]
[[package]] [[package]]
@ -2130,13 +2071,15 @@ wheels = [
[[package]] [[package]]
name = "strictyaml" name = "strictyaml"
version = "1.1.0" version = "1.7.3"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "python-dateutil" }, { name = "python-dateutil" },
{ name = "ruamel-yaml" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/a6/94/4030aaa69482a2c0780d03e354a8f8273bd49d4c99a3b5fd73710283cf7a/strictyaml-1.1.0.tar.gz", hash = "sha256:6b07dbd4f77ab023ed4167c43ffc1b9f9354fb6075cc6ff3b91fefcbb80342ca", size = 50092 } sdist = { url = "https://files.pythonhosted.org/packages/b3/08/efd28d49162ce89c2ad61a88bd80e11fb77bc9f6c145402589112d38f8af/strictyaml-1.7.3.tar.gz", hash = "sha256:22f854a5fcab42b5ddba8030a0e4be51ca89af0267961c8d6cfa86395586c407", size = 115206 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/96/7c/a81ef5ef10978dd073a854e0fa93b5d8021d0594b639cc8f6453c3c78a1d/strictyaml-1.7.3-py3-none-any.whl", hash = "sha256:fb5c8a4edb43bebb765959e420f9b3978d7f1af88c80606c03fb420888f5d1c7", size = 123917 },
]
[[package]] [[package]]
name = "tld" name = "tld"
@ -2166,15 +2109,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c5/1e/58ad28cd1c6be6d37ec86b3f4790770f1cc49050d479fe773573a4704bc0/tldextract-3.1.2-py2.py3-none-any.whl", hash = "sha256:f55e05f6bf4cc952a87d13594386d32ad2dd265630a8bdfc3df03bd60425c6b0", size = 87096 }, { url = "https://files.pythonhosted.org/packages/c5/1e/58ad28cd1c6be6d37ec86b3f4790770f1cc49050d479fe773573a4704bc0/tldextract-3.1.2-py2.py3-none-any.whl", hash = "sha256:f55e05f6bf4cc952a87d13594386d32ad2dd265630a8bdfc3df03bd60425c6b0", size = 87096 },
] ]
[[package]]
name = "toml"
version = "0.10.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/be/ba/1f744cdc819428fc6b5084ec34d9b30660f6f9daaf70eead706e3203ec3c/toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f", size = 22253 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", size = 16588 },
]
[[package]] [[package]]
name = "tomli" name = "tomli"
version = "2.0.1" version = "2.0.1"
@ -2364,26 +2298,6 @@ version = "1.15.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f8/7d/73e4e3cdb2c780e13f9d87dc10488d7566d8fd77f8d68f0e416bfbd144c7/wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a", size = 53519 } sdist = { url = "https://files.pythonhosted.org/packages/f8/7d/73e4e3cdb2c780e13f9d87dc10488d7566d8fd77f8d68f0e416bfbd144c7/wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a", size = 53519 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/0c/6e/f80c23efc625c10460240e31dcb18dd2b34b8df417bc98521fbfd5bc2e9a/wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923", size = 35834 },
{ url = "https://files.pythonhosted.org/packages/96/37/a33c1220e8a298ab18eb070b6a59e4ccc3f7344b434a7ac4bd5d4bdccc97/wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee", size = 36664 },
{ url = "https://files.pythonhosted.org/packages/fb/bd/ca7fd05a45e7022f3b780a709bbdb081a6138d828ecdb5b7df113a3ad3be/wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727", size = 78504 },
{ url = "https://files.pythonhosted.org/packages/94/55/91dd3a7efbc1db2b07bbfc490d48e8484852c355d55e61e8b1565d7725f6/wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7", size = 70949 },
{ url = "https://files.pythonhosted.org/packages/7f/b6/6dc0ddacd20337b4ce6ab0d6b0edc7da3898f85c4f97df7f30267e57509e/wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0", size = 78426 },
{ url = "https://files.pythonhosted.org/packages/48/65/0061e7432ca4b635e96e60e27e03a60ddaca3aeccc30e7415fed0325c3c2/wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec", size = 82908 },
{ url = "https://files.pythonhosted.org/packages/88/f1/4dfaa1ad111d2a48429dca133e46249922ee2f279e9fdd4ab5b149cd6c71/wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90", size = 75818 },
{ url = "https://files.pythonhosted.org/packages/2b/fb/c31489631bb94ac225677c1090f787a4ae367614b5277f13dbfde24b2b69/wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975", size = 82931 },
{ url = "https://files.pythonhosted.org/packages/a9/64/886e512f438f12424b48a3ab23ae2583ec633be6e13eb97b0ccdff8e328a/wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1", size = 33884 },
{ url = "https://files.pythonhosted.org/packages/a6/32/f4868adc994648fac4cfe347bcc1381c9afcb1602c8ba0910f36b96c5449/wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e", size = 36027 },
{ url = "https://files.pythonhosted.org/packages/e8/86/fc38e58843159bdda745258d872b1187ad916087369ec57ef93f5e832fa8/wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7", size = 35838 },
{ url = "https://files.pythonhosted.org/packages/6b/b0/bde5400fdf6d18cb7ef527831de0f86ac206c4da1670b67633e5a547b05f/wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72", size = 36661 },
{ url = "https://files.pythonhosted.org/packages/ca/1c/5caf61431705b3076ca1152abfd6da6304697d7d4fe48bb3448a6decab40/wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb", size = 79014 },
{ url = "https://files.pythonhosted.org/packages/8f/87/ba6dc86e8edb28fd1e314446301802751bd3157e9780385c9eef633994b9/wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e", size = 71480 },
{ url = "https://files.pythonhosted.org/packages/b9/40/975fbb1ab03fa987900bacc365645c4cbead22baddd273b4f5db7f9843d2/wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c", size = 78916 },
{ url = "https://files.pythonhosted.org/packages/23/0a/9964d7141b8c5e31c32425d3412662a7873aaf0c0964166f4b37b7db51b6/wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3", size = 83849 },
{ url = "https://files.pythonhosted.org/packages/ee/25/83f5dcd9f96606521da2d0e7a03a18800264eafb59b569ff109c4d2fea67/wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92", size = 76827 },
{ url = "https://files.pythonhosted.org/packages/5d/c4/3cc25541ec0404dd1d178e7697a34814d77be1e489cd6f8cb055ac688314/wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98", size = 83840 },
{ url = "https://files.pythonhosted.org/packages/ec/f4/f84538a367105f0a7e507f0c6766d3b15b848fd753647bbf0c206399b322/wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416", size = 33881 },
{ url = "https://files.pythonhosted.org/packages/dd/42/9eedee19435dfc0478cdb8bdc71800aab15a297d1074f1aae0d9489adbc3/wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705", size = 36028 },
{ url = "https://files.pythonhosted.org/packages/f8/f8/e068dafbb844c1447c55b23c921f3d338cddaba4ea53187a7dd0058452d9/wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640", size = 22007 }, { url = "https://files.pythonhosted.org/packages/f8/f8/e068dafbb844c1447c55b23c921f3d338cddaba4ea53187a7dd0058452d9/wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640", size = 22007 },
] ]
@ -2401,7 +2315,7 @@ wheels = [
[[package]] [[package]]
name = "yacron" name = "yacron"
version = "0.11.2" version = "0.19.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "aiohttp" }, { name = "aiohttp" },
@ -2409,54 +2323,59 @@ dependencies = [
{ name = "crontab" }, { name = "crontab" },
{ name = "jinja2" }, { name = "jinja2" },
{ name = "pytz" }, { name = "pytz" },
{ name = "ruamel-yaml" },
{ name = "sentry-sdk" }, { name = "sentry-sdk" },
{ name = "strictyaml" }, { name = "strictyaml" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/e4/af/459b812770b655a40ade2177ebcd10540a11b70fa43dc5382dea25010a11/yacron-0.11.2.tar.gz", hash = "sha256:5d8da679f3ab503c7871845f3034876af4828aad5ac8eff066413e77ac3bc772", size = 42325 } sdist = { url = "https://files.pythonhosted.org/packages/d2/95/890428da58784bafd48c260eb351656af3389c506affad225f1c7c19bf5b/yacron-0.19.0.tar.gz", hash = "sha256:666e43affebc61f6c4ccd55cbc719d5f2da99138c0c14b21a40dfd943633dcc0", size = 51494 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/83/92/34b20fde170101b0ff17f7dfe5c647705b5986631cecf156ef3777c03c77/yacron-0.11.2-py3-none-any.whl", hash = "sha256:2f5bf07f7064c9a8a335ec7311177dc057cd122eb478373cd76597e0872941f9", size = 22671 }, { url = "https://files.pythonhosted.org/packages/af/91/398a5f7b6f28d627f3c767358a029bde7ff0d9b87b071baba80e2ef15e18/yacron-0.19.0-py3-none-any.whl", hash = "sha256:ffde4d769101bc24455860aa8d88c6e4e9e07dc8820b07a9397f47a3bca73d05", size = 27799 },
] ]
[[package]] [[package]]
name = "yarl" name = "yarl"
version = "1.9.2" version = "1.18.3"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "idna" }, { name = "idna" },
{ name = "multidict" }, { name = "multidict" },
{ name = "propcache" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/5f/3f/04b3c5e57844fb9c034b09c5cb6d2b43de5d64a093c30529fd233e16cf09/yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571", size = 184673 } sdist = { url = "https://files.pythonhosted.org/packages/b7/9d/4b94a8e6d2b51b599516a5cb88e5bc99b4d8d4583e468057eaa29d5f0918/yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1", size = 181062 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/eb/cb/4970008c85810c7d0e154ac5d746451b04476ac1dd85dc538563a1c04698/yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82", size = 100297 }, { url = "https://files.pythonhosted.org/packages/33/85/bd2e2729752ff4c77338e0102914897512e92496375e079ce0150a6dc306/yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50", size = 142644 },
{ url = "https://files.pythonhosted.org/packages/19/ed/deeec0a15bf1d9a3d2d2102ebb9dbd84dc312a00fbf88564b56b05f266a1/yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8", size = 65747 }, { url = "https://files.pythonhosted.org/packages/ff/74/1178322cc0f10288d7eefa6e4a85d8d2e28187ccab13d5b844e8b5d7c88d/yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576", size = 94962 },
{ url = "https://files.pythonhosted.org/packages/6a/67/1ea83dd287358d47adc49f2aeb9e4e8ae72bec8ae2604c3bcae1e7fd73de/yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9", size = 62619 }, { url = "https://files.pythonhosted.org/packages/be/75/79c6acc0261e2c2ae8a1c41cf12265e91628c8c58ae91f5ff59e29c0787f/yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640", size = 92795 },
{ url = "https://files.pythonhosted.org/packages/a8/ce/95614d05af568504884e866d772c9f03235711f5a4d7fccfae54ce82d39d/yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560", size = 262071 }, { url = "https://files.pythonhosted.org/packages/6b/32/927b2d67a412c31199e83fefdce6e645247b4fb164aa1ecb35a0f9eb2058/yarl-1.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2", size = 332368 },
{ url = "https://files.pythonhosted.org/packages/63/80/95ae601d7b7f5f6b53174d91d94df865db9166895934d5065e924634dc76/yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac", size = 271262 }, { url = "https://files.pythonhosted.org/packages/19/e5/859fca07169d6eceeaa4fde1997c91d8abde4e9a7c018e371640c2da2b71/yarl-1.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75", size = 342314 },
{ url = "https://files.pythonhosted.org/packages/2d/76/d9178fe8fe5823370b26bbd1bbb159c2cc3f7449cade1a50818bcfc98cae/yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea", size = 270513 }, { url = "https://files.pythonhosted.org/packages/08/75/76b63ccd91c9e03ab213ef27ae6add2e3400e77e5cdddf8ed2dbc36e3f21/yarl-1.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512", size = 341987 },
{ url = "https://files.pythonhosted.org/packages/c9/d4/a5280faa1b8e9ad3a52ddc4c9aea94dd718f9c55f1e10cfb14580f5ebb45/yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608", size = 268794 }, { url = "https://files.pythonhosted.org/packages/1a/e1/a097d5755d3ea8479a42856f51d97eeff7a3a7160593332d98f2709b3580/yarl-1.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba", size = 336914 },
{ url = "https://files.pythonhosted.org/packages/78/1d/0554e6d4c8669ca707e93f188111e29cf8a3c97cf2e8e8448ad3b284ae84/yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5", size = 258911 }, { url = "https://files.pythonhosted.org/packages/0b/42/e1b4d0e396b7987feceebe565286c27bc085bf07d61a59508cdaf2d45e63/yarl-1.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb", size = 325765 },
{ url = "https://files.pythonhosted.org/packages/0e/b1/a65fcf0363ae8c08c0e586772a34cc15b4200bae163eed24258cc95cda90/yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0", size = 246511 }, { url = "https://files.pythonhosted.org/packages/7e/18/03a5834ccc9177f97ca1bbb245b93c13e58e8225276f01eedc4cc98ab820/yarl-1.18.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272", size = 344444 },
{ url = "https://files.pythonhosted.org/packages/19/41/97678e848ce963cd3e89c4dcc13900c9afedd42e5c7d9cfb019716f8bb2a/yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4", size = 248113 }, { url = "https://files.pythonhosted.org/packages/c8/03/a713633bdde0640b0472aa197b5b86e90fbc4c5bc05b727b714cd8a40e6d/yarl-1.18.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6", size = 340760 },
{ url = "https://files.pythonhosted.org/packages/e5/12/4fd9a60b167b00a58552020babb638f9b43c514da0227df9fc6bdf16948f/yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095", size = 254993 }, { url = "https://files.pythonhosted.org/packages/eb/99/f6567e3f3bbad8fd101886ea0276c68ecb86a2b58be0f64077396cd4b95e/yarl-1.18.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e", size = 346484 },
{ url = "https://files.pythonhosted.org/packages/e4/a7/6ffee644828e01c6d6ae177ac6cba56255bb793f79c4d32082a895bf8b91/yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3", size = 257710 }, { url = "https://files.pythonhosted.org/packages/8e/a9/84717c896b2fc6cb15bd4eecd64e34a2f0a9fd6669e69170c73a8b46795a/yarl-1.18.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb", size = 359864 },
{ url = "https://files.pythonhosted.org/packages/15/5a/5435fe438874f03aa9f559c5173418fbac680b095ac394e88b0825d12ebd/yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528", size = 252871 }, { url = "https://files.pythonhosted.org/packages/1e/2e/d0f5f1bef7ee93ed17e739ec8dbcb47794af891f7d165fa6014517b48169/yarl-1.18.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393", size = 364537 },
{ url = "https://files.pythonhosted.org/packages/30/55/eda822473c6206470a89ca3550efa23202310a2e56317e55afb709008fd5/yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3", size = 57438 }, { url = "https://files.pythonhosted.org/packages/97/8a/568d07c5d4964da5b02621a517532adb8ec5ba181ad1687191fffeda0ab6/yarl-1.18.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285", size = 357861 },
{ url = "https://files.pythonhosted.org/packages/98/21/9ef4adf36cfac771518c3bf687bc9b92451bdaf01ec770879f19e7e5b3c7/yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde", size = 61006 }, { url = "https://files.pythonhosted.org/packages/7d/e3/924c3f64b6b3077889df9a1ece1ed8947e7b61b0a933f2ec93041990a677/yarl-1.18.3-cp312-cp312-win32.whl", hash = "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2", size = 84097 },
{ url = "https://files.pythonhosted.org/packages/84/c1/eaebee42cbcace2d5b5eb103cae668dec1c239f5c82b90da4b3b20f39419/yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6", size = 97602 }, { url = "https://files.pythonhosted.org/packages/34/45/0e055320daaabfc169b21ff6174567b2c910c45617b0d79c68d7ab349b02/yarl-1.18.3-cp312-cp312-win_amd64.whl", hash = "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477", size = 90399 },
{ url = "https://files.pythonhosted.org/packages/fe/7d/9d85f658b6f7c041ca3ba371d133040c4dc41eb922aef0a6ba917291d187/yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb", size = 64436 }, { url = "https://files.pythonhosted.org/packages/30/c7/c790513d5328a8390be8f47be5d52e141f78b66c6c48f48d241ca6bd5265/yarl-1.18.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb", size = 140789 },
{ url = "https://files.pythonhosted.org/packages/b3/81/fb394392ec748d8fce66212b29dc2fd9b2fd8e30d56d818a6a866708e534/yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0", size = 61273 }, { url = "https://files.pythonhosted.org/packages/30/aa/a2f84e93554a578463e2edaaf2300faa61c8701f0898725842c704ba5444/yarl-1.18.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa", size = 94144 },
{ url = "https://files.pythonhosted.org/packages/53/87/f5588bdc6eba3ca4521bd37094563e8442ba2cff3d6b7e5a2cab48fdc96d/yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2", size = 278187 }, { url = "https://files.pythonhosted.org/packages/c6/fc/d68d8f83714b221a85ce7866832cba36d7c04a68fa6a960b908c2c84f325/yarl-1.18.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782", size = 91974 },
{ url = "https://files.pythonhosted.org/packages/b7/aa/8b53bceea5454d0b5602ffc81aaf3b80cc2e9b793fe1e054f690beb82429/yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191", size = 286869 }, { url = "https://files.pythonhosted.org/packages/56/4e/d2563d8323a7e9a414b5b25341b3942af5902a2263d36d20fb17c40411e2/yarl-1.18.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0", size = 333587 },
{ url = "https://files.pythonhosted.org/packages/35/0f/a68344daf90536755f4a890dbbab65dc6ca58c4a0268cf79bd7c5ddc1468/yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d", size = 287498 }, { url = "https://files.pythonhosted.org/packages/25/c9/cfec0bc0cac8d054be223e9f2c7909d3e8442a856af9dbce7e3442a8ec8d/yarl-1.18.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482", size = 344386 },
{ url = "https://files.pythonhosted.org/packages/ee/8d/55467943a172b97c1b5d9569433c1a70f86f1f9b0f1c6574285f8ad02fc2/yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7", size = 282833 }, { url = "https://files.pythonhosted.org/packages/ab/5d/4c532190113b25f1364d25f4c319322e86232d69175b91f27e3ebc2caf9a/yarl-1.18.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186", size = 345421 },
{ url = "https://files.pythonhosted.org/packages/50/af/93f1b6d02e936d49e664a8eb4374877e5bacfef115c956939729ac9e2ca8/yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6", size = 270604 }, { url = "https://files.pythonhosted.org/packages/23/d1/6cdd1632da013aa6ba18cee4d750d953104a5e7aac44e249d9410a972bf5/yarl-1.18.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58", size = 339384 },
{ url = "https://files.pythonhosted.org/packages/de/3f/5a8fcff69c8628ce4dab00612981f4c0598fb9aabd90d01a1ebb037bb6f6/yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8", size = 248759 }, { url = "https://files.pythonhosted.org/packages/9a/c4/6b3c39bec352e441bd30f432cda6ba51681ab19bb8abe023f0d19777aad1/yarl-1.18.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53", size = 326689 },
{ url = "https://files.pythonhosted.org/packages/1d/78/a273c991086df02837676dc68ccf50d56b2fe624d75258d521c651a65d82/yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9", size = 244303 }, { url = "https://files.pythonhosted.org/packages/23/30/07fb088f2eefdc0aa4fc1af4e3ca4eb1a3aadd1ce7d866d74c0f124e6a85/yarl-1.18.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2", size = 345453 },
{ url = "https://files.pythonhosted.org/packages/62/c8/b8e048ba98a0f41d46a22060a57f913b4f9ed9c4f6862de36b8137bb67e2/yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be", size = 256862 }, { url = "https://files.pythonhosted.org/packages/63/09/d54befb48f9cd8eec43797f624ec37783a0266855f4930a91e3d5c7717f8/yarl-1.18.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8", size = 341872 },
{ url = "https://files.pythonhosted.org/packages/3b/b2/34e45989fa5fcf406dd471c517697a5bf483fb1bcaebcf2bedd2b86e0cbb/yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7", size = 260845 }, { url = "https://files.pythonhosted.org/packages/91/26/fd0ef9bf29dd906a84b59f0cd1281e65b0c3e08c6aa94b57f7d11f593518/yarl-1.18.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1", size = 347497 },
{ url = "https://files.pythonhosted.org/packages/d5/8b/5a30baa12464d55b308c684a4a953df6b2190f7733c92719f194fcd42421/yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a", size = 251689 }, { url = "https://files.pythonhosted.org/packages/d9/b5/14ac7a256d0511b2ac168d50d4b7d744aea1c1aa20c79f620d1059aab8b2/yarl-1.18.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a", size = 359981 },
{ url = "https://files.pythonhosted.org/packages/d9/cb/0bfa73fad2049b6315ace645df2bd0682e20f9eb2dac120c2e9183359aa1/yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8", size = 56694 }, { url = "https://files.pythonhosted.org/packages/ca/b3/d493221ad5cbd18bc07e642894030437e405e1413c4236dd5db6e46bcec9/yarl-1.18.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10", size = 366229 },
{ url = "https://files.pythonhosted.org/packages/6b/83/e0cb0cbb37098475fca29b8c5000fed417b67fc2c6dc8d0fa7e32c000c80/yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051", size = 60212 }, { url = "https://files.pythonhosted.org/packages/04/56/6a3e2a5d9152c56c346df9b8fb8edd2c8888b1e03f96324d457e5cf06d34/yarl-1.18.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8", size = 360383 },
{ url = "https://files.pythonhosted.org/packages/fd/b7/4b3c7c7913a278d445cc6284e59b2e62fa25e72758f888b7a7a39eb8423f/yarl-1.18.3-cp313-cp313-win32.whl", hash = "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d", size = 310152 },
{ url = "https://files.pythonhosted.org/packages/f5/d5/688db678e987c3e0fb17867970700b92603cadf36c56e5fb08f23e822a0c/yarl-1.18.3-cp313-cp313-win_amd64.whl", hash = "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c", size = 315723 },
{ url = "https://files.pythonhosted.org/packages/f5/4b/a06e0ec3d155924f77835ed2d167ebd3b211a7b0853da1cf8d8414d784ef/yarl-1.18.3-py3-none-any.whl", hash = "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b", size = 45109 },
] ]
[[package]] [[package]]