diff --git a/.python-version b/.python-version index 24ee5b1..e4fba21 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.13 +3.12 diff --git a/.tool-versions b/.tool-versions index 522a41e..1d7a709 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -python 3.13.3t +python 3.12.3 diff --git a/maildir_gtd/__pycache__/__init__.cpython-311.pyc b/maildir_gtd/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index c4e5f86..0000000 Binary files a/maildir_gtd/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/__pycache__/utils.cpython-311.pyc b/maildir_gtd/__pycache__/utils.cpython-311.pyc deleted file mode 100644 index 07626f1..0000000 Binary files a/maildir_gtd/__pycache__/utils.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/actions/__pycache__/__init__.cpython-311.pyc b/maildir_gtd/actions/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index e65fb05..0000000 Binary files a/maildir_gtd/actions/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/actions/__pycache__/archive.cpython-311.pyc b/maildir_gtd/actions/__pycache__/archive.cpython-311.pyc deleted file mode 100644 index 914c7e8..0000000 Binary files a/maildir_gtd/actions/__pycache__/archive.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/actions/__pycache__/delete.cpython-311.pyc b/maildir_gtd/actions/__pycache__/delete.cpython-311.pyc deleted file mode 100644 index 008834a..0000000 Binary files a/maildir_gtd/actions/__pycache__/delete.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/actions/__pycache__/newest.cpython-311.pyc b/maildir_gtd/actions/__pycache__/newest.cpython-311.pyc deleted file mode 100644 index 8777b5f..0000000 Binary files a/maildir_gtd/actions/__pycache__/newest.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/actions/__pycache__/next.cpython-311.pyc b/maildir_gtd/actions/__pycache__/next.cpython-311.pyc deleted file mode 100644 index 1a41548..0000000 Binary files a/maildir_gtd/actions/__pycache__/next.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/actions/__pycache__/oldest.cpython-311.pyc b/maildir_gtd/actions/__pycache__/oldest.cpython-311.pyc deleted file mode 100644 index 9db22c4..0000000 Binary files a/maildir_gtd/actions/__pycache__/oldest.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/actions/__pycache__/open.cpython-311.pyc b/maildir_gtd/actions/__pycache__/open.cpython-311.pyc deleted file mode 100644 index fe73ff7..0000000 Binary files a/maildir_gtd/actions/__pycache__/open.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/actions/__pycache__/previous.cpython-311.pyc b/maildir_gtd/actions/__pycache__/previous.cpython-311.pyc deleted file mode 100644 index a54f63e..0000000 Binary files a/maildir_gtd/actions/__pycache__/previous.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/actions/__pycache__/show_message.cpython-311.pyc b/maildir_gtd/actions/__pycache__/show_message.cpython-311.pyc deleted file mode 100644 index 302da93..0000000 Binary files a/maildir_gtd/actions/__pycache__/show_message.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/actions/__pycache__/task.cpython-311.pyc b/maildir_gtd/actions/__pycache__/task.cpython-311.pyc deleted file mode 100644 index 9e1623c..0000000 Binary files a/maildir_gtd/actions/__pycache__/task.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/screens/__init__.py b/maildir_gtd/screens/__init__.py deleted file mode 100644 index 7329037..0000000 --- a/maildir_gtd/screens/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# Initialize the screens package -from maildir_gtd.screens.CreateTask import CreateTaskScreen -from maildir_gtd.screens.OpenMessage import OpenMessageScreen -from maildir_gtd.screens.DocumentViewer import DocumentViewerScreen - -__all__ = ["CreateTaskScreen", "OpenMessageScreen", "DocumentViewerScreen"] diff --git a/maildir_gtd/screens/__pycache__/CreateTask.cpython-311.pyc b/maildir_gtd/screens/__pycache__/CreateTask.cpython-311.pyc deleted file mode 100644 index c9fed7c..0000000 Binary files a/maildir_gtd/screens/__pycache__/CreateTask.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/screens/__pycache__/OpenMessage.cpython-311.pyc b/maildir_gtd/screens/__pycache__/OpenMessage.cpython-311.pyc deleted file mode 100644 index aa3dbb7..0000000 Binary files a/maildir_gtd/screens/__pycache__/OpenMessage.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/screens/__pycache__/__init__.cpython-311.pyc b/maildir_gtd/screens/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index deaa918..0000000 Binary files a/maildir_gtd/screens/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/widgets/__pycache__/EnvelopeHeader.cpython-311.pyc b/maildir_gtd/widgets/__pycache__/EnvelopeHeader.cpython-311.pyc deleted file mode 100644 index e64d9db..0000000 Binary files a/maildir_gtd/widgets/__pycache__/EnvelopeHeader.cpython-311.pyc and /dev/null differ diff --git a/maildir_gtd/widgets/__pycache__/__init__.cpython-311.pyc b/maildir_gtd/widgets/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 814758d..0000000 Binary files a/maildir_gtd/widgets/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/main.py b/main.py index 05243d7..9063fcc 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,10 @@ -def main(): - print("Hello from gtd-terminal-tools!") +import sys +import os + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'src'))) + +from src.cli import cli if __name__ == "__main__": - main() + cli() diff --git a/pyproject.toml b/pyproject.toml index 28addc6..1e0dbb3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "gtd-terminal-tools" version = "0.1.0" description = "Add your description here" readme = "README.md" -requires-python = ">=3.13" +requires-python = ">=3.12" dependencies = [ "aiohttp>=3.11.18", "html2text>=2025.4.15", diff --git a/src/cli/__init__.py b/src/cli/__init__.py new file mode 100644 index 0000000..4cae046 --- /dev/null +++ b/src/cli/__init__.py @@ -0,0 +1,20 @@ +# CLI module for the application + +import click + +from .sync import sync +from .drive import drive +from .email import email +from .calendar import calendar + + +@click.group() +def cli(): + """Root command for the CLI.""" + pass + + +cli.add_command(sync) +cli.add_command(drive) +cli.add_command(email) +cli.add_command(calendar) diff --git a/src/cli/__main__.py b/src/cli/__main__.py new file mode 100644 index 0000000..7c4a768 --- /dev/null +++ b/src/cli/__main__.py @@ -0,0 +1,4 @@ +from . import cli + +if __name__ == "__main__": + cli() diff --git a/src/cli/calendar.py b/src/cli/calendar.py new file mode 100644 index 0000000..62e74d6 --- /dev/null +++ b/src/cli/calendar.py @@ -0,0 +1,8 @@ +import click +import subprocess + +@click.command() +def calendar(): + """Open the calendar (khal interactive).""" + click.echo("Opening calendar...") + subprocess.run(["khal", "interactive"]) diff --git a/src/cli/drive.py b/src/cli/drive.py new file mode 100644 index 0000000..a59c312 --- /dev/null +++ b/src/cli/drive.py @@ -0,0 +1,9 @@ +import click +import subprocess + + +@click.command() +def drive(): + """View OneDrive files.""" + click.echo("Launching OneDrive viewer...") + subprocess.run(["python3", "src/drive_view_tui.py"]) diff --git a/src/cli/email.py b/src/cli/email.py new file mode 100644 index 0000000..251c38b --- /dev/null +++ b/src/cli/email.py @@ -0,0 +1,9 @@ +import click +from src.maildir_gtd.app import launch_email_viewer + + +@click.command() +def email(): + """Read emails from Maildir.""" + click.echo("Opening email viewer...") + launch_email_viewer() diff --git a/src/cli/sync.py b/src/cli/sync.py new file mode 100644 index 0000000..c4556d7 --- /dev/null +++ b/src/cli/sync.py @@ -0,0 +1,283 @@ +import click +import asyncio +import os +import sys +from rich.progress import Progress, SpinnerColumn, MofNCompleteColumn +from datetime import datetime, timedelta + +from src.utils.mail_utils.helpers import ensure_directory_exists +from src.utils.calendar_utils import save_events_to_vdir, save_events_to_file +from src.services.microsoft_graph.calendar import fetch_calendar_events +from src.services.microsoft_graph.mail import ( + fetch_mail_async, + archive_mail_async, + delete_mail_async, + synchronize_maildir_async, +) +from src.services.microsoft_graph.auth import get_access_token + +# Function to create Maildir structure +def create_maildir_structure(base_path): + """ + Create the standard Maildir directory structure. + + Args: + base_path (str): Base path for the Maildir. + + Returns: + None + """ + ensure_directory_exists(os.path.join(base_path, "cur")) + ensure_directory_exists(os.path.join(base_path, "new")) + ensure_directory_exists(os.path.join(base_path, "tmp")) + ensure_directory_exists(os.path.join(base_path, ".Archives")) + ensure_directory_exists(os.path.join(base_path, ".Trash", "cur")) + + +async def fetch_calendar_async(headers, progress, task_id, dry_run, vdir_path, ics_path, org_name, days_back, days_forward, continue_iteration): + """ + Fetch calendar events and save them in the appropriate format. + + Args: + headers: Authentication headers for Microsoft Graph API + progress: Progress instance for updating progress bars + task_id: ID of the task in the progress bar + + Returns: + List of event dictionaries + + Raises: + Exception: If there's an error fetching or saving events + """ + try: + # Use the utility function to fetch calendar events + progress.console.print( + "[cyan]Fetching events from Microsoft Graph API...[/cyan]" + ) + events, total_events = await fetch_calendar_events( + headers=headers, days_back=days_back, days_forward=days_forward + ) + + progress.console.print( + f"[cyan]Got {len(events)} events from API (reported total: {total_events})[/cyan]" + ) + + # Update progress bar with total events + progress.update(task_id, total=total_events) + + # Save events to appropriate format + if not dry_run: + if vdir_path: + # Create org-specific directory within vdir path + org_vdir_path = os.path.join(vdir_path, org_name) + progress.console.print( + f"[cyan]Saving events to vdir: {org_vdir_path}[/cyan]" + ) + save_events_to_vdir(events, org_vdir_path, + progress, task_id, dry_run) + progress.console.print( + f"[green]Finished saving events to vdir: {org_vdir_path}[/green]" + ) + elif ics_path: + # Save to a single ICS file in the output_ics directory + progress.console.print( + f"[cyan]Saving events to ICS file: {ics_path}/events_latest.ics[/cyan]" + ) + save_events_to_file( + events, f"{ics_path}/events_latest.ics", progress, task_id, dry_run + ) + progress.console.print( + f"[green]Finished saving events to ICS file[/green]" + ) + else: + # No destination specified + progress.console.print( + "[yellow]Warning: No destination path (--vdir or --icsfile) specified for calendar events.[/yellow]" + ) + else: + progress.console.print( + f"[DRY-RUN] Would save {len(events)} events to { + 'vdir format' if vdir_path else 'single ICS file'}" + ) + progress.update(task_id, advance=len(events)) + + # Interactive mode: Ask if the user wants to continue with the next date range + if continue_iteration: + # Move to the next date range + next_start_date = datetime.now() - timedelta(days=days_back) + next_end_date = next_start_date + timedelta(days=days_forward) + + progress.console.print( + f"\nCurrent date range: {next_start_date.strftime( + '%Y-%m-%d')} to {next_end_date.strftime('%Y-%m-%d')}" + ) + + user_response = click.prompt( + "\nContinue to iterate? [y/N]", default="N").strip().lower() + + while user_response == "y": + progress.console.print( + f"\nFetching events for {next_start_date.strftime( + '%Y-%m-%d')} to {next_end_date.strftime('%Y-%m-%d')}..." + ) + + # Reset the progress bar for the new fetch + progress.update(task_id, completed=0, total=0) + + # Fetch events for the next date range + next_events, next_total_events = await fetch_calendar_events( + headers=headers, + days_back=0, + days_forward=days_forward, + start_date=next_start_date, + end_date=next_end_date, + ) + + # Update progress bar with total events + progress.update(task_id, total=next_total_events) + + if not dry_run: + if vdir_path: + save_events_to_vdir( + next_events, org_vdir_path, progress, task_id, dry_run + ) + else: + save_events_to_file( + next_events, + f"output_ics/outlook_events_{next_start_date.strftime('%Y%m%d')}.ics", + progress, + task_id, + dry_run, + ) + else: + progress.console.print( + f"[DRY-RUN] Would save {len(next_events)} events to { + 'vdir format' if vdir_path else 'output_ics/outlook_events_' + next_start_date.strftime('%Y%m%d') + '.ics'}" + ) + progress.update(task_id, advance=len(next_events)) + + # Calculate the next date range + next_start_date = next_end_date + next_end_date = next_start_date + timedelta(days=days_forward) + + progress.console.print( + f"\nNext date range would be: {next_start_date.strftime( + '%Y-%m-%d')} to {next_end_date.strftime('%Y-%m-%d')}" + ) + user_response = click.prompt( + "\nContinue to iterate? [y/N]", default="N").strip().lower() + + return events + except Exception as e: + progress.console.print( + f"[red]Error fetching or saving calendar events: {str(e)}[/red]" + ) + import traceback + + progress.console.print(f"[red]{traceback.format_exc()}[/red]") + progress.update(task_id, completed=True) + return [] + + +async def _sync_outlook_data(dry_run, vdir, icsfile, org, days_back, days_forward, continue_iteration, download_attachments): + """Synchronize data from external sources.""" + + # Save emails to Maildir + maildir_path = ( + os.getenv("MAILDIR_PATH", os.path.expanduser( + "~/Mail")) + f"/{org}" + ) + attachments_dir = os.path.join(maildir_path, "attachments") + ensure_directory_exists(attachments_dir) + create_maildir_structure(maildir_path) + + # Define scopes for Microsoft Graph API + scopes = [ + "https://graph.microsoft.com/Calendars.Read", + "https://graph.microsoft.com/Mail.ReadWrite", + ] + + # Authenticate and get access token + access_token, headers = get_access_token(scopes) + + # Set up the progress bars + progress = Progress( + SpinnerColumn(), MofNCompleteColumn(), *Progress.get_default_columns() + ) + + with progress: + task_fetch = progress.add_task("[green]Syncing Inbox...", total=0) + task_calendar = progress.add_task( + "[cyan]Fetching calendar...", total=0) + task_read = progress.add_task("[blue]Marking as read...", total=0) + task_archive = progress.add_task("[yellow]Archiving mail...", total=0) + task_delete = progress.add_task("[red]Deleting mail...", total=0) + + await asyncio.gather( + synchronize_maildir_async( + maildir_path, headers, progress, task_read, dry_run + ), + archive_mail_async(maildir_path, headers, + progress, task_archive, dry_run), + delete_mail_async(maildir_path, headers, + progress, task_delete, dry_run), + fetch_mail_async( + maildir_path, + attachments_dir, + headers, + progress, + task_fetch, + dry_run, + download_attachments, + ), + fetch_calendar_async(headers, progress, task_calendar, dry_run, vdir, icsfile, org, days_back, days_forward, continue_iteration), + ) + click.echo("Sync complete.") + + +@click.command() +@click.option( + "--dry-run", + is_flag=True, + help="Run in dry-run mode without making changes.", + default=False, +) +@click.option( + "--vdir", + help="Output calendar events in vdir format to the specified directory (each event in its own file)", + default="~/Calendar", +) +@click.option( + "--icsfile", help="Output calendar events into this ics file path.", default=None +) +@click.option( + "--org", + help="Specify the organization name for the subfolder to store emails and calendar events", + default="corteva", +) +@click.option( + "--days-back", + type=int, + help="Number of days to look back for calendar events", + default=1, +) +@click.option( + "--days-forward", + type=int, + help="Number of days to look forward for calendar events", + default=6, +) +@click.option( + "--continue-iteration", + is_flag=True, + help="Enable interactive mode to continue fetching more date ranges", + default=False, +) +@click.option( + "--download-attachments", + is_flag=True, + help="Download email attachments", + default=False, +) +def sync(dry_run, vdir, icsfile, org, days_back, days_forward, continue_iteration, download_attachments): + asyncio.run(_sync_outlook_data(dry_run, vdir, icsfile, org, days_back, days_forward, continue_iteration, download_attachments)) \ No newline at end of file diff --git a/maildir_gtd/__init__.py b/src/maildir_gtd/__init__.py similarity index 100% rename from maildir_gtd/__init__.py rename to src/maildir_gtd/__init__.py diff --git a/maildir_gtd/actions/__init__.py b/src/maildir_gtd/actions/__init__.py similarity index 100% rename from maildir_gtd/actions/__init__.py rename to src/maildir_gtd/actions/__init__.py diff --git a/maildir_gtd/actions/archive.py b/src/maildir_gtd/actions/archive.py similarity index 96% rename from maildir_gtd/actions/archive.py rename to src/maildir_gtd/actions/archive.py index 11d9475..d7927b6 100644 --- a/maildir_gtd/actions/archive.py +++ b/src/maildir_gtd/actions/archive.py @@ -2,7 +2,7 @@ import asyncio import logging from textual import work -from apis.himalaya import client as himalaya_client +from src.services.himalaya import client as himalaya_client @work(exclusive=True) diff --git a/maildir_gtd/actions/delete.py b/src/maildir_gtd/actions/delete.py similarity index 96% rename from maildir_gtd/actions/delete.py rename to src/maildir_gtd/actions/delete.py index cc59644..a2331a6 100644 --- a/maildir_gtd/actions/delete.py +++ b/src/maildir_gtd/actions/delete.py @@ -1,7 +1,7 @@ import asyncio import logging from textual import work -from apis.himalaya import client as himalaya_client +from src.services.himalaya import client as himalaya_client @work(exclusive=True) diff --git a/maildir_gtd/actions/newest.py b/src/maildir_gtd/actions/newest.py similarity index 100% rename from maildir_gtd/actions/newest.py rename to src/maildir_gtd/actions/newest.py diff --git a/maildir_gtd/actions/next.py b/src/maildir_gtd/actions/next.py similarity index 100% rename from maildir_gtd/actions/next.py rename to src/maildir_gtd/actions/next.py diff --git a/maildir_gtd/actions/oldest.py b/src/maildir_gtd/actions/oldest.py similarity index 100% rename from maildir_gtd/actions/oldest.py rename to src/maildir_gtd/actions/oldest.py diff --git a/maildir_gtd/actions/open.py b/src/maildir_gtd/actions/open.py similarity index 90% rename from maildir_gtd/actions/open.py rename to src/maildir_gtd/actions/open.py index 5b308cf..fbe3ad9 100644 --- a/maildir_gtd/actions/open.py +++ b/src/maildir_gtd/actions/open.py @@ -1,4 +1,4 @@ -from maildir_gtd.screens.OpenMessage import OpenMessageScreen +from ..screens.OpenMessage import OpenMessageScreen def action_open(app) -> None: diff --git a/maildir_gtd/actions/previous.py b/src/maildir_gtd/actions/previous.py similarity index 100% rename from maildir_gtd/actions/previous.py rename to src/maildir_gtd/actions/previous.py diff --git a/maildir_gtd/actions/show_message.py b/src/maildir_gtd/actions/show_message.py similarity index 100% rename from maildir_gtd/actions/show_message.py rename to src/maildir_gtd/actions/show_message.py diff --git a/maildir_gtd/actions/task.py b/src/maildir_gtd/actions/task.py similarity index 84% rename from maildir_gtd/actions/task.py rename to src/maildir_gtd/actions/task.py index 6839fbe..a90344b 100644 --- a/maildir_gtd/actions/task.py +++ b/src/maildir_gtd/actions/task.py @@ -2,13 +2,15 @@ import asyncio import logging from textual import work from textual.screen import ModalScreen -from apis.taskwarrior import client as taskwarrior_client -from maildir_gtd.screens.CreateTask import CreateTaskScreen +from src.services.taskwarrior import client as taskwarrior_client +from ..screens.CreateTask import CreateTaskScreen + class TaskAction: def __init__(self, app): self.app = app + def action_create_task(app): """Show the create task screen.""" @@ -25,8 +27,11 @@ def action_create_task(app): # Show the create task screen with the current message data app.push_screen(CreateTaskScreen(subject=subject, from_addr=from_addr)) + @work(exclusive=True) -async def create_task(subject, description=None, tags=None, project=None, due=None, priority=None): +async def create_task( + subject, description=None, tags=None, project=None, due=None, priority=None +): """ Create a task with the Taskwarrior API client. """ @@ -36,7 +41,7 @@ async def create_task(subject, description=None, tags=None, project=None, due=No tags=tags or [], project=project, due=due, - priority=priority + priority=priority, ) if success: diff --git a/maildir_gtd/app.py b/src/maildir_gtd/app.py similarity index 94% rename from maildir_gtd/app.py rename to src/maildir_gtd/app.py index 83a21e4..e6235bb 100644 --- a/maildir_gtd/app.py +++ b/src/maildir_gtd/app.py @@ -1,3 +1,22 @@ +from .message_store import MessageStore +from .widgets.ContentContainer import ContentContainer +from .widgets.EnvelopeHeader import EnvelopeHeader +from .actions.task import action_create_task +from .actions.open import action_open +from .actions.delete import delete_current +from .actions.archive import archive_current +from src.services.taskwarrior import client as taskwarrior_client +from src.services.himalaya import client as himalaya_client +from textual.containers import ScrollableContainer, Vertical, Horizontal +from textual.timer import Timer +from textual.binding import Binding +from textual.reactive import reactive, Reactive +from textual.widgets import Footer, Static, Label, Markdown, ListView, ListItem +from textual.screen import Screen +from textual.logging import TextualHandler +from textual.app import App, ComposeResult, SystemCommand, RenderResult +from textual.worker import Worker +from textual import work import re import sys import os @@ -10,36 +29,18 @@ from collections import defaultdict # Add the parent directory to the system path to resolve relative imports sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -from textual import work -from textual.worker import Worker -from textual.app import App, ComposeResult, SystemCommand, RenderResult -from textual.logging import TextualHandler -from textual.screen import Screen -from textual.widgets import Footer, Static, Label, Markdown, ListView, ListItem -from textual.reactive import reactive, Reactive -from textual.binding import Binding -from textual.timer import Timer -from textual.containers import ScrollableContainer, Vertical, Horizontal # Import our new API modules -from apis.himalaya import client as himalaya_client -from apis.taskwarrior import client as taskwarrior_client # Updated imports with correct relative paths -from maildir_gtd.actions.archive import archive_current -from maildir_gtd.actions.delete import delete_current -from maildir_gtd.actions.open import action_open -from maildir_gtd.actions.task import action_create_task -from maildir_gtd.widgets.EnvelopeHeader import EnvelopeHeader -from maildir_gtd.widgets.ContentContainer import ContentContainer -from maildir_gtd.message_store import MessageStore logging.basicConfig( level="NOTSET", handlers=[TextualHandler()], ) + class StatusTitle(Static): total_messages: Reactive[int] = reactive(0) current_message_index: Reactive[int] = reactive(0) @@ -142,7 +143,8 @@ class EmailViewerApp(App): self.title = "MaildirGTD" self.query_one("#main_content").border_title = self.status_title sort_indicator = "↑" if self.sort_order_ascending else "↓" - self.query_one("#envelopes_list").border_title = f"1️⃣ Emails {sort_indicator}" + self.query_one("#envelopes_list").border_title = f"1️⃣ Emails { + sort_indicator}" self.query_one("#accounts_list").border_title = "2️⃣ Accounts" self.query_one("#folders_list").border_title = "3️⃣ Folders" @@ -154,7 +156,7 @@ class EmailViewerApp(App): self.query_one("#envelopes_list").focus() self.action_oldest() - def compute_status_title(self) -> None: + def compute_status_title(self): return f"✉️ Message ID: {self.current_message_id} " def watch_status_title(self, old_status_title: str, new_status_title: str) -> None: @@ -163,7 +165,8 @@ class EmailViewerApp(App): def watch_sort_order_ascending(self, old_value: bool, new_value: bool) -> None: """Update the border title of the envelopes list when the sort order changes.""" sort_indicator = "↑" if new_value else "↓" - self.query_one("#envelopes_list").border_title = f"1️⃣ Emails {sort_indicator}" + self.query_one("#envelopes_list").border_title = f"1️⃣ Emails { + sort_indicator}" def watch_current_message_index(self, old_index: int, new_index: int) -> None: if new_index < 0: @@ -189,12 +192,14 @@ class EmailViewerApp(App): ) -> None: """Called when the current message ID changes.""" logging.info( - f"Current message ID changed from {old_message_id} to {new_message_id}" + f"Current message ID changed from { + old_message_id} to {new_message_id}" ) if new_message_id == old_message_id: return self.msg_worker.cancel() if self.msg_worker else None - logging.info(f"new_message_id: {new_message_id}, type: {type(new_message_id)}") + logging.info(f"new_message_id: {new_message_id}, type: { + type(new_message_id)}") content_container = self.query_one(ContentContainer) content_container.display_content(new_message_id) @@ -219,7 +224,8 @@ class EmailViewerApp(App): if list_view.index != metadata["index"]: list_view.index = metadata["index"] else: - logging.warning(f"Message ID {new_message_id} not found in metadata.") + logging.warning( + f"Message ID {new_message_id} not found in metadata.") def on_list_view_selected(self, event: ListView.Selected) -> None: """Called when an item in the list view is selected.""" @@ -375,7 +381,9 @@ class EmailViewerApp(App): if not self.current_message_index >= 0: return - next_id, next_idx = self.message_store.find_next_valid_id(self.current_message_index) + next_id, next_idx = self.message_store.find_next_valid_id( + self.current_message_index + ) if next_id is not None and next_idx is not None: self.current_message_id = next_id self.current_message_index = next_idx @@ -386,7 +394,9 @@ class EmailViewerApp(App): if not self.current_message_index >= 0: return - prev_id, prev_idx = self.message_store.find_prev_valid_id(self.current_message_index) + prev_id, prev_idx = self.message_store.find_prev_valid_id( + self.current_message_index + ) if prev_id is not None and prev_idx is not None: self.current_message_id = prev_id self.current_message_index = prev_idx @@ -452,3 +462,7 @@ class EmailViewerApp(App): if __name__ == "__main__": app = EmailViewerApp() app.run() + +def launch_email_viewer(): + app = EmailViewerApp() + app.run() diff --git a/maildir_gtd/email_viewer.tcss b/src/maildir_gtd/email_viewer.tcss similarity index 100% rename from maildir_gtd/email_viewer.tcss rename to src/maildir_gtd/email_viewer.tcss diff --git a/maildir_gtd/message_store.py b/src/maildir_gtd/message_store.py similarity index 92% rename from maildir_gtd/message_store.py rename to src/maildir_gtd/message_store.py index 9754a9a..6335287 100644 --- a/maildir_gtd/message_store.py +++ b/src/maildir_gtd/message_store.py @@ -1,7 +1,8 @@ import logging from typing import List, Dict, Any, Tuple, Optional from datetime import datetime, UTC -from apis.himalaya import client as himalaya_client +from src.services.himalaya import client as himalaya_client + class MessageStore: """Store and manage message envelopes""" @@ -11,7 +12,9 @@ class MessageStore: self.metadata_by_id: Dict[int, Dict[str, Any]] = {} self.total_messages = 0 - def load(self, envelopes: List[Dict[str, Any]], sort_ascending: bool = True) -> None: + def load( + self, envelopes: List[Dict[str, Any]], sort_ascending: bool = True + ) -> None: """Load envelopes from Himalaya client and process them""" if not envelopes: self.envelopes = [] @@ -76,7 +79,9 @@ class MessageStore: """Get metadata for a message by ID""" return self.metadata_by_id.get(message_id) - def find_next_valid_id(self, current_index: int) -> Tuple[Optional[int], Optional[int]]: + def find_next_valid_id( + self, current_index: int + ) -> Tuple[Optional[int], Optional[int]]: """Find the next valid message ID and its index""" if not self.envelopes or current_index >= len(self.envelopes) - 1: return None, None @@ -90,7 +95,9 @@ class MessageStore: return None, None - def find_prev_valid_id(self, current_index: int) -> Tuple[Optional[int], Optional[int]]: + def find_prev_valid_id( + self, current_index: int + ) -> Tuple[Optional[int], Optional[int]]: """Find the previous valid message ID and its index""" if not self.envelopes or current_index <= 0: return None, None diff --git a/maildir_gtd/screens/CreateTask.py b/src/maildir_gtd/screens/CreateTask.py similarity index 86% rename from maildir_gtd/screens/CreateTask.py rename to src/maildir_gtd/screens/CreateTask.py index 87ce968..aa2e8ab 100644 --- a/maildir_gtd/screens/CreateTask.py +++ b/src/maildir_gtd/screens/CreateTask.py @@ -3,7 +3,8 @@ from textual.screen import ModalScreen from textual.widgets import Input, Label, Button, ListView, ListItem from textual.containers import Vertical, Horizontal, Container from textual import on, work -from apis.taskwarrior import client as taskwarrior_client +from src.services.taskwarrior import client as taskwarrior_client + class CreateTaskScreen(ModalScreen): """Screen for creating a new task.""" @@ -20,7 +21,11 @@ class CreateTaskScreen(ModalScreen): Label("Create Task", id="create_task_title"), Horizontal( Label("Subject:"), - Input(placeholder="Task subject", value=self.subject, id="subject_input"), + Input( + placeholder="Task subject", + value=self.subject, + id="subject_input", + ), ), Horizontal( Label("Project:"), @@ -32,7 +37,10 @@ class CreateTaskScreen(ModalScreen): ), Horizontal( Label("Due:"), - Input(placeholder="Due date (e.g., today, tomorrow, fri)", id="due_input"), + Input( + placeholder="Due date (e.g., today, tomorrow, fri)", + id="due_input", + ), ), Horizontal( Label("Priority:"), @@ -78,7 +86,9 @@ class CreateTaskScreen(ModalScreen): self.dismiss() @work(exclusive=True) - async def create_task_worker(self, subject, tags=None, project=None, due=None, priority=None): + async def create_task_worker( + self, subject, tags=None, project=None, due=None, priority=None + ): """Worker to create a task using the Taskwarrior API client.""" if not subject: self.app.show_status("Task subject cannot be empty.", "error") @@ -95,7 +105,7 @@ class CreateTaskScreen(ModalScreen): tags=tags or [], project=project, due=due, - priority=priority + priority=priority, ) if success: diff --git a/maildir_gtd/screens/DocumentViewer.py b/src/maildir_gtd/screens/DocumentViewer.py similarity index 98% rename from maildir_gtd/screens/DocumentViewer.py rename to src/maildir_gtd/screens/DocumentViewer.py index fb5c977..66341a4 100644 --- a/maildir_gtd/screens/DocumentViewer.py +++ b/src/maildir_gtd/screens/DocumentViewer.py @@ -234,6 +234,7 @@ class DocumentViewerScreen(Screen): id="document_link", ), ), + Button("Toggle Mode", id="toggle_mode_button"), id="top_container", ), ScrollableContainer( @@ -466,16 +467,21 @@ class DocumentViewerScreen(Screen): markdown_widget = self.query_one("#markdown_content", Markdown) plaintext_widget = self.query_one("#plaintext_content", Label) image_widget = self.query_one("#image_content", Static) + toggle_button = self.query_one("#toggle_mode_button", Button) + if self.mode == DisplayMode.IMAGE: + toggle_button.label = "\U000f02e9" image_widget.remove_class("hidden") markdown_widget.add_class("hidden") plaintext_widget.add_class("hidden") elif self.mode == DisplayMode.MARKDOWN: + toggle_button.label = "Mode \U000f0354|\U000f09ed" markdown_widget.update(self.document_content) markdown_widget.remove_class("hidden") image_widget.add_class("hidden") plaintext_widget.add_class("hidden") else: + toggle_button.label = "Mode \U000f0f5b|\U000f021a" plaintext_widget.update(self.plain_text_content) plaintext_widget.remove_class("hidden") image_widget.add_class("hidden") @@ -541,7 +547,7 @@ class DocumentViewerScreen(Screen): else DisplayMode.TEXT ) self.update_content_display() - mode_name = self.mode.name.capitalize() + mode_name = str(self.mode).capitalize() self.notify(f"Switched to {mode_name} mode") async def action_export_and_open(self) -> None: diff --git a/maildir_gtd/screens/OpenMessage.py b/src/maildir_gtd/screens/OpenMessage.py similarity index 100% rename from maildir_gtd/screens/OpenMessage.py rename to src/maildir_gtd/screens/OpenMessage.py diff --git a/src/maildir_gtd/screens/__init__.py b/src/maildir_gtd/screens/__init__.py new file mode 100644 index 0000000..8aeb3fd --- /dev/null +++ b/src/maildir_gtd/screens/__init__.py @@ -0,0 +1,6 @@ +# Initialize the screens package +from .CreateTask import CreateTaskScreen +from .OpenMessage import OpenMessageScreen +from .DocumentViewer import DocumentViewerScreen + +__all__ = ["CreateTaskScreen", "OpenMessageScreen", "DocumentViewerScreen"] diff --git a/maildir_gtd/utils.py b/src/maildir_gtd/utils.py similarity index 100% rename from maildir_gtd/utils.py rename to src/maildir_gtd/utils.py diff --git a/maildir_gtd/widgets/ContentContainer.py b/src/maildir_gtd/widgets/ContentContainer.py similarity index 78% rename from maildir_gtd/widgets/ContentContainer.py rename to src/maildir_gtd/widgets/ContentContainer.py index 3e035fb..d8de1f1 100644 --- a/maildir_gtd/widgets/ContentContainer.py +++ b/src/maildir_gtd/widgets/ContentContainer.py @@ -1,13 +1,17 @@ -import asyncio +from markitdown import MarkItDown +from textual import work +from textual.containers import Vertical, ScrollableContainer +from textual.widgets import Static, Markdown, Label +from src.services.himalaya import client as himalaya_client import logging from datetime import datetime import re -from textual.widgets import Static, Markdown, Label -from textual.containers import Vertical, Horizontal, ScrollableContainer -from textual import work -from textual.worker import Worker -from apis.himalaya import client as himalaya_client -from markitdown import MarkItDown +import os +import sys + +# Add the parent directory to the system path to resolve relative imports +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + class EnvelopeHeader(Vertical): def __init__(self, **kwargs): @@ -35,7 +39,7 @@ class EnvelopeHeader(Vertical): if date: try: # Try to convert the date string to a datetime object - date_obj = datetime.fromisoformat(date.replace('Z', '+00:00')) + date_obj = datetime.fromisoformat(date.replace("Z", "+00:00")) formatted_date = date_obj.strftime("%a, %d %b %Y %H:%M:%S %Z") self.date_label.update(f"[b]Date:[/b] {formatted_date}") except (ValueError, TypeError): @@ -50,12 +54,14 @@ class EnvelopeHeader(Vertical): else: self.cc_label.styles.display = "none" + class ContentContainer(ScrollableContainer): can_focus = True + def __init__(self, **kwargs): super().__init__(**kwargs) self.md = MarkItDown() - # self.header = EnvelopeHeader(id="envelope_header") + self.header = EnvelopeHeader(id="envelope_header") self.content = Markdown("", id="markdown_content") self.html_content = Static("", id="html_content", markup=False) self.current_mode = "text" # Default to text mode @@ -67,8 +73,6 @@ class ContentContainer(ScrollableContainer): yield self.content yield self.html_content - - def on_mount(self): # Hide markdown content initially self.content.styles.display = "none" @@ -89,8 +93,8 @@ class ContentContainer(ScrollableContainer): if self.current_message_id: self.display_content(self.current_message_id) - # def update_header(self, subject, from_, to, date, cc=None): - # self.header.update(subject, from_, to, date, cc) + def update_header(self, subject, from_, to, date, cc=None): + self.header.update(subject, from_, to, date, cc) @work(exclusive=True) async def fetch_message_content(self, message_id: int, format: str): @@ -103,8 +107,8 @@ class ContentContainer(ScrollableContainer): if success: self._update_content(content) else: - self.notify(f"Failed to fetch content for message ID {message_id}.") - + self.notify( + f"Failed to fetch content for message ID {message_id}.") def display_content(self, message_id: int) -> None: """Display the content of a message.""" @@ -119,29 +123,33 @@ class ContentContainer(ScrollableContainer): # Fetch content in the current mode format_type = "text" if self.current_mode == "text" else "html" - self.content_worker = self.fetch_message_content(message_id, format_type) + self.content_worker = self.fetch_message_content( + message_id, format_type) - def _update_content(self, content: str) -> None: + def _update_content(self, content: str | None) -> None: """Update the content widgets with the fetched content.""" try: if self.current_mode == "text": # For text mode, use the Markdown widget - self.content.update(content) else: # For HTML mode, use the Static widget with markup # First, try to extract the body content if it's HTML - body_match = re.search(r'
]*>(.*?)', content, re.DOTALL | re.IGNORECASE) + body_match = re.search( + r"]*>(.*?)", content, re.DOTALL | re.IGNORECASE + ) if body_match: content = body_match.group(1) # Replace some common HTML elements with Textual markup - content = content.replace('', '[b]').replace('', '[/b]') - content = content.replace('', '[i]').replace('', '[/i]') - content = content.replace('', '[u]').replace('', '[/u]') + content = content.replace("", "[b]").replace("", "[/b]") + content = content.replace("", "[i]").replace("", "[/i]") + content = content.replace("", "[u]").replace("", "[/u]") # Convert links to a readable format - content = re.sub(r']*>([^<]+)', r'[\2](\1)', content) + content = re.sub( + r']*>([^<]+)', r"[\2](\1)", content + ) # Add CSS for better readability self.html_content.update(content) @@ -152,5 +160,3 @@ class ContentContainer(ScrollableContainer): self.content.update(f"Error displaying content: {e}") else: self.html_content.update(f"Error displaying content: {e}") - - diff --git a/maildir_gtd/widgets/EnvelopeHeader.py b/src/maildir_gtd/widgets/EnvelopeHeader.py similarity index 72% rename from maildir_gtd/widgets/EnvelopeHeader.py rename to src/maildir_gtd/widgets/EnvelopeHeader.py index 2d5049b..42d5594 100644 --- a/maildir_gtd/widgets/EnvelopeHeader.py +++ b/src/maildir_gtd/widgets/EnvelopeHeader.py @@ -23,7 +23,8 @@ class EnvelopeHeader(ScrollableContainer): def compose(self) -> ComposeResult: yield Horizontal( Label("Subject:", classes="header_key"), - Label(self.subject, classes="header_value", markup=False, id="subject"), + Label(self.subject, classes="header_value", + markup=False, id="subject"), ) yield Horizontal( Label("Date:", classes="header_key"), @@ -31,23 +32,26 @@ class EnvelopeHeader(ScrollableContainer): ) # yield Horizontal( # Label("From:", classes="header_key"), - # Label(self.from_, classes="header_value", markup=False, id="from"), + # Label(self.from_, + # classes="header_value", markup=False, id="from"), # ) # yield Horizontal( # Label("To:", classes="header_key"), - # Label(self.to, classes="header_value", markup=False, id="to"), + # Label(self.to, classes="header_value", + # markup=False, id="to"), # ) # yield Horizontal( # ) # yield Horizontal( # Label("CC:", classes="header_key"), - # Label(self.cc, classes="header_value", markup=False, id="cc"), + # Label(self.cc, classes="header_value", + # markup=False, id="cc"), # ) def watch_subject(self, subject: str) -> None: """Watch the subject for changes.""" - self.query_one("#subject").update(subject) + self.query_one("#subject", Label).update(subject) # def watch_to(self, to: str) -> None: # """Watch the to field for changes.""" @@ -67,19 +71,23 @@ class EnvelopeHeader(ScrollableContainer): try: # Handle ISO format with Z suffix if 'Z' in date: - parsed_date = datetime.fromisoformat(date.replace('Z', '+00:00')) + parsed_date = datetime.fromisoformat( + date.replace('Z', '+00:00')) else: parsed_date = datetime.fromisoformat(date) except ValueError: # Try another common format - parsed_date = datetime.strptime(date, "%Y-%m-%d %H:%M%z") + parsed_date = datetime.strptime( + date, "%Y-%m-%d %H:%M%z") else: # No timezone info, assume UTC try: - parsed_date = datetime.strptime(date, "%Y-%m-%d %H:%M").replace(tzinfo=UTC) + parsed_date = datetime.strptime( + date, "%Y-%m-%d %H:%M").replace(tzinfo=UTC) except ValueError: - # If regular parsing fails, try to extract date components - match = re.search(r"(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2})", date) + # If regular parsing fails, try to extract date cmpnts + match = re.search( + r"(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2})", date) if match: date_part, time_part = match.groups() parsed_date = datetime.strptime( @@ -87,20 +95,20 @@ class EnvelopeHeader(ScrollableContainer): ).replace(tzinfo=UTC) else: # If all else fails, just use the original string - self.query_one("#date").update(date) + self.query_one("#date", Label).update(date) return # Convert to local timezone - local_date = parsed_date.astimezone() # Convert to system's local timezone + local_date = parsed_date.astimezone() # Format for display formatted_date = local_date.strftime("%a %b %d %H:%M (%Z)") - self.query_one("#date").update(formatted_date) - except Exception as e: + self.query_one("#date", Label).update(formatted_date) + except Exception: # If parsing fails, just display the original date - self.query_one("#date").update(f"{date}") + self.query_one("#date", Label).update(f"{date}") else: - self.query_one("#date").update("") + self.query_one("#date", Label).update("") # def watch_cc(self, cc: str) -> None: # """Watch the cc field for changes.""" diff --git a/maildir_gtd/widgets/__init__.py b/src/maildir_gtd/widgets/__init__.py similarity index 100% rename from maildir_gtd/widgets/__init__.py rename to src/maildir_gtd/widgets/__init__.py diff --git a/apis/__init__.py b/src/services/__init__.py similarity index 100% rename from apis/__init__.py rename to src/services/__init__.py diff --git a/apis/himalaya/__init__.py b/src/services/himalaya/__init__.py similarity index 90% rename from apis/himalaya/__init__.py rename to src/services/himalaya/__init__.py index 734294f..63f7053 100644 --- a/apis/himalaya/__init__.py +++ b/src/services/himalaya/__init__.py @@ -2,7 +2,7 @@ Himalaya API module for interacting with the Himalaya email client. """ -from apis.himalaya.client import ( +from .client import ( list_envelopes, list_accounts, list_folders, diff --git a/apis/himalaya/client.py b/src/services/himalaya/client.py similarity index 91% rename from apis/himalaya/client.py rename to src/services/himalaya/client.py index a87759a..c03166f 100644 --- a/apis/himalaya/client.py +++ b/src/services/himalaya/client.py @@ -1,7 +1,9 @@ +from typing import Tuple, List, Dict, Any, Optional import asyncio import json import logging -from typing import Tuple, List, Dict, Any, Optional, Union +import subprocess + async def list_envelopes(limit: int = 9999) -> Tuple[List[Dict[str, Any]], bool]: """ @@ -33,6 +35,7 @@ async def list_envelopes(limit: int = 9999) -> Tuple[List[Dict[str, Any]], bool] logging.error(f"Exception during envelope listing: {e}") return [], False + async def list_accounts() -> Tuple[List[Dict[str, Any]], bool]: """ Retrieve a list of accounts configured in Himalaya. @@ -60,6 +63,7 @@ async def list_accounts() -> Tuple[List[Dict[str, Any]], bool]: logging.error(f"Exception during account listing: {e}") return [], False + async def list_folders() -> Tuple[List[Dict[str, Any]], bool]: """ Retrieve a list of folders available in Himalaya. @@ -87,6 +91,7 @@ async def list_folders() -> Tuple[List[Dict[str, Any]], bool]: logging.error(f"Exception during folder listing: {e}") return [], False + async def delete_message(message_id: int) -> bool: """ Delete a message by its ID. @@ -110,6 +115,7 @@ async def delete_message(message_id: int) -> bool: logging.error(f"Exception during message deletion: {e}") return False + async def archive_message(message_id: int) -> bool: """ Archive a message by its ID. @@ -133,6 +139,7 @@ async def archive_message(message_id: int) -> bool: logging.error(f"Exception during message archiving: {e}") return False + async def get_message_content(message_id: int) -> Tuple[Optional[str], bool]: """ Retrieve the content of a message by its ID. @@ -149,7 +156,6 @@ async def get_message_content(message_id: int) -> Tuple[Optional[str], bool]: try: cmd = f"himalaya message read {message_id}" - process = await asyncio.create_subprocess_shell( cmd, stdout=asyncio.subprocess.PIPE, @@ -161,8 +167,18 @@ async def get_message_content(message_id: int) -> Tuple[Optional[str], bool]: content = stdout.decode() return content, True else: - logging.error(f"Error retrieving message content: {stderr.decode()}") + logging.error(f"Error retrieving message content: { + stderr.decode()}") return None, False except Exception as e: logging.error(f"Exception during message content retrieval: {e}") return None, False + + +def sync_himalaya(): + """Synchronize data using Himalaya.""" + try: + # subprocess.run(["himalaya", "sync"], check=True) + print("Himalaya sync completed successfully.") + except subprocess.CalledProcessError as e: + print(f"Error during Himalaya sync: {e}") diff --git a/apis/microsoft_graph/__init__.py b/src/services/microsoft_graph/__init__.py similarity index 100% rename from apis/microsoft_graph/__init__.py rename to src/services/microsoft_graph/__init__.py diff --git a/apis/microsoft_graph/auth.py b/src/services/microsoft_graph/auth.py similarity index 93% rename from apis/microsoft_graph/auth.py rename to src/services/microsoft_graph/auth.py index 9e304ef..5afc8e3 100644 --- a/apis/microsoft_graph/auth.py +++ b/src/services/microsoft_graph/auth.py @@ -3,6 +3,12 @@ Authentication module for Microsoft Graph API. """ import os import msal +from rich import print +from rich.panel import Panel + +def ensure_directory_exists(path): + if not os.path.exists(path): + os.makedirs(path) def get_access_token(scopes): """ @@ -45,8 +51,6 @@ def get_access_token(scopes): if 'user_code' not in flow: raise Exception("Failed to create device flow") - from rich import print - from rich.panel import Panel print(Panel(flow['message'], border_style="magenta", padding=2, title="MSAL Login Flow Link")) token_response = app.acquire_token_by_device_flow(flow) diff --git a/apis/microsoft_graph/calendar.py b/src/services/microsoft_graph/calendar.py similarity index 64% rename from apis/microsoft_graph/calendar.py rename to src/services/microsoft_graph/calendar.py index 6b91830..ca92db3 100644 --- a/apis/microsoft_graph/calendar.py +++ b/src/services/microsoft_graph/calendar.py @@ -1,12 +1,16 @@ """ Calendar operations for Microsoft Graph API. """ + import os from datetime import datetime, timedelta -from apis.microsoft_graph.client import fetch_with_aiohttp +from .client import fetch_with_aiohttp -async def fetch_calendar_events(headers, days_back=1, days_forward=6, start_date=None, end_date=None): + +async def fetch_calendar_events( + headers, days_back=1, days_forward=6, start_date=None, end_date=None +): """ Fetch calendar events from Microsoft Graph API. @@ -29,28 +33,28 @@ async def fetch_calendar_events(headers, days_back=1, days_forward=6, start_date end_date = start_date + timedelta(days=days_forward) # Format dates for API - start_date_str = start_date.strftime('%Y-%m-%dT00:00:00Z') - end_date_str = end_date.strftime('%Y-%m-%dT23:59:59Z') + start_date_str = start_date.strftime("%Y-%m-%dT00:00:00Z") + end_date_str = end_date.strftime("%Y-%m-%dT23:59:59Z") # Prepare the API query calendar_url = ( - f'https://graph.microsoft.com/v1.0/me/calendarView?' - f'startDateTime={start_date_str}&endDateTime={end_date_str}&' - f'$select=id,subject,organizer,start,end,location,isAllDay,showAs,sensitivity' + f"https://graph.microsoft.com/v1.0/me/calendarView?" + f"startDateTime={start_date_str}&endDateTime={end_date_str}&" + f"$select=id,subject,organizer,start,end,location,isAllDay,showAs,sensitivity" ) events = [] # Make the API request response_data = await fetch_with_aiohttp(calendar_url, headers) - events.extend(response_data.get('value', [])) + events.extend(response_data.get("value", [])) # Check if there are more events (pagination) - next_link = response_data.get('@odata.nextLink') + next_link = response_data.get("@odata.nextLink") while next_link: response_data = await fetch_with_aiohttp(next_link, headers) - events.extend(response_data.get('value', [])) - next_link = response_data.get('@odata.nextLink') + events.extend(response_data.get("value", [])) + next_link = response_data.get("@odata.nextLink") # Return events and total count return events, len(events) diff --git a/apis/microsoft_graph/client.py b/src/services/microsoft_graph/client.py similarity index 100% rename from apis/microsoft_graph/client.py rename to src/services/microsoft_graph/client.py diff --git a/apis/microsoft_graph/mail.py b/src/services/microsoft_graph/mail.py similarity index 57% rename from apis/microsoft_graph/mail.py rename to src/services/microsoft_graph/mail.py index 0463d7b..8fdf3dd 100644 --- a/apis/microsoft_graph/mail.py +++ b/src/services/microsoft_graph/mail.py @@ -1,15 +1,30 @@ """ Mail operations for Microsoft Graph API. """ + import os import re import glob from typing import Set import aiohttp -from apis.microsoft_graph.client import fetch_with_aiohttp, patch_with_aiohttp, post_with_aiohttp, delete_with_aiohttp +from .client import ( + fetch_with_aiohttp, + patch_with_aiohttp, + post_with_aiohttp, + delete_with_aiohttp, +) -async def fetch_mail_async(maildir_path, attachments_dir, headers, progress, task_id, dry_run=False, download_attachments=False): + +async def fetch_mail_async( + maildir_path, + attachments_dir, + headers, + progress, + task_id, + dry_run=False, + download_attachments=False, +): """ Fetch mail from Microsoft Graph API and save to Maildir. @@ -25,18 +40,18 @@ async def fetch_mail_async(maildir_path, attachments_dir, headers, progress, tas Returns: None """ - from utils.mail_utils.maildir import save_mime_to_maildir_async + from src.utils.mail_utils.maildir import save_mime_to_maildir_async from utils.mail_utils.helpers import truncate_id - mail_url = 'https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages?$top=100&$orderby=receivedDateTime asc&$select=id,subject,from,toRecipients,ccRecipients,receivedDateTime,isRead' + mail_url = "https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages?$top=100&$orderby=receivedDateTime asc&$select=id,subject,from,toRecipients,ccRecipients,receivedDateTime,isRead" messages = [] # Fetch the total count of messages in the inbox - inbox_url = 'https://graph.microsoft.com/v1.0/me/mailFolders/inbox' + inbox_url = "https://graph.microsoft.com/v1.0/me/mailFolders/inbox" response = await fetch_with_aiohttp(inbox_url, headers) - total_messages = response.get('totalItemCount', 0) + total_messages = response.get("totalItemCount", 0) progress.update(task_id, total=total_messages) while mail_url: @@ -45,22 +60,24 @@ async def fetch_mail_async(maildir_path, attachments_dir, headers, progress, tas except Exception as e: progress.console.print(f"Error fetching messages: {e}") continue - messages.extend(response_data.get('value', [])) - progress.advance(task_id, len(response_data.get('value', []))) + messages.extend(response_data.get("value", [])) + progress.advance(task_id, len(response_data.get("value", []))) # Get the next page URL from @odata.nextLink - mail_url = response_data.get('@odata.nextLink') + mail_url = response_data.get("@odata.nextLink") - inbox_msg_ids = set(message['id'] for message in messages) + inbox_msg_ids = set(message["id"] for message in messages) progress.update(task_id, completed=(len(messages) / 2)) - new_dir = os.path.join(maildir_path, 'new') - cur_dir = os.path.join(maildir_path, 'cur') - new_files = set(glob.glob(os.path.join(new_dir, '*.eml*'))) - cur_files = set(glob.glob(os.path.join(cur_dir, '*.eml*'))) + new_dir = os.path.join(maildir_path, "new") + cur_dir = os.path.join(maildir_path, "cur") + new_files = set(glob.glob(os.path.join(new_dir, "*.eml*"))) + cur_files = set(glob.glob(os.path.join(cur_dir, "*.eml*"))) for filename in Set.union(cur_files, new_files): - message_id = filename.split('.')[0].split('/')[-1] # Extract the Message-ID from the filename - if (message_id not in inbox_msg_ids): + message_id = filename.split(".")[0].split("/")[ + -1 + ] # Extract the Message-ID from the filename + if message_id not in inbox_msg_ids: if not dry_run: progress.console.print(f"Deleting {filename} from inbox") os.remove(filename) @@ -68,12 +85,23 @@ async def fetch_mail_async(maildir_path, attachments_dir, headers, progress, tas progress.console.print(f"[DRY-RUN] Would delete {filename} from inbox") for message in messages: - progress.console.print(f"Processing message: {message.get('subject', 'No Subject')}", end='\r') - await save_mime_to_maildir_async(maildir_path, message, attachments_dir, headers, progress, dry_run, download_attachments) + progress.console.print( + f"Processing message: {message.get('subject', 'No Subject')}", end="\r" + ) + await save_mime_to_maildir_async( + maildir_path, + message, + attachments_dir, + headers, + progress, + dry_run, + download_attachments, + ) progress.update(task_id, advance=0.5) progress.update(task_id, completed=len(messages)) progress.console.print(f"\nFinished saving {len(messages)} messages.") + async def archive_mail_async(maildir_path, headers, progress, task_id, dry_run=False): """ Archive mail from Maildir to Microsoft Graph API archive folder. @@ -88,38 +116,56 @@ async def archive_mail_async(maildir_path, headers, progress, task_id, dry_run=F Returns: None """ - archive_dir = os.path.join(maildir_path, '.Archives') - archive_files = glob.glob(os.path.join(archive_dir, '**', '*.eml*'), recursive=True) + archive_dir = os.path.join(maildir_path, ".Archives") + archive_files = glob.glob(os.path.join(archive_dir, "**", "*.eml*"), recursive=True) progress.update(task_id, total=len(archive_files)) - folder_response = await fetch_with_aiohttp('https://graph.microsoft.com/v1.0/me/mailFolders', headers) - folders = folder_response.get('value', []) - archive_folder_id = next((folder.get('id') for folder in folders if folder.get('displayName', '').lower() == 'archive'), None) + folder_response = await fetch_with_aiohttp( + "https://graph.microsoft.com/v1.0/me/mailFolders", headers + ) + folders = folder_response.get("value", []) + archive_folder_id = next( + ( + folder.get("id") + for folder in folders + if folder.get("displayName", "").lower() == "archive" + ), + None, + ) if not archive_folder_id: raise Exception("No folder named 'Archive' found on the server.") for filepath in archive_files: - message_id = os.path.basename(filepath).split('.')[0] # Extract the Message-ID from the filename + message_id = os.path.basename(filepath).split(".")[ + 0 + ] # Extract the Message-ID from the filename if not dry_run: status = await post_with_aiohttp( - f'https://graph.microsoft.com/v1.0/me/messages/{message_id}/microsoft.graph.move', + f"https://graph.microsoft.com/v1.0/me/messages/{message_id}/microsoft.graph.move", headers, - {'destinationId': archive_folder_id} + {"destinationId": archive_folder_id}, ) if status != 201: # 201 Created indicates success - progress.console.print(f"Failed to move message to 'Archive': {message_id}, {status}") + progress.console.print( + f"Failed to move message to 'Archive': {message_id}, {status}" + ) if status == 404: os.remove(filepath) # Remove the file from local archive if not found - progress.console.print(f"Message not found on server, removed local copy: {message_id}") + progress.console.print( + f"Message not found on server, removed local copy: {message_id}" + ) elif status == 204: progress.console.print(f"Moved message to 'Archive': {message_id}") else: - progress.console.print(f"[DRY-RUN] Would move message to 'Archive' folder: {message_id}") + progress.console.print( + f"[DRY-RUN] Would move message to 'Archive' folder: {message_id}" + ) progress.advance(task_id) return + async def delete_mail_async(maildir_path, headers, progress, task_id, dry_run=False): """ Delete mail from Maildir and Microsoft Graph API. @@ -134,17 +180,18 @@ async def delete_mail_async(maildir_path, headers, progress, task_id, dry_run=Fa Returns: None """ - trash_dir = os.path.join(maildir_path, '.Trash', 'cur') - trash_files = set(glob.glob(os.path.join(trash_dir, '*.eml*'))) + trash_dir = os.path.join(maildir_path, ".Trash", "cur") + trash_files = set(glob.glob(os.path.join(trash_dir, "*.eml*"))) progress.update(task_id, total=len(trash_files)) for filepath in trash_files: - message_id = os.path.basename(filepath).split('.')[0] # Extract the Message-ID from the filename + message_id = os.path.basename(filepath).split(".")[ + 0 + ] # Extract the Message-ID from the filename if not dry_run: progress.console.print(f"Moving message to trash: {message_id}") status = await delete_with_aiohttp( - f'https://graph.microsoft.com/v1.0/me/messages/{message_id}', - headers + f"https://graph.microsoft.com/v1.0/me/messages/{message_id}", headers ) if status == 204 or status == 404: os.remove(filepath) # Remove the file from local trash @@ -152,7 +199,10 @@ async def delete_mail_async(maildir_path, headers, progress, task_id, dry_run=Fa progress.console.print(f"[DRY-RUN] Would delete message: {message_id}") progress.advance(task_id) -async def synchronize_maildir_async(maildir_path, headers, progress, task_id, dry_run=False): + +async def synchronize_maildir_async( + maildir_path, headers, progress, task_id, dry_run=False +): """ Synchronize Maildir with Microsoft Graph API. @@ -166,15 +216,19 @@ async def synchronize_maildir_async(maildir_path, headers, progress, task_id, Returns: None """ - from utils.mail_utils.helpers import load_last_sync_timestamp, save_sync_timestamp, truncate_id + from src.utils.mail_utils.helpers import ( + load_last_sync_timestamp, + save_sync_timestamp, + truncate_id, +) last_sync = load_last_sync_timestamp() # Find messages moved from "new" to "cur" and mark them as read - new_dir = os.path.join(maildir_path, 'new') - cur_dir = os.path.join(maildir_path, 'cur') - new_files = set(glob.glob(os.path.join(new_dir, '*.eml*'))) - cur_files = set(glob.glob(os.path.join(cur_dir, '*.eml*'))) + new_dir = os.path.join(maildir_path, "new") + cur_dir = os.path.join(maildir_path, "cur") + new_files = set(glob.glob(os.path.join(new_dir, "*.eml*"))) + cur_files = set(glob.glob(os.path.join(cur_dir, "*.eml*"))) moved_to_cur = [os.path.basename(f) for f in cur_files - new_files] progress.update(task_id, total=len(moved_to_cur)) @@ -183,18 +237,22 @@ async def synchronize_maildir_async(maildir_path, headers, progress, task_id, if os.path.getmtime(os.path.join(cur_dir, filename)) < last_sync: progress.update(task_id, advance=1) continue - message_id = re.sub(r"\:2.+", "", filename.split('.')[0]) # Extract the Message-ID from the filename + message_id = re.sub( + r"\:2.+", "", filename.split(".")[0] + ) # Extract the Message-ID from the filename if not dry_run: status = await patch_with_aiohttp( - f'https://graph.microsoft.com/v1.0/me/messages/{message_id}', + f"https://graph.microsoft.com/v1.0/me/messages/{message_id}", headers, - {'isRead': True} + {"isRead": True}, ) if status == 404: os.remove(os.path.join(cur_dir, filename)) else: - progress.console.print(f"[DRY-RUN] Would mark message as read: {truncate_id(message_id)}") + progress.console.print( + f"[DRY-RUN] Would mark message as read: {truncate_id(message_id)}" + ) progress.advance(task_id) # Save the current sync timestamp diff --git a/apis/taskwarrior/__init__.py b/src/services/taskwarrior/__init__.py similarity index 87% rename from apis/taskwarrior/__init__.py rename to src/services/taskwarrior/__init__.py index 4d21a33..b3bff70 100644 --- a/apis/taskwarrior/__init__.py +++ b/src/services/taskwarrior/__init__.py @@ -2,7 +2,7 @@ Taskwarrior API module for interacting with the Taskwarrior command-line task manager. """ -from apis.taskwarrior.client import ( +from .client import ( create_task, list_tasks, complete_task, diff --git a/apis/taskwarrior/client.py b/src/services/taskwarrior/client.py similarity index 100% rename from apis/taskwarrior/client.py rename to src/services/taskwarrior/client.py diff --git a/utils/calendar_utils.py b/src/utils/calendar_utils.py similarity index 100% rename from utils/calendar_utils.py rename to src/utils/calendar_utils.py diff --git a/utils/file_icons.py b/src/utils/file_icons.py similarity index 100% rename from utils/file_icons.py rename to src/utils/file_icons.py diff --git a/utils/mail_utils/__init__.py b/src/utils/mail_utils/__init__.py similarity index 100% rename from utils/mail_utils/__init__.py rename to src/utils/mail_utils/__init__.py diff --git a/utils/mail_utils/helpers.py b/src/utils/mail_utils/helpers.py similarity index 100% rename from utils/mail_utils/helpers.py rename to src/utils/mail_utils/helpers.py diff --git a/utils/mail_utils/maildir.py b/src/utils/mail_utils/maildir.py similarity index 99% rename from utils/mail_utils/maildir.py rename to src/utils/mail_utils/maildir.py index 435b464..59fa04d 100644 --- a/utils/mail_utils/maildir.py +++ b/src/utils/mail_utils/maildir.py @@ -12,7 +12,7 @@ import time import aiohttp import re -from utils.calendar_utils import truncate_id +from src.utils.calendar_utils import truncate_id from utils.mail_utils.helpers import safe_filename, ensure_directory_exists, format_datetime, format_mime_date async def save_mime_to_maildir_async(maildir_path, message, attachments_dir, headers, progress, dry_run=False, download_attachments=False): diff --git a/uv.lock b/uv.lock index f5bd60e..7966cfe 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,10 @@ version = 1 revision = 2 -requires-python = ">=3.13" +requires-python = ">=3.12" +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version < '3.13'", +] [[package]] name = "aiohappyeyeballs" @@ -26,6 +30,22 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/63/e7/fa1a8c00e2c54b05dc8cb5d1439f627f7c267874e3f7bb047146116020f9/aiohttp-3.11.18.tar.gz", hash = "sha256:ae856e1138612b7e412db63b7708735cff4d38d0399f6a5435d3dac2669f558a", size = 7678653, upload-time = "2025-04-21T09:43:09.191Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/d2/5bc436f42bf4745c55f33e1e6a2d69e77075d3e768e3d1a34f96ee5298aa/aiohttp-3.11.18-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:63d71eceb9cad35d47d71f78edac41fcd01ff10cacaa64e473d1aec13fa02df2", size = 706671, upload-time = "2025-04-21T09:41:28.021Z" }, + { url = "https://files.pythonhosted.org/packages/fe/d0/2dbabecc4e078c0474abb40536bbde717fb2e39962f41c5fc7a216b18ea7/aiohttp-3.11.18-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d1929da615840969929e8878d7951b31afe0bac883d84418f92e5755d7b49508", size = 466169, upload-time = "2025-04-21T09:41:29.783Z" }, + { url = "https://files.pythonhosted.org/packages/70/84/19edcf0b22933932faa6e0be0d933a27bd173da02dc125b7354dff4d8da4/aiohttp-3.11.18-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d0aebeb2392f19b184e3fdd9e651b0e39cd0f195cdb93328bd124a1d455cd0e", size = 457554, upload-time = "2025-04-21T09:41:31.327Z" }, + { url = "https://files.pythonhosted.org/packages/32/d0/e8d1f034ae5624a0f21e4fb3feff79342ce631f3a4d26bd3e58b31ef033b/aiohttp-3.11.18-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3849ead845e8444f7331c284132ab314b4dac43bfae1e3cf350906d4fff4620f", size = 1690154, upload-time = "2025-04-21T09:41:33.541Z" }, + { url = "https://files.pythonhosted.org/packages/16/de/2f9dbe2ac6f38f8495562077131888e0d2897e3798a0ff3adda766b04a34/aiohttp-3.11.18-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5e8452ad6b2863709f8b3d615955aa0807bc093c34b8e25b3b52097fe421cb7f", size = 1733402, upload-time = "2025-04-21T09:41:35.634Z" }, + { url = "https://files.pythonhosted.org/packages/e0/04/bd2870e1e9aef990d14b6df2a695f17807baf5c85a4c187a492bda569571/aiohttp-3.11.18-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b8d2b42073611c860a37f718b3d61ae8b4c2b124b2e776e2c10619d920350ec", size = 1783958, upload-time = "2025-04-21T09:41:37.456Z" }, + { url = "https://files.pythonhosted.org/packages/23/06/4203ffa2beb5bedb07f0da0f79b7d9039d1c33f522e0d1a2d5b6218e6f2e/aiohttp-3.11.18-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40fbf91f6a0ac317c0a07eb328a1384941872f6761f2e6f7208b63c4cc0a7ff6", size = 1695288, upload-time = "2025-04-21T09:41:39.756Z" }, + { url = "https://files.pythonhosted.org/packages/30/b2/e2285dda065d9f29ab4b23d8bcc81eb881db512afb38a3f5247b191be36c/aiohttp-3.11.18-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ff5625413fec55216da5eaa011cf6b0a2ed67a565914a212a51aa3755b0009", size = 1618871, upload-time = "2025-04-21T09:41:41.972Z" }, + { url = "https://files.pythonhosted.org/packages/57/e0/88f2987885d4b646de2036f7296ebea9268fdbf27476da551c1a7c158bc0/aiohttp-3.11.18-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7f33a92a2fde08e8c6b0c61815521324fc1612f397abf96eed86b8e31618fdb4", size = 1646262, upload-time = "2025-04-21T09:41:44.192Z" }, + { url = "https://files.pythonhosted.org/packages/e0/19/4d2da508b4c587e7472a032290b2981f7caeca82b4354e19ab3df2f51d56/aiohttp-3.11.18-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:11d5391946605f445ddafda5eab11caf310f90cdda1fd99865564e3164f5cff9", size = 1677431, upload-time = "2025-04-21T09:41:46.049Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ae/047473ea50150a41440f3265f53db1738870b5a1e5406ece561ca61a3bf4/aiohttp-3.11.18-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3cc314245deb311364884e44242e00c18b5896e4fe6d5f942e7ad7e4cb640adb", size = 1637430, upload-time = "2025-04-21T09:41:47.973Z" }, + { url = "https://files.pythonhosted.org/packages/11/32/c6d1e3748077ce7ee13745fae33e5cb1dac3e3b8f8787bf738a93c94a7d2/aiohttp-3.11.18-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0f421843b0f70740772228b9e8093289924359d306530bcd3926f39acbe1adda", size = 1703342, upload-time = "2025-04-21T09:41:50.323Z" }, + { url = "https://files.pythonhosted.org/packages/c5/1d/a3b57bfdbe285f0d45572d6d8f534fd58761da3e9cbc3098372565005606/aiohttp-3.11.18-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e220e7562467dc8d589e31c1acd13438d82c03d7f385c9cd41a3f6d1d15807c1", size = 1740600, upload-time = "2025-04-21T09:41:52.111Z" }, + { url = "https://files.pythonhosted.org/packages/a5/71/f9cd2fed33fa2b7ce4d412fb7876547abb821d5b5520787d159d0748321d/aiohttp-3.11.18-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ab2ef72f8605046115bc9aa8e9d14fd49086d405855f40b79ed9e5c1f9f4faea", size = 1695131, upload-time = "2025-04-21T09:41:53.94Z" }, + { url = "https://files.pythonhosted.org/packages/97/97/d1248cd6d02b9de6aa514793d0dcb20099f0ec47ae71a933290116c070c5/aiohttp-3.11.18-cp312-cp312-win32.whl", hash = "sha256:12a62691eb5aac58d65200c7ae94d73e8a65c331c3a86a2e9670927e94339ee8", size = 412442, upload-time = "2025-04-21T09:41:55.689Z" }, + { url = "https://files.pythonhosted.org/packages/33/9a/e34e65506e06427b111e19218a99abf627638a9703f4b8bcc3e3021277ed/aiohttp-3.11.18-cp312-cp312-win_amd64.whl", hash = "sha256:364329f319c499128fd5cd2d1c31c44f234c58f9b96cc57f743d16ec4f3238c8", size = 439444, upload-time = "2025-04-21T09:41:57.977Z" }, { url = "https://files.pythonhosted.org/packages/0a/18/be8b5dd6b9cf1b2172301dbed28e8e5e878ee687c21947a6c81d6ceaa15d/aiohttp-3.11.18-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:474215ec618974054cf5dc465497ae9708543cbfc312c65212325d4212525811", size = 699833, upload-time = "2025-04-21T09:42:00.298Z" }, { url = "https://files.pythonhosted.org/packages/0d/84/ecdc68e293110e6f6f6d7b57786a77555a85f70edd2b180fb1fafaff361a/aiohttp-3.11.18-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ced70adf03920d4e67c373fd692123e34d3ac81dfa1c27e45904a628567d804", size = 462774, upload-time = "2025-04-21T09:42:02.015Z" }, { url = "https://files.pythonhosted.org/packages/d7/85/f07718cca55884dad83cc2433746384d267ee970e91f0dcc75c6d5544079/aiohttp-3.11.18-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2d9f6c0152f8d71361905aaf9ed979259537981f47ad099c8b3d81e0319814bd", size = 454429, upload-time = "2025-04-21T09:42:03.728Z" }, @@ -72,6 +92,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "idna" }, { name = "sniffio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949, upload-time = "2025-03-17T00:02:54.77Z" } wheels = [ @@ -202,6 +223,17 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" } wheels = [ + { 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, upload-time = "2024-09-04T20:44:12.232Z" }, + { 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, upload-time = "2024-09-04T20:44:13.739Z" }, + { 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, upload-time = "2024-09-04T20:44:15.231Z" }, + { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload-time = "2024-09-04T20:44:17.188Z" }, + { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload-time = "2024-09-04T20:44:18.688Z" }, + { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload-time = "2024-09-04T20:44:20.248Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload-time = "2024-09-04T20:44:21.673Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload-time = "2024-09-04T20:44:23.245Z" }, + { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload-time = "2024-09-04T20:44:24.757Z" }, + { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload-time = "2024-09-04T20:44:26.208Z" }, + { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" }, { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989, upload-time = "2024-09-04T20:44:28.956Z" }, { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802, upload-time = "2024-09-04T20:44:30.289Z" }, { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload-time = "2024-09-04T20:44:32.01Z" }, @@ -221,6 +253,19 @@ version = "3.4.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367, upload-time = "2025-05-02T08:34:42.01Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/a4/37f4d6035c89cac7930395a35cc0f1b872e652eaafb76a6075943754f095/charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", size = 199936, upload-time = "2025-05-02T08:32:33.712Z" }, + { url = "https://files.pythonhosted.org/packages/ee/8a/1a5e33b73e0d9287274f899d967907cd0bf9c343e651755d9307e0dbf2b3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", size = 143790, upload-time = "2025-05-02T08:32:35.768Z" }, + { url = "https://files.pythonhosted.org/packages/66/52/59521f1d8e6ab1482164fa21409c5ef44da3e9f653c13ba71becdd98dec3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", size = 153924, upload-time = "2025-05-02T08:32:37.284Z" }, + { url = "https://files.pythonhosted.org/packages/86/2d/fb55fdf41964ec782febbf33cb64be480a6b8f16ded2dbe8db27a405c09f/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", size = 146626, upload-time = "2025-05-02T08:32:38.803Z" }, + { url = "https://files.pythonhosted.org/packages/8c/73/6ede2ec59bce19b3edf4209d70004253ec5f4e319f9a2e3f2f15601ed5f7/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", size = 148567, upload-time = "2025-05-02T08:32:40.251Z" }, + { url = "https://files.pythonhosted.org/packages/09/14/957d03c6dc343c04904530b6bef4e5efae5ec7d7990a7cbb868e4595ee30/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", size = 150957, upload-time = "2025-05-02T08:32:41.705Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c8/8174d0e5c10ccebdcb1b53cc959591c4c722a3ad92461a273e86b9f5a302/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", size = 145408, upload-time = "2025-05-02T08:32:43.709Z" }, + { url = "https://files.pythonhosted.org/packages/58/aa/8904b84bc8084ac19dc52feb4f5952c6df03ffb460a887b42615ee1382e8/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", size = 153399, upload-time = "2025-05-02T08:32:46.197Z" }, + { url = "https://files.pythonhosted.org/packages/c2/26/89ee1f0e264d201cb65cf054aca6038c03b1a0c6b4ae998070392a3ce605/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", size = 156815, upload-time = "2025-05-02T08:32:48.105Z" }, + { url = "https://files.pythonhosted.org/packages/fd/07/68e95b4b345bad3dbbd3a8681737b4338ff2c9df29856a6d6d23ac4c73cb/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", size = 154537, upload-time = "2025-05-02T08:32:49.719Z" }, + { url = "https://files.pythonhosted.org/packages/77/1a/5eefc0ce04affb98af07bc05f3bac9094513c0e23b0562d64af46a06aae4/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", size = 149565, upload-time = "2025-05-02T08:32:51.404Z" }, + { url = "https://files.pythonhosted.org/packages/37/a0/2410e5e6032a174c95e0806b1a6585eb21e12f445ebe239fac441995226a/charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", size = 98357, upload-time = "2025-05-02T08:32:53.079Z" }, + { url = "https://files.pythonhosted.org/packages/6c/4f/c02d5c493967af3eda9c771ad4d2bbc8df6f99ddbeb37ceea6e8716a32bc/charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", size = 105776, upload-time = "2025-05-02T08:32:54.573Z" }, { url = "https://files.pythonhosted.org/packages/ea/12/a93df3366ed32db1d907d7593a94f1fe6293903e3e92967bebd6950ed12c/charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", size = 199622, upload-time = "2025-05-02T08:32:56.363Z" }, { url = "https://files.pythonhosted.org/packages/04/93/bf204e6f344c39d9937d3c13c8cd5bbfc266472e51fc8c07cb7f64fcd2de/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", size = 143435, upload-time = "2025-05-02T08:32:58.551Z" }, { url = "https://files.pythonhosted.org/packages/22/2a/ea8a2095b0bafa6c5b5a55ffdc2f924455233ee7b91c69b7edfcc9e02284/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", size = 153653, upload-time = "2025-05-02T08:33:00.342Z" }, @@ -356,6 +401,23 @@ version = "1.6.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ee/f4/d744cba2da59b5c1d88823cf9e8a6c74e4659e2b27604ed973be2a0bf5ab/frozenlist-1.6.0.tar.gz", hash = "sha256:b99655c32c1c8e06d111e7f41c06c29a5318cb1835df23a45518e02a47c63b68", size = 42831, upload-time = "2025-04-17T22:38:53.099Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/9c/8a/289b7d0de2fbac832ea80944d809759976f661557a38bb8e77db5d9f79b7/frozenlist-1.6.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c5b9e42ace7d95bf41e19b87cec8f262c41d3510d8ad7514ab3862ea2197bfb1", size = 160193, upload-time = "2025-04-17T22:36:47.382Z" }, + { url = "https://files.pythonhosted.org/packages/19/80/2fd17d322aec7f430549f0669f599997174f93ee17929ea5b92781ec902c/frozenlist-1.6.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ca9973735ce9f770d24d5484dcb42f68f135351c2fc81a7a9369e48cf2998a29", size = 123831, upload-time = "2025-04-17T22:36:49.401Z" }, + { url = "https://files.pythonhosted.org/packages/99/06/f5812da431273f78c6543e0b2f7de67dfd65eb0a433978b2c9c63d2205e4/frozenlist-1.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6ac40ec76041c67b928ca8aaffba15c2b2ee3f5ae8d0cb0617b5e63ec119ca25", size = 121862, upload-time = "2025-04-17T22:36:51.899Z" }, + { url = "https://files.pythonhosted.org/packages/d0/31/9e61c6b5fc493cf24d54881731204d27105234d09878be1a5983182cc4a5/frozenlist-1.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95b7a8a3180dfb280eb044fdec562f9b461614c0ef21669aea6f1d3dac6ee576", size = 316361, upload-time = "2025-04-17T22:36:53.402Z" }, + { url = "https://files.pythonhosted.org/packages/9d/55/22ca9362d4f0222324981470fd50192be200154d51509ee6eb9baa148e96/frozenlist-1.6.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c444d824e22da6c9291886d80c7d00c444981a72686e2b59d38b285617cb52c8", size = 307115, upload-time = "2025-04-17T22:36:55.016Z" }, + { url = "https://files.pythonhosted.org/packages/ae/39/4fff42920a57794881e7bb3898dc7f5f539261711ea411b43bba3cde8b79/frozenlist-1.6.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb52c8166499a8150bfd38478248572c924c003cbb45fe3bcd348e5ac7c000f9", size = 322505, upload-time = "2025-04-17T22:36:57.12Z" }, + { url = "https://files.pythonhosted.org/packages/55/f2/88c41f374c1e4cf0092a5459e5f3d6a1e17ed274c98087a76487783df90c/frozenlist-1.6.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b35298b2db9c2468106278537ee529719228950a5fdda686582f68f247d1dc6e", size = 322666, upload-time = "2025-04-17T22:36:58.735Z" }, + { url = "https://files.pythonhosted.org/packages/75/51/034eeb75afdf3fd03997856195b500722c0b1a50716664cde64e28299c4b/frozenlist-1.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d108e2d070034f9d57210f22fefd22ea0d04609fc97c5f7f5a686b3471028590", size = 302119, upload-time = "2025-04-17T22:37:00.512Z" }, + { url = "https://files.pythonhosted.org/packages/2b/a6/564ecde55ee633270a793999ef4fd1d2c2b32b5a7eec903b1012cb7c5143/frozenlist-1.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e1be9111cb6756868ac242b3c2bd1f09d9aea09846e4f5c23715e7afb647103", size = 316226, upload-time = "2025-04-17T22:37:02.102Z" }, + { url = "https://files.pythonhosted.org/packages/f1/c8/6c0682c32377f402b8a6174fb16378b683cf6379ab4d2827c580892ab3c7/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:94bb451c664415f02f07eef4ece976a2c65dcbab9c2f1705b7031a3a75349d8c", size = 312788, upload-time = "2025-04-17T22:37:03.578Z" }, + { url = "https://files.pythonhosted.org/packages/b6/b8/10fbec38f82c5d163ca1750bfff4ede69713badf236a016781cf1f10a0f0/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d1a686d0b0949182b8faddea596f3fc11f44768d1f74d4cad70213b2e139d821", size = 325914, upload-time = "2025-04-17T22:37:05.213Z" }, + { url = "https://files.pythonhosted.org/packages/62/ca/2bf4f3a1bd40cdedd301e6ecfdbb291080d5afc5f9ce350c0739f773d6b9/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ea8e59105d802c5a38bdbe7362822c522230b3faba2aa35c0fa1765239b7dd70", size = 305283, upload-time = "2025-04-17T22:37:06.985Z" }, + { url = "https://files.pythonhosted.org/packages/09/64/20cc13ccf94abc2a1f482f74ad210703dc78a590d0b805af1c9aa67f76f9/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:abc4e880a9b920bc5020bf6a431a6bb40589d9bca3975c980495f63632e8382f", size = 319264, upload-time = "2025-04-17T22:37:08.618Z" }, + { url = "https://files.pythonhosted.org/packages/20/ff/86c6a2bbe98cfc231519f5e6d712a0898488ceac804a917ce014f32e68f6/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9a79713adfe28830f27a3c62f6b5406c37376c892b05ae070906f07ae4487046", size = 326482, upload-time = "2025-04-17T22:37:10.196Z" }, + { url = "https://files.pythonhosted.org/packages/2f/da/8e381f66367d79adca245d1d71527aac774e30e291d41ef161ce2d80c38e/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a0318c2068e217a8f5e3b85e35899f5a19e97141a45bb925bb357cfe1daf770", size = 318248, upload-time = "2025-04-17T22:37:12.284Z" }, + { url = "https://files.pythonhosted.org/packages/39/24/1a1976563fb476ab6f0fa9fefaac7616a4361dbe0461324f9fd7bf425dbe/frozenlist-1.6.0-cp312-cp312-win32.whl", hash = "sha256:853ac025092a24bb3bf09ae87f9127de9fe6e0c345614ac92536577cf956dfcc", size = 115161, upload-time = "2025-04-17T22:37:13.902Z" }, + { url = "https://files.pythonhosted.org/packages/80/2e/fb4ed62a65f8cd66044706b1013f0010930d8cbb0729a2219561ea075434/frozenlist-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:2bdfe2d7e6c9281c6e55523acd6c2bf77963cb422fdc7d142fb0cb6621b66878", size = 120548, upload-time = "2025-04-17T22:37:15.326Z" }, { url = "https://files.pythonhosted.org/packages/6f/e5/04c7090c514d96ca00887932417f04343ab94904a56ab7f57861bf63652d/frozenlist-1.6.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1d7fb014fe0fbfee3efd6a94fc635aeaa68e5e1720fe9e57357f2e2c6e1a647e", size = 158182, upload-time = "2025-04-17T22:37:16.837Z" }, { url = "https://files.pythonhosted.org/packages/e9/8f/60d0555c61eec855783a6356268314d204137f5e0c53b59ae2fc28938c99/frozenlist-1.6.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01bcaa305a0fdad12745502bfd16a1c75b14558dabae226852f9159364573117", size = 122838, upload-time = "2025-04-17T22:37:18.352Z" }, { url = "https://files.pythonhosted.org/packages/5a/a7/d0ec890e3665b4b3b7c05dc80e477ed8dc2e2e77719368e78e2cd9fec9c8/frozenlist-1.6.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8b314faa3051a6d45da196a2c495e922f987dc848e967d8cfeaee8a0328b1cd4", size = 120980, upload-time = "2025-04-17T22:37:19.857Z" }, @@ -524,6 +586,18 @@ version = "0.9.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/1e/c2/e4562507f52f0af7036da125bb699602ead37a2332af0788f8e0a3417f36/jiter-0.9.0.tar.gz", hash = "sha256:aadba0964deb424daa24492abc3d229c60c4a31bfee205aedbf1acc7639d7893", size = 162604, upload-time = "2025-03-10T21:37:03.278Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/af/d7/c55086103d6f29b694ec79156242304adf521577530d9031317ce5338c59/jiter-0.9.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7b46249cfd6c48da28f89eb0be3f52d6fdb40ab88e2c66804f546674e539ec11", size = 309203, upload-time = "2025-03-10T21:35:44.852Z" }, + { url = "https://files.pythonhosted.org/packages/b0/01/f775dfee50beb420adfd6baf58d1c4d437de41c9b666ddf127c065e5a488/jiter-0.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:609cf3c78852f1189894383cf0b0b977665f54cb38788e3e6b941fa6d982c00e", size = 319678, upload-time = "2025-03-10T21:35:46.365Z" }, + { url = "https://files.pythonhosted.org/packages/ab/b8/09b73a793714726893e5d46d5c534a63709261af3d24444ad07885ce87cb/jiter-0.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d726a3890a54561e55a9c5faea1f7655eda7f105bd165067575ace6e65f80bb2", size = 341816, upload-time = "2025-03-10T21:35:47.856Z" }, + { url = "https://files.pythonhosted.org/packages/35/6f/b8f89ec5398b2b0d344257138182cc090302854ed63ed9c9051e9c673441/jiter-0.9.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2e89dc075c1fef8fa9be219e249f14040270dbc507df4215c324a1839522ea75", size = 364152, upload-time = "2025-03-10T21:35:49.397Z" }, + { url = "https://files.pythonhosted.org/packages/9b/ca/978cc3183113b8e4484cc7e210a9ad3c6614396e7abd5407ea8aa1458eef/jiter-0.9.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04e8ffa3c353b1bc4134f96f167a2082494351e42888dfcf06e944f2729cbe1d", size = 406991, upload-time = "2025-03-10T21:35:50.745Z" }, + { url = "https://files.pythonhosted.org/packages/13/3a/72861883e11a36d6aa314b4922125f6ae90bdccc225cd96d24cc78a66385/jiter-0.9.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:203f28a72a05ae0e129b3ed1f75f56bc419d5f91dfacd057519a8bd137b00c42", size = 395824, upload-time = "2025-03-10T21:35:52.162Z" }, + { url = "https://files.pythonhosted.org/packages/87/67/22728a86ef53589c3720225778f7c5fdb617080e3deaed58b04789418212/jiter-0.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fca1a02ad60ec30bb230f65bc01f611c8608b02d269f998bc29cca8619a919dc", size = 351318, upload-time = "2025-03-10T21:35:53.566Z" }, + { url = "https://files.pythonhosted.org/packages/69/b9/f39728e2e2007276806d7a6609cda7fac44ffa28ca0d02c49a4f397cc0d9/jiter-0.9.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:237e5cee4d5d2659aaf91bbf8ec45052cc217d9446070699441a91b386ae27dc", size = 384591, upload-time = "2025-03-10T21:35:54.95Z" }, + { url = "https://files.pythonhosted.org/packages/eb/8f/8a708bc7fd87b8a5d861f1c118a995eccbe6d672fe10c9753e67362d0dd0/jiter-0.9.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:528b6b71745e7326eed73c53d4aa57e2a522242320b6f7d65b9c5af83cf49b6e", size = 520746, upload-time = "2025-03-10T21:35:56.444Z" }, + { url = "https://files.pythonhosted.org/packages/95/1e/65680c7488bd2365dbd2980adaf63c562d3d41d3faac192ebc7ef5b4ae25/jiter-0.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9f48e86b57bc711eb5acdfd12b6cb580a59cc9a993f6e7dcb6d8b50522dcd50d", size = 512754, upload-time = "2025-03-10T21:35:58.789Z" }, + { url = "https://files.pythonhosted.org/packages/78/f3/fdc43547a9ee6e93c837685da704fb6da7dba311fc022e2766d5277dfde5/jiter-0.9.0-cp312-cp312-win32.whl", hash = "sha256:699edfde481e191d81f9cf6d2211debbfe4bd92f06410e7637dffb8dd5dfde06", size = 207075, upload-time = "2025-03-10T21:36:00.616Z" }, + { url = "https://files.pythonhosted.org/packages/cd/9d/742b289016d155f49028fe1bfbeb935c9bf0ffeefdf77daf4a63a42bb72b/jiter-0.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:099500d07b43f61d8bd780466d429c45a7b25411b334c60ca875fa775f68ccb0", size = 207999, upload-time = "2025-03-10T21:36:02.366Z" }, { url = "https://files.pythonhosted.org/packages/e7/1b/4cd165c362e8f2f520fdb43245e2b414f42a255921248b4f8b9c8d871ff1/jiter-0.9.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:2764891d3f3e8b18dce2cff24949153ee30c9239da7c00f032511091ba688ff7", size = 308197, upload-time = "2025-03-10T21:36:03.828Z" }, { url = "https://files.pythonhosted.org/packages/13/aa/7a890dfe29c84c9a82064a9fe36079c7c0309c91b70c380dc138f9bea44a/jiter-0.9.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:387b22fbfd7a62418d5212b4638026d01723761c75c1c8232a8b8c37c2f1003b", size = 318160, upload-time = "2025-03-10T21:36:05.281Z" }, { url = "https://files.pythonhosted.org/packages/6a/38/5888b43fc01102f733f085673c4f0be5a298f69808ec63de55051754e390/jiter-0.9.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d8da8629ccae3606c61d9184970423655fb4e33d03330bcdfe52d234d32f69", size = 341259, upload-time = "2025-03-10T21:36:06.716Z" }, @@ -559,6 +633,23 @@ version = "5.4.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/76/3d/14e82fc7c8fb1b7761f7e748fd47e2ec8276d137b6acfe5a4bb73853e08f/lxml-5.4.0.tar.gz", hash = "sha256:d12832e1dbea4be280b22fd0ea7c9b87f0d8fc51ba06e92dc62d52f804f78ebd", size = 3679479, upload-time = "2025-04-23T01:50:29.322Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/4c/d101ace719ca6a4ec043eb516fcfcb1b396a9fccc4fcd9ef593df34ba0d5/lxml-5.4.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b5aff6f3e818e6bdbbb38e5967520f174b18f539c2b9de867b1e7fde6f8d95a4", size = 8127392, upload-time = "2025-04-23T01:46:04.09Z" }, + { url = "https://files.pythonhosted.org/packages/11/84/beddae0cec4dd9ddf46abf156f0af451c13019a0fa25d7445b655ba5ccb7/lxml-5.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:942a5d73f739ad7c452bf739a62a0f83e2578afd6b8e5406308731f4ce78b16d", size = 4415103, upload-time = "2025-04-23T01:46:07.227Z" }, + { url = "https://files.pythonhosted.org/packages/d0/25/d0d93a4e763f0462cccd2b8a665bf1e4343dd788c76dcfefa289d46a38a9/lxml-5.4.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:460508a4b07364d6abf53acaa0a90b6d370fafde5693ef37602566613a9b0779", size = 5024224, upload-time = "2025-04-23T01:46:10.237Z" }, + { url = "https://files.pythonhosted.org/packages/31/ce/1df18fb8f7946e7f3388af378b1f34fcf253b94b9feedb2cec5969da8012/lxml-5.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:529024ab3a505fed78fe3cc5ddc079464e709f6c892733e3f5842007cec8ac6e", size = 4769913, upload-time = "2025-04-23T01:46:12.757Z" }, + { url = "https://files.pythonhosted.org/packages/4e/62/f4a6c60ae7c40d43657f552f3045df05118636be1165b906d3423790447f/lxml-5.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ca56ebc2c474e8f3d5761debfd9283b8b18c76c4fc0967b74aeafba1f5647f9", size = 5290441, upload-time = "2025-04-23T01:46:16.037Z" }, + { url = "https://files.pythonhosted.org/packages/9e/aa/04f00009e1e3a77838c7fc948f161b5d2d5de1136b2b81c712a263829ea4/lxml-5.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a81e1196f0a5b4167a8dafe3a66aa67c4addac1b22dc47947abd5d5c7a3f24b5", size = 4820165, upload-time = "2025-04-23T01:46:19.137Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/e0b2f61fa2404bf0f1fdf1898377e5bd1b74cc9b2cf2c6ba8509b8f27990/lxml-5.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00b8686694423ddae324cf614e1b9659c2edb754de617703c3d29ff568448df5", size = 4932580, upload-time = "2025-04-23T01:46:21.963Z" }, + { url = "https://files.pythonhosted.org/packages/24/a2/8263f351b4ffe0ed3e32ea7b7830f845c795349034f912f490180d88a877/lxml-5.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:c5681160758d3f6ac5b4fea370495c48aac0989d6a0f01bb9a72ad8ef5ab75c4", size = 4759493, upload-time = "2025-04-23T01:46:24.316Z" }, + { url = "https://files.pythonhosted.org/packages/05/00/41db052f279995c0e35c79d0f0fc9f8122d5b5e9630139c592a0b58c71b4/lxml-5.4.0-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:2dc191e60425ad70e75a68c9fd90ab284df64d9cd410ba8d2b641c0c45bc006e", size = 5324679, upload-time = "2025-04-23T01:46:27.097Z" }, + { url = "https://files.pythonhosted.org/packages/1d/be/ee99e6314cdef4587617d3b3b745f9356d9b7dd12a9663c5f3b5734b64ba/lxml-5.4.0-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:67f779374c6b9753ae0a0195a892a1c234ce8416e4448fe1e9f34746482070a7", size = 4890691, upload-time = "2025-04-23T01:46:30.009Z" }, + { url = "https://files.pythonhosted.org/packages/ad/36/239820114bf1d71f38f12208b9c58dec033cbcf80101cde006b9bde5cffd/lxml-5.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:79d5bfa9c1b455336f52343130b2067164040604e41f6dc4d8313867ed540079", size = 4955075, upload-time = "2025-04-23T01:46:32.33Z" }, + { url = "https://files.pythonhosted.org/packages/d4/e1/1b795cc0b174efc9e13dbd078a9ff79a58728a033142bc6d70a1ee8fc34d/lxml-5.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3d3c30ba1c9b48c68489dc1829a6eede9873f52edca1dda900066542528d6b20", size = 4838680, upload-time = "2025-04-23T01:46:34.852Z" }, + { url = "https://files.pythonhosted.org/packages/72/48/3c198455ca108cec5ae3662ae8acd7fd99476812fd712bb17f1b39a0b589/lxml-5.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1af80c6316ae68aded77e91cd9d80648f7dd40406cef73df841aa3c36f6907c8", size = 5391253, upload-time = "2025-04-23T01:46:37.608Z" }, + { url = "https://files.pythonhosted.org/packages/d6/10/5bf51858971c51ec96cfc13e800a9951f3fd501686f4c18d7d84fe2d6352/lxml-5.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4d885698f5019abe0de3d352caf9466d5de2baded00a06ef3f1216c1a58ae78f", size = 5261651, upload-time = "2025-04-23T01:46:40.183Z" }, + { url = "https://files.pythonhosted.org/packages/2b/11/06710dd809205377da380546f91d2ac94bad9ff735a72b64ec029f706c85/lxml-5.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aea53d51859b6c64e7c51d522c03cc2c48b9b5d6172126854cc7f01aa11f52bc", size = 5024315, upload-time = "2025-04-23T01:46:43.333Z" }, + { url = "https://files.pythonhosted.org/packages/f5/b0/15b6217834b5e3a59ebf7f53125e08e318030e8cc0d7310355e6edac98ef/lxml-5.4.0-cp312-cp312-win32.whl", hash = "sha256:d90b729fd2732df28130c064aac9bb8aff14ba20baa4aee7bd0795ff1187545f", size = 3486149, upload-time = "2025-04-23T01:46:45.684Z" }, + { url = "https://files.pythonhosted.org/packages/91/1e/05ddcb57ad2f3069101611bd5f5084157d90861a2ef460bf42f45cced944/lxml-5.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1dc4ca99e89c335a7ed47d38964abcb36c5910790f9bd106f2a8fa2ee0b909d2", size = 3817095, upload-time = "2025-04-23T01:46:48.521Z" }, { url = "https://files.pythonhosted.org/packages/87/cb/2ba1e9dd953415f58548506fa5549a7f373ae55e80c61c9041b7fd09a38a/lxml-5.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:773e27b62920199c6197130632c18fb7ead3257fce1ffb7d286912e56ddb79e0", size = 8110086, upload-time = "2025-04-23T01:46:52.218Z" }, { url = "https://files.pythonhosted.org/packages/b5/3e/6602a4dca3ae344e8609914d6ab22e52ce42e3e1638c10967568c5c1450d/lxml-5.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ce9c671845de9699904b1e9df95acfe8dfc183f2310f163cdaa91a3535af95de", size = 4404613, upload-time = "2025-04-23T01:46:55.281Z" }, { url = "https://files.pythonhosted.org/packages/4c/72/bf00988477d3bb452bef9436e45aeea82bb40cdfb4684b83c967c53909c7/lxml-5.4.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9454b8d8200ec99a224df8854786262b1bd6461f4280064c807303c642c05e76", size = 5012008, upload-time = "2025-04-23T01:46:57.817Z" }, @@ -735,6 +826,23 @@ version = "6.4.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/da/2c/e367dfb4c6538614a0c9453e510d75d66099edf1c4e69da1b5ce691a1931/multidict-6.4.3.tar.gz", hash = "sha256:3ada0b058c9f213c5f95ba301f922d402ac234f1111a7d8fd70f1b99f3c281ec", size = 89372, upload-time = "2025-04-10T22:20:17.956Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/bb/3abdaf8fe40e9226ce8a2ba5ecf332461f7beec478a455d6587159f1bf92/multidict-6.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1f1c2f58f08b36f8475f3ec6f5aeb95270921d418bf18f90dffd6be5c7b0e676", size = 64019, upload-time = "2025-04-10T22:18:23.174Z" }, + { url = "https://files.pythonhosted.org/packages/7e/b5/1b2e8de8217d2e89db156625aa0fe4a6faad98972bfe07a7b8c10ef5dd6b/multidict-6.4.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:26ae9ad364fc61b936fb7bf4c9d8bd53f3a5b4417142cd0be5c509d6f767e2f1", size = 37925, upload-time = "2025-04-10T22:18:24.834Z" }, + { url = "https://files.pythonhosted.org/packages/b4/e2/3ca91c112644a395c8eae017144c907d173ea910c913ff8b62549dcf0bbf/multidict-6.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:659318c6c8a85f6ecfc06b4e57529e5a78dfdd697260cc81f683492ad7e9435a", size = 37008, upload-time = "2025-04-10T22:18:26.069Z" }, + { url = "https://files.pythonhosted.org/packages/60/23/79bc78146c7ac8d1ac766b2770ca2e07c2816058b8a3d5da6caed8148637/multidict-6.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1eb72c741fd24d5a28242ce72bb61bc91f8451877131fa3fe930edb195f7054", size = 224374, upload-time = "2025-04-10T22:18:27.714Z" }, + { url = "https://files.pythonhosted.org/packages/86/35/77950ed9ebd09136003a85c1926ba42001ca5be14feb49710e4334ee199b/multidict-6.4.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3cd06d88cb7398252284ee75c8db8e680aa0d321451132d0dba12bc995f0adcc", size = 230869, upload-time = "2025-04-10T22:18:29.162Z" }, + { url = "https://files.pythonhosted.org/packages/49/97/2a33c6e7d90bc116c636c14b2abab93d6521c0c052d24bfcc231cbf7f0e7/multidict-6.4.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4543d8dc6470a82fde92b035a92529317191ce993533c3c0c68f56811164ed07", size = 231949, upload-time = "2025-04-10T22:18:30.679Z" }, + { url = "https://files.pythonhosted.org/packages/56/ce/e9b5d9fcf854f61d6686ada7ff64893a7a5523b2a07da6f1265eaaea5151/multidict-6.4.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:30a3ebdc068c27e9d6081fca0e2c33fdf132ecea703a72ea216b81a66860adde", size = 231032, upload-time = "2025-04-10T22:18:32.146Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ac/7ced59dcdfeddd03e601edb05adff0c66d81ed4a5160c443e44f2379eef0/multidict-6.4.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b038f10e23f277153f86f95c777ba1958bcd5993194fda26a1d06fae98b2f00c", size = 223517, upload-time = "2025-04-10T22:18:33.538Z" }, + { url = "https://files.pythonhosted.org/packages/db/e6/325ed9055ae4e085315193a1b58bdb4d7fc38ffcc1f4975cfca97d015e17/multidict-6.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c605a2b2dc14282b580454b9b5d14ebe0668381a3a26d0ac39daa0ca115eb2ae", size = 216291, upload-time = "2025-04-10T22:18:34.962Z" }, + { url = "https://files.pythonhosted.org/packages/fa/84/eeee6d477dd9dcb7691c3bb9d08df56017f5dd15c730bcc9383dcf201cf4/multidict-6.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8bd2b875f4ca2bb527fe23e318ddd509b7df163407b0fb717df229041c6df5d3", size = 228982, upload-time = "2025-04-10T22:18:36.443Z" }, + { url = "https://files.pythonhosted.org/packages/82/94/4d1f3e74e7acf8b0c85db350e012dcc61701cd6668bc2440bb1ecb423c90/multidict-6.4.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c2e98c840c9c8e65c0e04b40c6c5066c8632678cd50c8721fdbcd2e09f21a507", size = 226823, upload-time = "2025-04-10T22:18:37.924Z" }, + { url = "https://files.pythonhosted.org/packages/09/f0/1e54b95bda7cd01080e5732f9abb7b76ab5cc795b66605877caeb2197476/multidict-6.4.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:66eb80dd0ab36dbd559635e62fba3083a48a252633164857a1d1684f14326427", size = 222714, upload-time = "2025-04-10T22:18:39.807Z" }, + { url = "https://files.pythonhosted.org/packages/e7/a2/f6cbca875195bd65a3e53b37ab46486f3cc125bdeab20eefe5042afa31fb/multidict-6.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c23831bdee0a2a3cf21be057b5e5326292f60472fb6c6f86392bbf0de70ba731", size = 233739, upload-time = "2025-04-10T22:18:41.341Z" }, + { url = "https://files.pythonhosted.org/packages/79/68/9891f4d2b8569554723ddd6154375295f789dc65809826c6fb96a06314fd/multidict-6.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1535cec6443bfd80d028052e9d17ba6ff8a5a3534c51d285ba56c18af97e9713", size = 230809, upload-time = "2025-04-10T22:18:42.817Z" }, + { url = "https://files.pythonhosted.org/packages/e6/72/a7be29ba1e87e4fc5ceb44dabc7940b8005fd2436a332a23547709315f70/multidict-6.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3b73e7227681f85d19dec46e5b881827cd354aabe46049e1a61d2f9aaa4e285a", size = 226934, upload-time = "2025-04-10T22:18:44.311Z" }, + { url = "https://files.pythonhosted.org/packages/12/c1/259386a9ad6840ff7afc686da96808b503d152ac4feb3a96c651dc4f5abf/multidict-6.4.3-cp312-cp312-win32.whl", hash = "sha256:8eac0c49df91b88bf91f818e0a24c1c46f3622978e2c27035bfdca98e0e18124", size = 35242, upload-time = "2025-04-10T22:18:46.193Z" }, + { url = "https://files.pythonhosted.org/packages/06/24/c8fdff4f924d37225dc0c56a28b1dca10728fc2233065fafeb27b4b125be/multidict-6.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:11990b5c757d956cd1db7cb140be50a63216af32cd6506329c2c59d732d802db", size = 38635, upload-time = "2025-04-10T22:18:47.498Z" }, { url = "https://files.pythonhosted.org/packages/6c/4b/86fd786d03915c6f49998cf10cd5fe6b6ac9e9a071cb40885d2e080fb90d/multidict-6.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a76534263d03ae0cfa721fea40fd2b5b9d17a6f85e98025931d41dc49504474", size = 63831, upload-time = "2025-04-10T22:18:48.748Z" }, { url = "https://files.pythonhosted.org/packages/45/05/9b51fdf7aef2563340a93be0a663acba2c428c4daeaf3960d92d53a4a930/multidict-6.4.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:805031c2f599eee62ac579843555ed1ce389ae00c7e9f74c2a1b45e0564a88dd", size = 37888, upload-time = "2025-04-10T22:18:50.021Z" }, { url = "https://files.pythonhosted.org/packages/0b/43/53fc25394386c911822419b522181227ca450cf57fea76e6188772a1bd91/multidict-6.4.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c56c179839d5dcf51d565132185409d1d5dd8e614ba501eb79023a6cab25576b", size = 36852, upload-time = "2025-04-10T22:18:51.246Z" }, @@ -778,6 +886,16 @@ version = "2.2.5" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/dc/b2/ce4b867d8cd9c0ee84938ae1e6a6f7926ebf928c9090d036fc3c6a04f946/numpy-2.2.5.tar.gz", hash = "sha256:a9c0d994680cd991b1cb772e8b297340085466a6fe964bc9d4e80f5e2f43c291", size = 20273920, upload-time = "2025-04-19T23:27:42.561Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/f7/1fd4ff108cd9d7ef929b8882692e23665dc9c23feecafbb9c6b80f4ec583/numpy-2.2.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ee461a4eaab4f165b68780a6a1af95fb23a29932be7569b9fab666c407969051", size = 20948633, upload-time = "2025-04-19T22:37:52.4Z" }, + { url = "https://files.pythonhosted.org/packages/12/03/d443c278348371b20d830af155ff2079acad6a9e60279fac2b41dbbb73d8/numpy-2.2.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ec31367fd6a255dc8de4772bd1658c3e926d8e860a0b6e922b615e532d320ddc", size = 14176123, upload-time = "2025-04-19T22:38:15.058Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0b/5ca264641d0e7b14393313304da48b225d15d471250376f3fbdb1a2be603/numpy-2.2.5-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:47834cde750d3c9f4e52c6ca28a7361859fcaf52695c7dc3cc1a720b8922683e", size = 5163817, upload-time = "2025-04-19T22:38:24.885Z" }, + { url = "https://files.pythonhosted.org/packages/04/b3/d522672b9e3d28e26e1613de7675b441bbd1eaca75db95680635dd158c67/numpy-2.2.5-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:2c1a1c6ccce4022383583a6ded7bbcda22fc635eb4eb1e0a053336425ed36dfa", size = 6698066, upload-time = "2025-04-19T22:38:35.782Z" }, + { url = "https://files.pythonhosted.org/packages/a0/93/0f7a75c1ff02d4b76df35079676b3b2719fcdfb39abdf44c8b33f43ef37d/numpy-2.2.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d75f338f5f79ee23548b03d801d28a505198297534f62416391857ea0479571", size = 14087277, upload-time = "2025-04-19T22:38:57.697Z" }, + { url = "https://files.pythonhosted.org/packages/b0/d9/7c338b923c53d431bc837b5b787052fef9ae68a56fe91e325aac0d48226e/numpy-2.2.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a801fef99668f309b88640e28d261991bfad9617c27beda4a3aec4f217ea073", size = 16135742, upload-time = "2025-04-19T22:39:22.689Z" }, + { url = "https://files.pythonhosted.org/packages/2d/10/4dec9184a5d74ba9867c6f7d1e9f2e0fb5fe96ff2bf50bb6f342d64f2003/numpy-2.2.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:abe38cd8381245a7f49967a6010e77dbf3680bd3627c0fe4362dd693b404c7f8", size = 15581825, upload-time = "2025-04-19T22:39:45.794Z" }, + { url = "https://files.pythonhosted.org/packages/80/1f/2b6fcd636e848053f5b57712a7d1880b1565eec35a637fdfd0a30d5e738d/numpy-2.2.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5a0ac90e46fdb5649ab6369d1ab6104bfe5854ab19b645bf5cda0127a13034ae", size = 17899600, upload-time = "2025-04-19T22:40:13.427Z" }, + { url = "https://files.pythonhosted.org/packages/ec/87/36801f4dc2623d76a0a3835975524a84bd2b18fe0f8835d45c8eae2f9ff2/numpy-2.2.5-cp312-cp312-win32.whl", hash = "sha256:0cd48122a6b7eab8f06404805b1bd5856200e3ed6f8a1b9a194f9d9054631beb", size = 6312626, upload-time = "2025-04-19T22:40:25.223Z" }, + { url = "https://files.pythonhosted.org/packages/8b/09/4ffb4d6cfe7ca6707336187951992bd8a8b9142cf345d87ab858d2d7636a/numpy-2.2.5-cp312-cp312-win_amd64.whl", hash = "sha256:ced69262a8278547e63409b2653b372bf4baff0870c57efa76c5703fd6543282", size = 12645715, upload-time = "2025-04-19T22:40:44.528Z" }, { url = "https://files.pythonhosted.org/packages/e2/a0/0aa7f0f4509a2e07bd7a509042967c2fab635690d4f48c6c7b3afd4f448c/numpy-2.2.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:059b51b658f4414fff78c6d7b1b4e18283ab5fa56d270ff212d5ba0c561846f4", size = 20935102, upload-time = "2025-04-19T22:41:16.234Z" }, { url = "https://files.pythonhosted.org/packages/7e/e4/a6a9f4537542912ec513185396fce52cdd45bdcf3e9d921ab02a93ca5aa9/numpy-2.2.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:47f9ed103af0bc63182609044b0490747e03bd20a67e391192dde119bf43d52f", size = 14191709, upload-time = "2025-04-19T22:41:38.472Z" }, { url = "https://files.pythonhosted.org/packages/be/65/72f3186b6050bbfe9c43cb81f9df59ae63603491d36179cf7a7c8d216758/numpy-2.2.5-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:261a1ef047751bb02f29dfe337230b5882b54521ca121fc7f62668133cb119c9", size = 5149173, upload-time = "2025-04-19T22:41:47.823Z" }, @@ -822,6 +940,10 @@ dependencies = [ { name = "sympy" }, ] wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/de/9162872c6e502e9ac8c99a98a8738b2fab408123d11de55022ac4f92562a/onnxruntime-1.22.0-cp312-cp312-macosx_13_0_universal2.whl", hash = "sha256:f3c0380f53c1e72a41b3f4d6af2ccc01df2c17844072233442c3a7e74851ab97", size = 34298046, upload-time = "2025-05-09T20:26:02.399Z" }, + { url = "https://files.pythonhosted.org/packages/03/79/36f910cd9fc96b444b0e728bba14607016079786adf032dae61f7c63b4aa/onnxruntime-1.22.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c8601128eaef79b636152aea76ae6981b7c9fc81a618f584c15d78d42b310f1c", size = 14443220, upload-time = "2025-05-09T20:25:47.078Z" }, + { url = "https://files.pythonhosted.org/packages/8c/60/16d219b8868cc8e8e51a68519873bdb9f5f24af080b62e917a13fff9989b/onnxruntime-1.22.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6964a975731afc19dc3418fad8d4e08c48920144ff590149429a5ebe0d15fb3c", size = 16406377, upload-time = "2025-05-09T20:26:14.478Z" }, + { url = "https://files.pythonhosted.org/packages/36/b4/3f1c71ce1d3d21078a6a74c5483bfa2b07e41a8d2b8fb1e9993e6a26d8d3/onnxruntime-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:c0d534a43d1264d1273c2d4f00a5a588fa98d21117a3345b7104fa0bbcaadb9a", size = 12692233, upload-time = "2025-05-12T21:26:16.963Z" }, { url = "https://files.pythonhosted.org/packages/a9/65/5cb5018d5b0b7cba820d2c4a1d1b02d40df538d49138ba36a509457e4df6/onnxruntime-1.22.0-cp313-cp313-macosx_13_0_universal2.whl", hash = "sha256:fe7c051236aae16d8e2e9ffbfc1e115a0cc2450e873a9c4cb75c0cc96c1dae07", size = 34298715, upload-time = "2025-05-09T20:26:05.634Z" }, { url = "https://files.pythonhosted.org/packages/e1/89/1dfe1b368831d1256b90b95cb8d11da8ab769febd5c8833ec85ec1f79d21/onnxruntime-1.22.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6a6bbed10bc5e770c04d422893d3045b81acbbadc9fb759a2cd1ca00993da919", size = 14443266, upload-time = "2025-05-09T20:25:49.479Z" }, { url = "https://files.pythonhosted.org/packages/1e/70/342514ade3a33ad9dd505dcee96ff1f0e7be6d0e6e9c911fe0f1505abf42/onnxruntime-1.22.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9fe45ee3e756300fccfd8d61b91129a121d3d80e9d38e01f03ff1295badc32b8", size = 16406707, upload-time = "2025-05-09T20:26:17.454Z" }, @@ -867,6 +989,21 @@ version = "3.10.18" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/81/0b/fea456a3ffe74e70ba30e01ec183a9b26bec4d497f61dcfce1b601059c60/orjson-3.10.18.tar.gz", hash = "sha256:e8da3947d92123eda795b68228cafe2724815621fe35e8e320a9e9593a4bcd53", size = 5422810, upload-time = "2025-04-29T23:30:08.423Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/21/1a/67236da0916c1a192d5f4ccbe10ec495367a726996ceb7614eaa687112f2/orjson-3.10.18-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:50c15557afb7f6d63bc6d6348e0337a880a04eaa9cd7c9d569bcb4e760a24753", size = 249184, upload-time = "2025-04-29T23:28:53.612Z" }, + { url = "https://files.pythonhosted.org/packages/b3/bc/c7f1db3b1d094dc0c6c83ed16b161a16c214aaa77f311118a93f647b32dc/orjson-3.10.18-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:356b076f1662c9813d5fa56db7d63ccceef4c271b1fb3dd522aca291375fcf17", size = 133279, upload-time = "2025-04-29T23:28:55.055Z" }, + { url = "https://files.pythonhosted.org/packages/af/84/664657cd14cc11f0d81e80e64766c7ba5c9b7fc1ec304117878cc1b4659c/orjson-3.10.18-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:559eb40a70a7494cd5beab2d73657262a74a2c59aff2068fdba8f0424ec5b39d", size = 136799, upload-time = "2025-04-29T23:28:56.828Z" }, + { url = "https://files.pythonhosted.org/packages/9a/bb/f50039c5bb05a7ab024ed43ba25d0319e8722a0ac3babb0807e543349978/orjson-3.10.18-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f3c29eb9a81e2fbc6fd7ddcfba3e101ba92eaff455b8d602bf7511088bbc0eae", size = 132791, upload-time = "2025-04-29T23:28:58.751Z" }, + { url = "https://files.pythonhosted.org/packages/93/8c/ee74709fc072c3ee219784173ddfe46f699598a1723d9d49cbc78d66df65/orjson-3.10.18-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6612787e5b0756a171c7d81ba245ef63a3533a637c335aa7fcb8e665f4a0966f", size = 137059, upload-time = "2025-04-29T23:29:00.129Z" }, + { url = "https://files.pythonhosted.org/packages/6a/37/e6d3109ee004296c80426b5a62b47bcadd96a3deab7443e56507823588c5/orjson-3.10.18-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ac6bd7be0dcab5b702c9d43d25e70eb456dfd2e119d512447468f6405b4a69c", size = 138359, upload-time = "2025-04-29T23:29:01.704Z" }, + { url = "https://files.pythonhosted.org/packages/4f/5d/387dafae0e4691857c62bd02839a3bf3fa648eebd26185adfac58d09f207/orjson-3.10.18-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9f72f100cee8dde70100406d5c1abba515a7df926d4ed81e20a9730c062fe9ad", size = 142853, upload-time = "2025-04-29T23:29:03.576Z" }, + { url = "https://files.pythonhosted.org/packages/27/6f/875e8e282105350b9a5341c0222a13419758545ae32ad6e0fcf5f64d76aa/orjson-3.10.18-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9dca85398d6d093dd41dc0983cbf54ab8e6afd1c547b6b8a311643917fbf4e0c", size = 133131, upload-time = "2025-04-29T23:29:05.753Z" }, + { url = "https://files.pythonhosted.org/packages/48/b2/73a1f0b4790dcb1e5a45f058f4f5dcadc8a85d90137b50d6bbc6afd0ae50/orjson-3.10.18-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:22748de2a07fcc8781a70edb887abf801bb6142e6236123ff93d12d92db3d406", size = 134834, upload-time = "2025-04-29T23:29:07.35Z" }, + { url = "https://files.pythonhosted.org/packages/56/f5/7ed133a5525add9c14dbdf17d011dd82206ca6840811d32ac52a35935d19/orjson-3.10.18-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3a83c9954a4107b9acd10291b7f12a6b29e35e8d43a414799906ea10e75438e6", size = 413368, upload-time = "2025-04-29T23:29:09.301Z" }, + { url = "https://files.pythonhosted.org/packages/11/7c/439654221ed9c3324bbac7bdf94cf06a971206b7b62327f11a52544e4982/orjson-3.10.18-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:303565c67a6c7b1f194c94632a4a39918e067bd6176a48bec697393865ce4f06", size = 153359, upload-time = "2025-04-29T23:29:10.813Z" }, + { url = "https://files.pythonhosted.org/packages/48/e7/d58074fa0cc9dd29a8fa2a6c8d5deebdfd82c6cfef72b0e4277c4017563a/orjson-3.10.18-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:86314fdb5053a2f5a5d881f03fca0219bfdf832912aa88d18676a5175c6916b5", size = 137466, upload-time = "2025-04-29T23:29:12.26Z" }, + { url = "https://files.pythonhosted.org/packages/57/4d/fe17581cf81fb70dfcef44e966aa4003360e4194d15a3f38cbffe873333a/orjson-3.10.18-cp312-cp312-win32.whl", hash = "sha256:187ec33bbec58c76dbd4066340067d9ece6e10067bb0cc074a21ae3300caa84e", size = 142683, upload-time = "2025-04-29T23:29:13.865Z" }, + { url = "https://files.pythonhosted.org/packages/e6/22/469f62d25ab5f0f3aee256ea732e72dc3aab6d73bac777bd6277955bceef/orjson-3.10.18-cp312-cp312-win_amd64.whl", hash = "sha256:f9f94cf6d3f9cd720d641f8399e390e7411487e493962213390d1ae45c7814fc", size = 134754, upload-time = "2025-04-29T23:29:15.338Z" }, + { url = "https://files.pythonhosted.org/packages/10/b0/1040c447fac5b91bc1e9c004b69ee50abb0c1ffd0d24406e1350c58a7fcb/orjson-3.10.18-cp312-cp312-win_arm64.whl", hash = "sha256:3d600be83fe4514944500fa8c2a0a77099025ec6482e8087d7659e891f23058a", size = 131218, upload-time = "2025-04-29T23:29:17.324Z" }, { url = "https://files.pythonhosted.org/packages/04/f0/8aedb6574b68096f3be8f74c0b56d36fd94bcf47e6c7ed47a7bd1474aaa8/orjson-3.10.18-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:69c34b9441b863175cc6a01f2935de994025e773f814412030f269da4f7be147", size = 249087, upload-time = "2025-04-29T23:29:19.083Z" }, { url = "https://files.pythonhosted.org/packages/bc/f7/7118f965541aeac6844fcb18d6988e111ac0d349c9b80cda53583e758908/orjson-3.10.18-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:1ebeda919725f9dbdb269f59bc94f861afbe2a27dce5608cdba2d92772364d1c", size = 133273, upload-time = "2025-04-29T23:29:20.602Z" }, { url = "https://files.pythonhosted.org/packages/fb/d9/839637cc06eaf528dd8127b36004247bf56e064501f68df9ee6fd56a88ee/orjson-3.10.18-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5adf5f4eed520a4959d29ea80192fa626ab9a20b2ea13f8f6dc58644f6927103", size = 136779, upload-time = "2025-04-29T23:29:22.062Z" }, @@ -905,6 +1042,13 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/9f8431bacc2e19dca897724cd097b1bb224a6ad5433784a44b587c7c13af/pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", size = 4399213, upload-time = "2024-09-20T13:10:04.827Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/17/a3/fb2734118db0af37ea7433f57f722c0a56687e14b14690edff0cdb4b7e58/pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9", size = 12529893, upload-time = "2024-09-20T13:09:09.655Z" }, + { url = "https://files.pythonhosted.org/packages/e1/0c/ad295fd74bfac85358fd579e271cded3ac969de81f62dd0142c426b9da91/pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4", size = 11363475, upload-time = "2024-09-20T13:09:14.718Z" }, + { url = "https://files.pythonhosted.org/packages/c6/2a/4bba3f03f7d07207481fed47f5b35f556c7441acddc368ec43d6643c5777/pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3", size = 15188645, upload-time = "2024-09-20T19:02:03.88Z" }, + { url = "https://files.pythonhosted.org/packages/38/f8/d8fddee9ed0d0c0f4a2132c1dfcf0e3e53265055da8df952a53e7eaf178c/pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319", size = 12739445, upload-time = "2024-09-20T13:09:17.621Z" }, + { url = "https://files.pythonhosted.org/packages/20/e8/45a05d9c39d2cea61ab175dbe6a2de1d05b679e8de2011da4ee190d7e748/pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8", size = 16359235, upload-time = "2024-09-20T19:02:07.094Z" }, + { url = "https://files.pythonhosted.org/packages/1d/99/617d07a6a5e429ff90c90da64d428516605a1ec7d7bea494235e1c3882de/pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a", size = 14056756, upload-time = "2024-09-20T13:09:20.474Z" }, + { url = "https://files.pythonhosted.org/packages/29/d4/1244ab8edf173a10fd601f7e13b9566c1b525c4f365d6bee918e68381889/pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13", size = 11504248, upload-time = "2024-09-20T13:09:23.137Z" }, { url = "https://files.pythonhosted.org/packages/64/22/3b8f4e0ed70644e85cfdcd57454686b9057c6c38d2f74fe4b8bc2527214a/pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015", size = 12477643, upload-time = "2024-09-20T13:09:25.522Z" }, { url = "https://files.pythonhosted.org/packages/e4/93/b3f5d1838500e22c8d793625da672f3eec046b1a99257666c94446969282/pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28", size = 11281573, upload-time = "2024-09-20T13:09:28.012Z" }, { url = "https://files.pythonhosted.org/packages/f5/94/6c79b07f0e5aab1dcfa35a75f4817f5c4f677931d4234afcd75f0e6a66ca/pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0", size = 15196085, upload-time = "2024-09-20T19:02:10.451Z" }, @@ -939,6 +1083,17 @@ version = "11.2.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/af/cb/bb5c01fcd2a69335b86c22142b2bccfc3464087efb7fd382eee5ffc7fdf7/pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6", size = 47026707, upload-time = "2025-04-12T17:50:03.289Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/40/052610b15a1b8961f52537cc8326ca6a881408bc2bdad0d852edeb6ed33b/pillow-11.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:78afba22027b4accef10dbd5eed84425930ba41b3ea0a86fa8d20baaf19d807f", size = 3190185, upload-time = "2025-04-12T17:48:00.417Z" }, + { url = "https://files.pythonhosted.org/packages/e5/7e/b86dbd35a5f938632093dc40d1682874c33dcfe832558fc80ca56bfcb774/pillow-11.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78092232a4ab376a35d68c4e6d5e00dfd73454bd12b230420025fbe178ee3b0b", size = 3030306, upload-time = "2025-04-12T17:48:02.391Z" }, + { url = "https://files.pythonhosted.org/packages/a4/5c/467a161f9ed53e5eab51a42923c33051bf8d1a2af4626ac04f5166e58e0c/pillow-11.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a5f306095c6780c52e6bbb6109624b95c5b18e40aab1c3041da3e9e0cd3e2d", size = 4416121, upload-time = "2025-04-12T17:48:04.554Z" }, + { url = "https://files.pythonhosted.org/packages/62/73/972b7742e38ae0e2ac76ab137ca6005dcf877480da0d9d61d93b613065b4/pillow-11.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7b29dbd4281923a2bfe562acb734cee96bbb129e96e6972d315ed9f232bef4", size = 4501707, upload-time = "2025-04-12T17:48:06.831Z" }, + { url = "https://files.pythonhosted.org/packages/e4/3a/427e4cb0b9e177efbc1a84798ed20498c4f233abde003c06d2650a6d60cb/pillow-11.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e645b020f3209a0181a418bffe7b4a93171eef6c4ef6cc20980b30bebf17b7d", size = 4522921, upload-time = "2025-04-12T17:48:09.229Z" }, + { url = "https://files.pythonhosted.org/packages/fe/7c/d8b1330458e4d2f3f45d9508796d7caf0c0d3764c00c823d10f6f1a3b76d/pillow-11.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2dbea1012ccb784a65349f57bbc93730b96e85b42e9bf7b01ef40443db720b4", size = 4612523, upload-time = "2025-04-12T17:48:11.631Z" }, + { url = "https://files.pythonhosted.org/packages/b3/2f/65738384e0b1acf451de5a573d8153fe84103772d139e1e0bdf1596be2ea/pillow-11.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3104c57bbd72948d75f6a9389e6727d2ab6333c3617f0a89d72d4940aa0443", size = 4587836, upload-time = "2025-04-12T17:48:13.592Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c5/e795c9f2ddf3debb2dedd0df889f2fe4b053308bb59a3cc02a0cd144d641/pillow-11.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:598174aef4589af795f66f9caab87ba4ff860ce08cd5bb447c6fc553ffee603c", size = 4669390, upload-time = "2025-04-12T17:48:15.938Z" }, + { url = "https://files.pythonhosted.org/packages/96/ae/ca0099a3995976a9fce2f423166f7bff9b12244afdc7520f6ed38911539a/pillow-11.2.1-cp312-cp312-win32.whl", hash = "sha256:1d535df14716e7f8776b9e7fee118576d65572b4aad3ed639be9e4fa88a1cad3", size = 2332309, upload-time = "2025-04-12T17:48:17.885Z" }, + { url = "https://files.pythonhosted.org/packages/7c/18/24bff2ad716257fc03da964c5e8f05d9790a779a8895d6566e493ccf0189/pillow-11.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:14e33b28bf17c7a38eede290f77db7c664e4eb01f7869e37fa98a5aa95978941", size = 2676768, upload-time = "2025-04-12T17:48:19.655Z" }, + { url = "https://files.pythonhosted.org/packages/da/bb/e8d656c9543276517ee40184aaa39dcb41e683bca121022f9323ae11b39d/pillow-11.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:21e1470ac9e5739ff880c211fc3af01e3ae505859392bf65458c224d0bf283eb", size = 2415087, upload-time = "2025-04-12T17:48:21.991Z" }, { url = "https://files.pythonhosted.org/packages/36/9c/447528ee3776e7ab8897fe33697a7ff3f0475bb490c5ac1456a03dc57956/pillow-11.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fdec757fea0b793056419bca3e9932eb2b0ceec90ef4813ea4c1e072c389eb28", size = 3190098, upload-time = "2025-04-12T17:48:23.915Z" }, { url = "https://files.pythonhosted.org/packages/b5/09/29d5cd052f7566a63e5b506fac9c60526e9ecc553825551333e1e18a4858/pillow-11.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0e130705d568e2f43a17bcbe74d90958e8a16263868a12c3e0d9c8162690830", size = 3030166, upload-time = "2025-04-12T17:48:25.738Z" }, { url = "https://files.pythonhosted.org/packages/71/5d/446ee132ad35e7600652133f9c2840b4799bbd8e4adba881284860da0a36/pillow-11.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdb5e09068332578214cadd9c05e3d64d99e0e87591be22a324bdbc18925be0", size = 4408674, upload-time = "2025-04-12T17:48:27.908Z" }, @@ -978,6 +1133,22 @@ version = "0.3.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/07/c8/fdc6686a986feae3541ea23dcaa661bd93972d3940460646c6bb96e21c40/propcache-0.3.1.tar.gz", hash = "sha256:40d980c33765359098837527e18eddefc9a24cea5b45e078a7f3bb5b032c6ecf", size = 43651, upload-time = "2025-03-26T03:06:12.05Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/41/aa/ca78d9be314d1e15ff517b992bebbed3bdfef5b8919e85bf4940e57b6137/propcache-0.3.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f78eb8422acc93d7b69964012ad7048764bb45a54ba7a39bb9e146c72ea29723", size = 80430, upload-time = "2025-03-26T03:04:26.436Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d8/f0c17c44d1cda0ad1979af2e593ea290defdde9eaeb89b08abbe02a5e8e1/propcache-0.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:89498dd49c2f9a026ee057965cdf8192e5ae070ce7d7a7bd4b66a8e257d0c976", size = 46637, upload-time = "2025-03-26T03:04:27.932Z" }, + { url = "https://files.pythonhosted.org/packages/ae/bd/c1e37265910752e6e5e8a4c1605d0129e5b7933c3dc3cf1b9b48ed83b364/propcache-0.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:09400e98545c998d57d10035ff623266927cb784d13dd2b31fd33b8a5316b85b", size = 46123, upload-time = "2025-03-26T03:04:30.659Z" }, + { url = "https://files.pythonhosted.org/packages/d4/b0/911eda0865f90c0c7e9f0415d40a5bf681204da5fd7ca089361a64c16b28/propcache-0.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa8efd8c5adc5a2c9d3b952815ff8f7710cefdcaf5f2c36d26aff51aeca2f12f", size = 243031, upload-time = "2025-03-26T03:04:31.977Z" }, + { url = "https://files.pythonhosted.org/packages/0a/06/0da53397c76a74271621807265b6eb61fb011451b1ddebf43213df763669/propcache-0.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2fe5c910f6007e716a06d269608d307b4f36e7babee5f36533722660e8c4a70", size = 249100, upload-time = "2025-03-26T03:04:33.45Z" }, + { url = "https://files.pythonhosted.org/packages/f1/eb/13090e05bf6b963fc1653cdc922133ced467cb4b8dab53158db5a37aa21e/propcache-0.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a0ab8cf8cdd2194f8ff979a43ab43049b1df0b37aa64ab7eca04ac14429baeb7", size = 250170, upload-time = "2025-03-26T03:04:35.542Z" }, + { url = "https://files.pythonhosted.org/packages/3b/4c/f72c9e1022b3b043ec7dc475a0f405d4c3e10b9b1d378a7330fecf0652da/propcache-0.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:563f9d8c03ad645597b8d010ef4e9eab359faeb11a0a2ac9f7b4bc8c28ebef25", size = 245000, upload-time = "2025-03-26T03:04:37.501Z" }, + { url = "https://files.pythonhosted.org/packages/e8/fd/970ca0e22acc829f1adf5de3724085e778c1ad8a75bec010049502cb3a86/propcache-0.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb6e0faf8cb6b4beea5d6ed7b5a578254c6d7df54c36ccd3d8b3eb00d6770277", size = 230262, upload-time = "2025-03-26T03:04:39.532Z" }, + { url = "https://files.pythonhosted.org/packages/c4/42/817289120c6b9194a44f6c3e6b2c3277c5b70bbad39e7df648f177cc3634/propcache-0.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1c5c7ab7f2bb3f573d1cb921993006ba2d39e8621019dffb1c5bc94cdbae81e8", size = 236772, upload-time = "2025-03-26T03:04:41.109Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9c/3b3942b302badd589ad6b672da3ca7b660a6c2f505cafd058133ddc73918/propcache-0.3.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:050b571b2e96ec942898f8eb46ea4bfbb19bd5502424747e83badc2d4a99a44e", size = 231133, upload-time = "2025-03-26T03:04:42.544Z" }, + { url = "https://files.pythonhosted.org/packages/98/a1/75f6355f9ad039108ff000dfc2e19962c8dea0430da9a1428e7975cf24b2/propcache-0.3.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e1c4d24b804b3a87e9350f79e2371a705a188d292fd310e663483af6ee6718ee", size = 230741, upload-time = "2025-03-26T03:04:44.06Z" }, + { url = "https://files.pythonhosted.org/packages/67/0c/3e82563af77d1f8731132166da69fdfd95e71210e31f18edce08a1eb11ea/propcache-0.3.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e4fe2a6d5ce975c117a6bb1e8ccda772d1e7029c1cca1acd209f91d30fa72815", size = 244047, upload-time = "2025-03-26T03:04:45.983Z" }, + { url = "https://files.pythonhosted.org/packages/f7/50/9fb7cca01532a08c4d5186d7bb2da6c4c587825c0ae134b89b47c7d62628/propcache-0.3.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:feccd282de1f6322f56f6845bf1207a537227812f0a9bf5571df52bb418d79d5", size = 246467, upload-time = "2025-03-26T03:04:47.699Z" }, + { url = "https://files.pythonhosted.org/packages/a9/02/ccbcf3e1c604c16cc525309161d57412c23cf2351523aedbb280eb7c9094/propcache-0.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ec314cde7314d2dd0510c6787326bbffcbdc317ecee6b7401ce218b3099075a7", size = 241022, upload-time = "2025-03-26T03:04:49.195Z" }, + { url = "https://files.pythonhosted.org/packages/db/19/e777227545e09ca1e77a6e21274ae9ec45de0f589f0ce3eca2a41f366220/propcache-0.3.1-cp312-cp312-win32.whl", hash = "sha256:7d2d5a0028d920738372630870e7d9644ce437142197f8c827194fca404bf03b", size = 40647, upload-time = "2025-03-26T03:04:50.595Z" }, + { url = "https://files.pythonhosted.org/packages/24/bb/3b1b01da5dd04c77a204c84e538ff11f624e31431cfde7201d9110b092b1/propcache-0.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:88c423efef9d7a59dae0614eaed718449c09a5ac79a5f224a8b9664d603f04a3", size = 44784, upload-time = "2025-03-26T03:04:51.791Z" }, { url = "https://files.pythonhosted.org/packages/58/60/f645cc8b570f99be3cf46714170c2de4b4c9d6b827b912811eff1eb8a412/propcache-0.3.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f1528ec4374617a7a753f90f20e2f551121bb558fcb35926f99e3c42367164b8", size = 77865, upload-time = "2025-03-26T03:04:53.406Z" }, { url = "https://files.pythonhosted.org/packages/6f/d4/c1adbf3901537582e65cf90fd9c26fde1298fde5a2c593f987112c0d0798/propcache-0.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc1915ec523b3b494933b5424980831b636fe483d7d543f7afb7b3bf00f0c10f", size = 45452, upload-time = "2025-03-26T03:04:54.624Z" }, { url = "https://files.pythonhosted.org/packages/d1/b5/fe752b2e63f49f727c6c1c224175d21b7d1727ce1d4873ef1c24c9216830/propcache-0.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a110205022d077da24e60b3df8bcee73971be9575dec5573dd17ae5d81751111", size = 44800, upload-time = "2025-03-26T03:04:55.844Z" }, @@ -1060,6 +1231,20 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" }, + { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" }, + { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" }, + { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" }, + { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" }, + { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" }, + { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" }, + { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" }, + { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" }, + { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" }, + { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" }, + { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" }, { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, @@ -1263,8 +1448,8 @@ name = "speechrecognition" version = "3.14.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "audioop-lts" }, - { name = "standard-aifc" }, + { name = "audioop-lts", marker = "python_full_version >= '3.13'" }, + { name = "standard-aifc", marker = "python_full_version >= '3.13'" }, { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a9/7b/51d8b756aa1066b3f95bcbe3795f382f630ca9d2559ed808dada022141bf/speechrecognition-3.14.3.tar.gz", hash = "sha256:bdd2000a9897832b33095e33adfa48580787255706092e1346d1c6c36adae0a4", size = 32858109, upload-time = "2025-05-12T23:42:29.671Z" } @@ -1277,8 +1462,8 @@ name = "standard-aifc" version = "3.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "audioop-lts" }, - { name = "standard-chunk" }, + { name = "audioop-lts", marker = "python_full_version >= '3.13'" }, + { name = "standard-chunk", marker = "python_full_version >= '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c4/53/6050dc3dde1671eb3db592c13b55a8005e5040131f7509cef0215212cb84/standard_aifc-3.13.0.tar.gz", hash = "sha256:64e249c7cb4b3daf2fdba4e95721f811bde8bdfc43ad9f936589b7bb2fae2e43", size = 15240, upload-time = "2024-10-30T16:01:31.772Z" } wheels = [ @@ -1423,6 +1608,23 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/62/51/c0edba5219027f6eab262e139f73e2417b0f4efffa23bf562f6e18f76ca5/yarl-1.20.0.tar.gz", hash = "sha256:686d51e51ee5dfe62dec86e4866ee0e9ed66df700d55c828a615640adc885307", size = 185258, upload-time = "2025-04-17T00:45:14.661Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/e8/3efdcb83073df978bb5b1a9cc0360ce596680e6c3fac01f2a994ccbb8939/yarl-1.20.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e06b9f6cdd772f9b665e5ba8161968e11e403774114420737f7884b5bd7bdf6f", size = 147089, upload-time = "2025-04-17T00:42:39.602Z" }, + { url = "https://files.pythonhosted.org/packages/60/c3/9e776e98ea350f76f94dd80b408eaa54e5092643dbf65fd9babcffb60509/yarl-1.20.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b9ae2fbe54d859b3ade40290f60fe40e7f969d83d482e84d2c31b9bff03e359e", size = 97706, upload-time = "2025-04-17T00:42:41.469Z" }, + { url = "https://files.pythonhosted.org/packages/0c/5b/45cdfb64a3b855ce074ae607b9fc40bc82e7613b94e7612b030255c93a09/yarl-1.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d12b8945250d80c67688602c891237994d203d42427cb14e36d1a732eda480e", size = 95719, upload-time = "2025-04-17T00:42:43.666Z" }, + { url = "https://files.pythonhosted.org/packages/2d/4e/929633b249611eeed04e2f861a14ed001acca3ef9ec2a984a757b1515889/yarl-1.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:087e9731884621b162a3e06dc0d2d626e1542a617f65ba7cc7aeab279d55ad33", size = 343972, upload-time = "2025-04-17T00:42:45.391Z" }, + { url = "https://files.pythonhosted.org/packages/49/fd/047535d326c913f1a90407a3baf7ff535b10098611eaef2c527e32e81ca1/yarl-1.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:69df35468b66c1a6e6556248e6443ef0ec5f11a7a4428cf1f6281f1879220f58", size = 339639, upload-time = "2025-04-17T00:42:47.552Z" }, + { url = "https://files.pythonhosted.org/packages/48/2f/11566f1176a78f4bafb0937c0072410b1b0d3640b297944a6a7a556e1d0b/yarl-1.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b2992fe29002fd0d4cbaea9428b09af9b8686a9024c840b8a2b8f4ea4abc16f", size = 353745, upload-time = "2025-04-17T00:42:49.406Z" }, + { url = "https://files.pythonhosted.org/packages/26/17/07dfcf034d6ae8837b33988be66045dd52f878dfb1c4e8f80a7343f677be/yarl-1.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c903e0b42aab48abfbac668b5a9d7b6938e721a6341751331bcd7553de2dcae", size = 354178, upload-time = "2025-04-17T00:42:51.588Z" }, + { url = "https://files.pythonhosted.org/packages/15/45/212604d3142d84b4065d5f8cab6582ed3d78e4cc250568ef2a36fe1cf0a5/yarl-1.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf099e2432131093cc611623e0b0bcc399b8cddd9a91eded8bfb50402ec35018", size = 349219, upload-time = "2025-04-17T00:42:53.674Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e0/a10b30f294111c5f1c682461e9459935c17d467a760c21e1f7db400ff499/yarl-1.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a7f62f5dc70a6c763bec9ebf922be52aa22863d9496a9a30124d65b489ea672", size = 337266, upload-time = "2025-04-17T00:42:55.49Z" }, + { url = "https://files.pythonhosted.org/packages/33/a6/6efa1d85a675d25a46a167f9f3e80104cde317dfdf7f53f112ae6b16a60a/yarl-1.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:54ac15a8b60382b2bcefd9a289ee26dc0920cf59b05368c9b2b72450751c6eb8", size = 360873, upload-time = "2025-04-17T00:42:57.895Z" }, + { url = "https://files.pythonhosted.org/packages/77/67/c8ab718cb98dfa2ae9ba0f97bf3cbb7d45d37f13fe1fbad25ac92940954e/yarl-1.20.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:25b3bc0763a7aca16a0f1b5e8ef0f23829df11fb539a1b70476dcab28bd83da7", size = 360524, upload-time = "2025-04-17T00:43:00.094Z" }, + { url = "https://files.pythonhosted.org/packages/bd/e8/c3f18660cea1bc73d9f8a2b3ef423def8dadbbae6c4afabdb920b73e0ead/yarl-1.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b2586e36dc070fc8fad6270f93242124df68b379c3a251af534030a4a33ef594", size = 365370, upload-time = "2025-04-17T00:43:02.242Z" }, + { url = "https://files.pythonhosted.org/packages/c9/99/33f3b97b065e62ff2d52817155a89cfa030a1a9b43fee7843ef560ad9603/yarl-1.20.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:866349da9d8c5290cfefb7fcc47721e94de3f315433613e01b435473be63daa6", size = 373297, upload-time = "2025-04-17T00:43:04.189Z" }, + { url = "https://files.pythonhosted.org/packages/3d/89/7519e79e264a5f08653d2446b26d4724b01198a93a74d2e259291d538ab1/yarl-1.20.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:33bb660b390a0554d41f8ebec5cd4475502d84104b27e9b42f5321c5192bfcd1", size = 378771, upload-time = "2025-04-17T00:43:06.609Z" }, + { url = "https://files.pythonhosted.org/packages/3a/58/6c460bbb884abd2917c3eef6f663a4a873f8dc6f498561fc0ad92231c113/yarl-1.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:737e9f171e5a07031cbee5e9180f6ce21a6c599b9d4b2c24d35df20a52fabf4b", size = 375000, upload-time = "2025-04-17T00:43:09.01Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2a/dd7ed1aa23fea996834278d7ff178f215b24324ee527df53d45e34d21d28/yarl-1.20.0-cp312-cp312-win32.whl", hash = "sha256:839de4c574169b6598d47ad61534e6981979ca2c820ccb77bf70f4311dd2cc64", size = 86355, upload-time = "2025-04-17T00:43:11.311Z" }, + { url = "https://files.pythonhosted.org/packages/ca/c6/333fe0338305c0ac1c16d5aa7cc4841208d3252bbe62172e0051006b5445/yarl-1.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:3d7dbbe44b443b0c4aa0971cb07dcb2c2060e4a9bf8d1301140a33a93c98e18c", size = 92904, upload-time = "2025-04-17T00:43:13.087Z" }, { url = "https://files.pythonhosted.org/packages/0f/6f/514c9bff2900c22a4f10e06297714dbaf98707143b37ff0bcba65a956221/yarl-1.20.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2137810a20b933b1b1b7e5cf06a64c3ed3b4747b0e5d79c9447c00db0e2f752f", size = 145030, upload-time = "2025-04-17T00:43:15.083Z" }, { url = "https://files.pythonhosted.org/packages/4e/9d/f88da3fa319b8c9c813389bfb3463e8d777c62654c7168e580a13fadff05/yarl-1.20.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:447c5eadd750db8389804030d15f43d30435ed47af1313303ed82a62388176d3", size = 96894, upload-time = "2025-04-17T00:43:17.372Z" }, { url = "https://files.pythonhosted.org/packages/cd/57/92e83538580a6968b2451d6c89c5579938a7309d4785748e8ad42ddafdce/yarl-1.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:42fbe577272c203528d402eec8bf4b2d14fd49ecfec92272334270b850e9cd7d", size = 94457, upload-time = "2025-04-17T00:43:19.431Z" },