From 547d4e6ab1325659a78a3fc18a64936398ef4277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Hells=C3=A9n?= Date: Thu, 24 Jul 2025 01:27:31 +0200 Subject: [PATCH] Debloat HTML --- accounts/migrations/0001_initial.py | 89 +++- accounts/views.py | 16 +- config/settings.py | 3 + config/urls.py | 6 +- pyproject.toml | 7 + templates/accounts/login.html | 97 ++--- templates/accounts/profile.html | 151 ++----- templates/accounts/signup.html | 134 ++---- templates/base.html | 160 ++----- templates/navbar.html | 21 + templates/twitch/campaign_detail.html | 235 ++++------- templates/twitch/campaign_list.html | 394 +++++------------- templates/twitch/dashboard.html | 236 +++-------- templates/twitch/game_detail.html | 226 +++------- templates/twitch/game_list.html | 81 +--- .../commands/import_drop_campaign.py | 4 +- twitch/models.py | 20 +- uv.lock | 268 ++++++++++++ 18 files changed, 869 insertions(+), 1279 deletions(-) create mode 100644 templates/navbar.html diff --git a/accounts/migrations/0001_initial.py b/accounts/migrations/0001_initial.py index 8009a93..84f8d52 100644 --- a/accounts/migrations/0001_initial.py +++ b/accounts/migrations/0001_initial.py @@ -1,4 +1,5 @@ # Generated by Django 5.2.4 on 2025-07-21 00:54 +from __future__ import annotations import django.contrib.auth.models import django.contrib.auth.validators @@ -7,38 +8,86 @@ from django.db import migrations, models class Migration(migrations.Migration): - initial = True dependencies = [ - ('auth', '0012_alter_user_first_name_max_length'), + ("auth", "0012_alter_user_first_name_max_length"), ] operations = [ migrations.CreateModel( - name='User', + name="User", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('password', models.CharField(max_length=128, verbose_name='password')), - ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), - ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), - ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), - ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), - ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), - ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), - ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), - ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), - ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), - ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), - ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), + ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("password", models.CharField(max_length=128, verbose_name="password")), + ("last_login", models.DateTimeField(blank=True, null=True, verbose_name="last login")), + ( + "is_superuser", + models.BooleanField( + default=False, + help_text="Designates that this user has all permissions without explicitly assigning them.", + verbose_name="superuser status", + ), + ), + ( + "username", + models.CharField( + error_messages={"unique": "A user with that username already exists."}, + help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.", + max_length=150, + unique=True, + validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], + verbose_name="username", + ), + ), + ("first_name", models.CharField(blank=True, max_length=150, verbose_name="first name")), + ("last_name", models.CharField(blank=True, max_length=150, verbose_name="last name")), + ("email", models.EmailField(blank=True, max_length=254, verbose_name="email address")), + ( + "is_staff", + models.BooleanField( + default=False, help_text="Designates whether the user can log into this admin site.", verbose_name="staff status" + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", + verbose_name="active", + ), + ), + ("date_joined", models.DateTimeField(default=django.utils.timezone.now, verbose_name="date joined")), + ( + "groups", + models.ManyToManyField( + blank=True, + help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", + related_name="user_set", + related_query_name="user", + to="auth.group", + verbose_name="groups", + ), + ), + ( + "user_permissions", + models.ManyToManyField( + blank=True, + help_text="Specific permissions for this user.", + related_name="user_set", + related_query_name="user", + to="auth.permission", + verbose_name="user permissions", + ), + ), ], options={ - 'verbose_name': 'User', - 'verbose_name_plural': 'Users', - 'db_table': 'auth_user', + "verbose_name": "User", + "verbose_name_plural": "Users", + "db_table": "auth_user", }, managers=[ - ('objects', django.contrib.auth.models.UserManager()), + ("objects", django.contrib.auth.models.UserManager()), ], ), ] diff --git a/accounts/views.py b/accounts/views.py index 5be3c81..4a4f890 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, ClassVar from django.contrib.auth import login from django.contrib.auth.decorators import login_required @@ -36,6 +36,20 @@ class CustomLogoutView(LogoutView): """Custom logout view.""" next_page = reverse_lazy("twitch:dashboard") + http_method_names: ClassVar[list[str]] = ["get", "post", "options"] # pyright: ignore[reportIncompatibleVariableOverride] + + def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: + """Allow GET requests for logout. + + Args: + request: The HTTP request object. + *args: Additional positional arguments. + **kwargs: Additional keyword arguments. + + Returns: + HttpResponse: Response after logout. + """ + return self.post(request, *args, **kwargs) class SignUpView(CreateView): diff --git a/config/settings.py b/config/settings.py index 3bf42b9..d939f7c 100644 --- a/config/settings.py +++ b/config/settings.py @@ -189,10 +189,13 @@ TESTING: bool = "test" in sys.argv or "PYTEST_VERSION" in os.environ if not TESTING: DEBUG_TOOLBAR_CONFIG: dict[str, str] = {"ROOT_TAG_EXTRA_ATTRS": "hx-preserve"} INSTALLED_APPS = [ # pyright: ignore[reportConstantRedefinition] + "django_watchfiles", *INSTALLED_APPS, "debug_toolbar", + "django_browser_reload", ] MIDDLEWARE = [ # pyright: ignore[reportConstantRedefinition] "debug_toolbar.middleware.DebugToolbarMiddleware", *MIDDLEWARE, + "django_browser_reload.middleware.BrowserReloadMiddleware", ] diff --git a/config/urls.py b/config/urls.py index d3adb5a..0d8dde6 100644 --- a/config/urls.py +++ b/config/urls.py @@ -17,4 +17,8 @@ urlpatterns: list[URLResolver] = [ ] if not settings.TESTING: - urlpatterns = [*urlpatterns, *debug_toolbar_urls()] + urlpatterns = [ + *urlpatterns, + *debug_toolbar_urls(), + path("__reload__/", include("django_browser_reload.urls")), + ] diff --git a/pyproject.toml b/pyproject.toml index f208b20..0e7ceeb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,10 @@ readme = "README.md" requires-python = ">=3.13" dependencies = [ "django>=5.2.4", + "django-browser-reload>=1.18.0", "django-debug-toolbar>=5.2.0", + "django-watchfiles>=1.1.0", + "djlint>=1.36.4", "platformdirs>=4.3.8", "python-dotenv>=1.1.1", ] @@ -76,3 +79,7 @@ line-length = 140 "S105", ] "**/migrations/**" = ["RUF012"] + +[tool.djlint] +profile = "django" +ignore = "H021" diff --git a/templates/accounts/login.html b/templates/accounts/login.html index 2d6db3d..adace53 100644 --- a/templates/accounts/login.html +++ b/templates/accounts/login.html @@ -1,66 +1,35 @@ -{% extends 'base.html' %} - -{% block title %}Login{% endblock %} - +{% extends "base.html" %} +{% block title %} + Login +{% endblock title %} {% block content %} -
-
-
-
-
-

Login

-
-
- {% if form.errors %} -
-
    - {% for field, errors in form.errors.items %} - {% for error in errors %} -
  • {{ error }}
  • - {% endfor %} - {% endfor %} -
-
- {% endif %} - -
- {% csrf_token %} -
- -
- - -
-
- -
- -
- - -
-
- -
- -
-
-
- -
-
-
-
- - -{% endblock %} \ No newline at end of file + +{% endblock content %} diff --git a/templates/accounts/profile.html b/templates/accounts/profile.html index 5d05c3f..1bce3ed 100644 --- a/templates/accounts/profile.html +++ b/templates/accounts/profile.html @@ -1,124 +1,29 @@ -{% extends 'base.html' %} - -{% block title %}Profile{% endblock %} - +{% extends "base.html" %} +{% block title %} + {{ user.username }} +{% endblock title %} {% block content %} -
-
-
-
-
-

User Profile

-
-
-
-
-
- -
-
{{ user.username }}
-

Member since {{ user.date_joined|date:"F Y" }}

-
-
-
Account Information
- - - - - - - - - - - - - - - - - - - - - -
Username:{{ user.username }}
Email:{{ user.email|default:"Not provided" }}
Date Joined:{{ user.date_joined|date:"F d, Y" }}
Last Login:{{ user.last_login|date:"F d, Y H:i"|default:"Never" }}
Account Status: - {% if user.is_active %} - Active - {% else %} - Inactive - {% endif %} - {% if user.is_staff %} - Staff - {% endif %} - {% if user.is_superuser %} - Superuser - {% endif %} -
-
-
-
- -
- - -
-
-
Quick Stats
-
-
-
-
-
-

-

-

Campaigns Tracked

-
-
-
-
-

-

-

Games Followed

-
-
-
-
-
-
-
-
- - -{% endblock %} \ No newline at end of file +

{{ user.username }}

+

Joined {{ user.date_joined|date:"F d, Y" }}

+ + + + + + + + + + + + + +
+ Date Joined: + {{ user.date_joined|date:"F d, Y" }}
+ Last Login: + {{ user.last_login|date:"F d, Y H:i"|default:"Never" }}
+ Email: + {{ user.email|default:"Not provided" }}
+ Logout +{% endblock content %} diff --git a/templates/accounts/signup.html b/templates/accounts/signup.html index 49c9153..1acba9d 100644 --- a/templates/accounts/signup.html +++ b/templates/accounts/signup.html @@ -1,96 +1,40 @@ -{% extends 'base.html' %} - -{% block title %}Sign Up{% endblock %} - +{% extends "base.html" %} +{% block title %} + Sign Up +{% endblock title %} {% block content %} -
-
-
-
-
-

Sign Up

-
-
- {% if form.errors %} -
-
    - {% for field, errors in form.errors.items %} - {% for error in errors %} -
  • {{ error }}
  • - {% endfor %} - {% endfor %} -
-
- {% endif %} - -
- {% csrf_token %} -
- -
- - -
- {% if form.username.help_text %} -
{{ form.username.help_text }}
- {% endif %} -
- -
- -
- - -
- {% if form.password1.help_text %} -
{{ form.password1.help_text }}
- {% endif %} -
- -
- -
- - -
- {% if form.password2.help_text %} -
{{ form.password2.help_text }}
- {% endif %} -
- -
- -
-
-
- -
-
-
-
- - -{% endblock %} \ No newline at end of file +

Sign Up

+ {% if form.errors %} + + {% endif %} +
+ {% csrf_token %} + + + {% if form.username.help_text %}{{ form.username.help_text }}{% endif %} + + + {% if form.password1.help_text %}{{ form.password1.help_text }}{% endif %} + + + {% if form.password2.help_text %}{{ form.password2.help_text }}{% endif %} + +
+

+ Already have an account? Login here +

+{% endblock content %} diff --git a/templates/base.html b/templates/base.html index ab84c0c..9375550 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,135 +1,41 @@ - - - - - {% block title %}ttvdrops{% endblock %} - - - - - - {% block extra_css %}{% endblock %} - - - - - -
- {% block content %}{% endblock %} -
- - - - {% block extra_js %}{% endblock %} - - - \ No newline at end of file + + diff --git a/templates/navbar.html b/templates/navbar.html new file mode 100644 index 0000000..6d45b7f --- /dev/null +++ b/templates/navbar.html @@ -0,0 +1,21 @@ + diff --git a/templates/twitch/campaign_detail.html b/templates/twitch/campaign_detail.html index 3b2eaae..f1c400f 100644 --- a/templates/twitch/campaign_detail.html +++ b/templates/twitch/campaign_detail.html @@ -1,152 +1,95 @@ {% extends "base.html" %} - -{% block title %}{{ campaign.clean_name }} - Twitch Drops Tracker{% endblock %} - +{% load static %} +{% block title %} + {{ campaign.clean_name }} +{% endblock title %} {% block content %} -
-
- -
-
- -
-
-

{{ campaign.clean_name }}

-
- - {{ campaign.game.display_name }} - - {% if campaign.start_at <= now and campaign.end_at >= now %} - {% if campaign.status == 'ACTIVE' %} - Active - {% else %} - {{ campaign.status|title }} - {% endif %} - {% elif campaign.start_at > now %} - Upcoming - {% else %} - Expired - {% endif %} -
-

{{ campaign.description }}

-
-
-

Start Date: - {{ campaign.start_at|date:"F j, Y, g:i a" }}

-
-
-

End Date: - {{ campaign.end_at|date:"F j, Y, g:i a" }}

-
-
- {% if campaign.details_url %} +

+ {{ campaign.game.display_name }} - {{ campaign.clean_name }} +

+

+ {# TODO: Link to organization #} + {{ campaign.owner.name }} +

+ {% if campaign.image_url %} + {{ campaign.name }} + {% endif %} +

{{ campaign.description }}

+

+ Start: + {{ campaign.start_at }} +

+

+ End: + {{ campaign.end_at }} +

+ {% if campaign.details_url %} + {# TODO: Archive this URL automatically #}

- - Official Details - + Official Details

- {% endif %} - {% if campaign.account_link_url %} + {% endif %} + {% if campaign.account_link_url %} + {# TODO: Archive this URL automatically #}

- - Connect Account - + Connect Account

- {% endif %} -
-
- {% if campaign.image_url %} - {{ campaign.name }} - {% else %} -
- -

No image available

-
- {% endif %} -
-
-
Campaign Info
-
-
-

Owner: {{ campaign.owner.name }}

-

Status: {{ campaign.status }}

-

Account Connected: {% if campaign.is_account_connected %}Yes{% else %}No{% endif %}

-
-
-
-
- -
-
-
-
-
Rewards
-
-
- {% if drops %} -
- {% for drop in drops %} -
-
-
-
-

{{ drop.name }}

-

- {{ drop.required_minutes_watched }} minutes - watched - {% if drop.required_subs > 0 %} - {{ drop.required_subs }} subscriptions - required - {% endif %} -

-

- - Available: - {{ drop.start_at|date:"M d, Y" }} - {{ drop.end_at|date:"M d, Y" }} - -

-
-
- 0 / {{ drop.required_minutes_watched }} minutes -
-
-
-
- {% for benefit in drop.benefits.all %} -
- {% if benefit.image_asset_url %} - {{ benefit.name }} - {% else %} -
- -
- {% endif %} -

{{ benefit.name }}

-
- {% endfor %} -
-
-
-
- {% endfor %} -
- {% else %} -
- No drops found for this campaign. -
- {% endif %} -
-
-
-
-{% endblock %} \ No newline at end of file + {% endif %} +
Campaign Info
+ {% if user.is_staff %} +

+ {% if campaign.is_account_connected %} + Connected + {% else %} + Not Connected + {% endif %} +

+ {% endif %} + {% if drops %} + + + + + + + + {% for drop in drops %} + + + + + + + {% endfor %} + {% if not drops %} + + + + {% endif %} +
ImageNameRequirementsAvailability
+ {% for benefit in drop.benefits.all %} + {% if benefit.image_asset_url %} + {{ benefit.name }} + {% else %} + No Image Available + {% endif %} + {% endfor %} + {{ drop.name }} + {{ drop.required_minutes_watched }} minutes watched + {% if drop.required_subs > 0 %}and {{ drop.required_subs }} subscriptions required{% endif %} + {{ drop.start_at }} - {{ drop.end_at }}
No drops found for this campaign.
+ {% else %} +

No drops available for this campaign.

+ {% endif %} +{% endblock content %} diff --git a/templates/twitch/campaign_list.html b/templates/twitch/campaign_list.html index 31f4d42..c84f914 100644 --- a/templates/twitch/campaign_list.html +++ b/templates/twitch/campaign_list.html @@ -1,286 +1,114 @@ {% extends "base.html" %} - -{% block title %}Drop Campaigns - Twitch Drops Tracker{% endblock %} - +{% load static %} +{% block title %} + Drop Campaigns - Twitch Drops Tracker +{% endblock title %} {% block content %} -
-
-

Drop Campaigns

-

Browse all Twitch drop campaigns.

-
-
- -
-
-
-
-
Filter Campaigns
-
-
-
-
- - -
-
- - -
-
- - -
-
- -
-
-
-
-
-
- -
-
-
-
-
Campaign List
-
-
- {% if campaigns %} -
- {% for campaign in campaigns %} -
- {% if campaign.start_at <= now and campaign.end_at >= now %} - {% if campaign.status == 'ACTIVE' %} -
- {% else %} -
- {% endif %} - {% elif campaign.start_at > now %} -
- {% else %} -
- {% endif %} -
-
- {% if campaign.image_url %} - {{ campaign.name }} - {% else %} -
- -
- {% endif %} -
-
-
-
- {{ campaign.clean_name }}
-
-

- - {{ campaign.game.display_name }} - -

-

- {{ campaign.start_at|date:"M d, Y" }} - - {{ campaign.end_at|date:"M d, Y" }} -

-
-
-
- {% if campaign.start_at <= now and campaign.end_at >= now %} - {% if campaign.status == 'ACTIVE' %} - Active - {% else %} - {{ campaign.status|title }} - {% endif %} - {% elif campaign.start_at > now %} - Upcoming - {% else %} - Expired - {% endif %} - Details -
-
-
- {% endfor %} -
- {% else %} -
- No campaigns found with the current filters. -
- {% endif %} -
-
-
-
- - - {% if is_paginated %} -
-
- -
-
- -
-
- - Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ page_obj.paginator.count }} - campaigns - (Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}) - -
-
+

Drop Campaigns

+
+ + + + + +
+
Campaign List
+ {% if campaigns %} + {% for campaign in campaigns %} + {% if campaign.image_url %} + {{ campaign.name }} + {% else %} + No Image Available {% endif %} - -
-
-
-
-
Quick Stats
-
-
-
-
-
-

- {% if is_paginated %} - {{ page_obj.paginator.count }} - {% else %} - {{ campaigns|length }} - {% endif %} -

-

Total Campaigns

-
-
-
-
-

{{ now|date:"F j, Y" }}

-

Current Date

-
-
- -
-
-
-
-
- {% endblock %} \ No newline at end of file +
{{ campaign.clean_name }}
+

+ {{ campaign.game.display_name }} +

+

+ {{ campaign.start_at|date:"M d, Y" }} + - {{ campaign.end_at|date:"M d, Y" }} +

+ {% if campaign.start_at <= now and campaign.end_at >= now %} + {% if campaign.status == 'ACTIVE' %}Active{% endif %} + {% elif campaign.start_at > now %} + Upcoming + {% else %} + Expired + {% endif %} + Details + {% endfor %} + {% else %} + No campaigns found with the current filters. + {% endif %} + + {% if is_paginated %} + + + Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ page_obj.paginator.count }} + campaigns + (Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}) + + {% endif %} +{% endblock content %} diff --git a/templates/twitch/dashboard.html b/templates/twitch/dashboard.html index ac94258..b740b67 100644 --- a/templates/twitch/dashboard.html +++ b/templates/twitch/dashboard.html @@ -1,192 +1,50 @@ {% extends "base.html" %} - -{% block title %}Dashboard - Twitch Drops Tracker{% endblock %} - +{% load static %} +{% block title %} + Dashboard +{% endblock title %} {% block content %} -
-
-

Dashboard

-

Track your active Twitch drop campaigns and progress.

-
-
- - - -
-
-
-
-
Active Campaigns
-
-
- {% if campaigns_by_org_game %} - {% for org_id, org_data in campaigns_by_org_game.items %} -
-
{{ org_data.name }}
- - {% for game_id, game_data in org_data.games.items %} -
-
- - {{ game_data.name }} - -
- -
- {% for campaign in game_data.campaigns %} -
-
-
-
- {% if campaign.image_url %} - {{ campaign.name }} - {% else %} -
- -
- {% endif %} -
-
-
-
- {{ campaign.clean_name }}
-
-
- Active - Ends - {{ campaign.end_at|date:"M d" }} -
- -
-
-
-
- {% endfor %} -
-
+ {% if campaigns_by_org_game %} + {% for org_id, org_data in campaigns_by_org_game.items %} +

{{ org_data.name }}

+ {% for game_id, game_data in org_data.games.items %} +

+ {{ game_data.name }} +

+

{{ game_data.campaigns.0.description|default:"No description available."|linebreaksbr }}

+ + + + + + + {% for campaign in game_data.campaigns %} + + + + + {% endfor %} - - {% endfor %} - {% else %} -
- No active campaigns at the moment. -
- {% endif %} - - - - - -
-
-
-
-
Quick Stats
-
-
-
-
-
-

{{ active_campaigns.count }}

-

Active Campaigns

-
-
-
-
-

{{ campaigns_by_org_game|length }}

-

Organizations

-
-
-
-
-

{{ now|date:"M j" }}

-

Current Date

-
-
- -
-
-
-
-
-{% endblock %} \ No newline at end of file +
ImageCampaignEnds In
+ {% if campaign.image_url %} + {{ campaign.name }} + {% else %} + No Image Available + {% endif %} + + {{ campaign.clean_name }} + + Ends in {{ campaign.end_at|timeuntil }} +
+ {% endfor %} + {% endfor %} + {% else %} + No active campaigns at the moment. + {% endif %} +{% endblock content %} diff --git a/templates/twitch/game_detail.html b/templates/twitch/game_detail.html index 65fef08..ebc5c7b 100644 --- a/templates/twitch/game_detail.html +++ b/templates/twitch/game_detail.html @@ -1,169 +1,61 @@ {% extends "base.html" %} - -{% block title %}{{ game.display_name }} - Twitch Drops Tracker{% endblock %} - +{% block title %} + {{ game.display_name }} +{% endblock title %} {% block content %} -
-
- -

- {{ game.display_name }} -

-

View all drop campaigns for {{ game.display_name }}.

-
-
- -{% if active_campaigns %} -
-
-
-
-
Active Campaigns
-
-
-
- - - - - - - - - - - {% for campaign in active_campaigns %} - - - - - - - {% endfor %} - -
CampaignOrganizationTime RemainingActions
{{ campaign.clean_name }}{{ campaign.owner.name }} - - Ends in {{ campaign.end_at|timeuntil }} - - - - View Details - -
-
-
-
-
-
-{% endif %} - -{% if upcoming_campaigns %} -
-
-
-
-
Upcoming Campaigns
-
-
-
- - - - - - - - - - - {% for campaign in upcoming_campaigns %} - - - - - - - {% endfor %} - -
CampaignOrganizationStarts InActions
{{ campaign.clean_name }}{{ campaign.owner.name }} - - Starts in {{ campaign.start_at|timeuntil }} - - - - View Details - -
-
-
-
-
-
-{% endif %} - -{% if expired_campaigns %} -
-
-
-
-
Past Campaigns
-
-
-
- - - - - - - - - - - {% for campaign in expired_campaigns %} - - - - - - - {% endfor %} - -
CampaignOrganizationEndedActions
{{ campaign.clean_name }}{{ campaign.owner.name }} - - {{ campaign.end_at|timesince }} ago - - - - View Details - -
-
-
-
-
-
-{% endif %} - -{% if not active_campaigns and not upcoming_campaigns and not expired_campaigns %} -
-
-
- No campaigns found for this game. -
-
-
-{% endif %} - -{% endblock %} \ No newline at end of file +

{{ game.display_name }}

+ {% if active_campaigns %} +
Active Campaigns
+ + + {% for campaign in active_campaigns %} + + + + + {% endfor %} + +
+ {{ campaign.clean_name }} + + Ends in {{ campaign.end_at|timeuntil }} +
+ {% endif %} + {% if upcoming_campaigns %} +
Upcoming Campaigns
+ + + {% for campaign in upcoming_campaigns %} + + + + + {% endfor %} + +
+ {{ campaign.clean_name }} + + Starts in {{ campaign.start_at|timeuntil }} +
+ {% endif %} + {% if expired_campaigns %} +
Past Campaigns
+ + + {% for campaign in expired_campaigns %} + + + + + {% endfor %} + +
+ {{ campaign.clean_name }} + + {{ campaign.end_at|timesince }} ago +
+ {% endif %} + {% if not active_campaigns and not upcoming_campaigns and not expired_campaigns %} + No campaigns found for this game. + {% endif %} +{% endblock content %} diff --git a/templates/twitch/game_list.html b/templates/twitch/game_list.html index 4f94ad1..b089fed 100644 --- a/templates/twitch/game_list.html +++ b/templates/twitch/game_list.html @@ -1,60 +1,25 @@ {% extends "base.html" %} - -{% block title %}Games by Organization - Twitch Drops Tracker{% endblock %} - +{% block title %} + Games by Organization - Twitch Drops Tracker +{% endblock title %} {% block content %} -
-
-

Games by Organization

-

Browse all games with Twitch drop campaigns, grouped by organization.

-
-
- -{% if games_by_org %} -{% for organization, games in games_by_org.items %} -
-
-

- {{ organization.name }} -

-
-
-
- {% for item in games %} -
-
-
-
- - {{ item.game.display_name }} - -
-
- - {{ item.campaign_count }} Campaigns - - {% if item.active_count > 0 %} - - {{ item.active_count }} Active - - {% endif %} -
-
- -
-
- {% endfor %} -
-
-
-{% endfor %} -{% else %} -
- No games found. -
-{% endif %} -{% endblock %} \ No newline at end of file +

Games by Organization

+ {% if games_by_org %} + {% for organization, games in games_by_org.items %} +

{{ organization.name }}

+ + + {% for item in games %} + + + + {% endfor %} + +
+ {{ item.game.display_name }} +
+ {% endfor %} + {% else %} + No games found. + {% endif %} +{% endblock content %} diff --git a/twitch/management/commands/import_drop_campaign.py b/twitch/management/commands/import_drop_campaign.py index 6d2d114..e8ebaf0 100644 --- a/twitch/management/commands/import_drop_campaign.py +++ b/twitch/management/commands/import_drop_campaign.py @@ -60,7 +60,7 @@ class Command(BaseCommand): help="Delay in seconds between retries for database operations (default: 0.5)", ) - def handle(self, **options) -> None: # noqa: ANN003 + def handle(self, **options) -> None: """Execute the command. Args: @@ -268,7 +268,7 @@ class Command(BaseCommand): id=campaign_data["id"], defaults={ "name": campaign_data["name"], - "description": campaign_data["description"], + "description": campaign_data["description"].replace("\\n", "\n"), "details_url": campaign_data.get("detailsURL", ""), "account_link_url": campaign_data.get("accountLinkURL", ""), "image_url": campaign_data.get("imageURL", ""), diff --git a/twitch/models.py b/twitch/models.py index d0b7878..a8c6e94 100644 --- a/twitch/models.py +++ b/twitch/models.py @@ -74,17 +74,31 @@ class DropCampaign(models.Model): Examples: "Ravendawn - July 2" -> "July 2" "Party Animals Twitch Drop" -> "Twitch Drop" + "Skull & Bones - Closed Beta" -> "Closed Beta" (& is replaced with "and") """ if not self.game or not self.game.display_name: return self.name - game_name = self.game.display_name + # Try different variations of the game name + game_variations = [self.game.display_name] + + # Add & to "and" conversion + if "&" in self.game.display_name: + game_variations.append(self.game.display_name.replace("&", "and")) + + # Add "and" to & conversion + if "and" in self.game.display_name: + game_variations.append(self.game.display_name.replace("and", "&")) + + # Check each variation + for game_name in game_variations: + if not self.name.startswith(game_name): + continue - # Remove game name if it's at the beginning of the campaign name - if self.name.startswith(game_name): # Check if it's followed by a separator like " - " if self.name[len(game_name) :].startswith(" - "): return self.name[len(game_name) + 3 :].strip() + # Or just remove the game name if it's followed by a space if len(self.name) > len(game_name) and self.name[len(game_name)] == " ": return self.name[len(game_name) + 1 :].strip() diff --git a/uv.lock b/uv.lock index ae6ef05..740bb82 100644 --- a/uv.lock +++ b/uv.lock @@ -2,6 +2,19 @@ version = 1 revision = 2 requires-python = ">=3.13" +[[package]] +name = "anyio" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "sniffio" }, +] +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 = [ + { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload-time = "2025-03-17T00:02:52.713Z" }, +] + [[package]] name = "asgiref" version = "3.9.1" @@ -11,6 +24,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7c/3c/0464dcada90d5da0e71018c04a140ad6349558afb30b3051b4264cc5b965/asgiref-3.9.1-py3-none-any.whl", hash = "sha256:f3bba7092a48005b5f5bacd747d36ee4a5a61f4a269a6df590b43144355ebd2c", size = 23790, upload-time = "2025-07-08T09:07:41.548Z" }, ] +[[package]] +name = "click" +version = "8.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -20,6 +45,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] +[[package]] +name = "cssbeautifier" +version = "1.15.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "editorconfig" }, + { name = "jsbeautifier" }, + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f7/01/fdf41c1e5f93d359681976ba10410a04b299d248e28ecce1d4e88588dde4/cssbeautifier-1.15.4.tar.gz", hash = "sha256:9bb08dc3f64c101a01677f128acf01905914cf406baf87434dcde05b74c0acf5", size = 25376, upload-time = "2025-02-27T17:53:51.341Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/51/ef6c5628e46092f0a54c7cee69acc827adc6b6aab57b55d344fefbdf28f1/cssbeautifier-1.15.4-py3-none-any.whl", hash = "sha256:78c84d5e5378df7d08622bbd0477a1abdbd209680e95480bf22f12d5701efc98", size = 123667, upload-time = "2025-02-27T17:53:43.594Z" }, +] + [[package]] name = "django" version = "5.2.4" @@ -34,6 +73,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/14/ae/706965237a672434c8b520e89a818e8b047af94e9beb342d0bee405c26c7/django-5.2.4-py3-none-any.whl", hash = "sha256:60c35bd96201b10c6e7a78121bd0da51084733efa303cc19ead021ab179cef5e", size = 8302187, upload-time = "2025-07-02T18:47:35.373Z" }, ] +[[package]] +name = "django-browser-reload" +version = "1.18.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asgiref" }, + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3b/41/84eaa4f2b7f764e56e01c4ee49aa12bdea30ae50fd0d3ef7c2690b0c4ec2/django_browser_reload-1.18.0.tar.gz", hash = "sha256:c5f0b134723cbf2a0dc9ae1ee1d38e42db28fe23c74cdee613ba3ef286d04735", size = 14319, upload-time = "2025-02-06T22:14:40.799Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/9d/1322dc4bce4982d1eadd3a62802c996ae0303aad13d9ad88c1d35025f73d/django_browser_reload-1.18.0-py3-none-any.whl", hash = "sha256:ed4cc2fb83c3bf6c30b54107a1a6736c0b896e62e4eba666d81005b9f2ecf6f8", size = 12230, upload-time = "2025-02-06T22:14:36.87Z" }, +] + [[package]] name = "django-debug-toolbar" version = "5.2.0" @@ -47,6 +99,52 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/c2/ed3cb815002664349e9e50799b8c00ef15941f4cad797247cadbdeebab02/django_debug_toolbar-5.2.0-py3-none-any.whl", hash = "sha256:15627f4c2836a9099d795e271e38e8cf5204ccd79d5dbcd748f8a6c284dcd195", size = 262834, upload-time = "2025-04-29T05:23:55.472Z" }, ] +[[package]] +name = "django-watchfiles" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "watchfiles" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a2/b1/89c36fb87f5af2736cfd0610ea050c38e382251b44bcebeef603d45ab100/django_watchfiles-1.1.0.tar.gz", hash = "sha256:7f7b716387d320778b003bf3ff32945b904f7e240a65f8c5432f140705a5fdda", size = 5300, upload-time = "2025-02-06T22:15:51.834Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/0f/c696529f2542c42c00a3eeef52a4c214ec01a610e769be9e8cd69ab684b9/django_watchfiles-1.1.0-py3-none-any.whl", hash = "sha256:a8256d9dc8eb4fce3f038ec6e630d4058458dda3a5e8130066f4aa4ebedef42a", size = 4598, upload-time = "2025-02-06T22:15:50.663Z" }, +] + +[[package]] +name = "djlint" +version = "1.36.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "colorama" }, + { name = "cssbeautifier" }, + { name = "jsbeautifier" }, + { name = "json5" }, + { name = "pathspec" }, + { name = "pyyaml" }, + { name = "regex" }, + { name = "tqdm" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/89/ecf5be9f5c59a0c53bcaa29671742c5e269cc7d0e2622e3f65f41df251bf/djlint-1.36.4.tar.gz", hash = "sha256:17254f218b46fe5a714b224c85074c099bcb74e3b2e1f15c2ddc2cf415a408a1", size = 47849, upload-time = "2024-12-24T13:06:36.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/83/88b4c885812921739f5529a29085c3762705154d41caf7eb9a8886a3380c/djlint-1.36.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ead475013bcac46095b1bbc8cf97ed2f06e83422335734363f8a76b4ba7e47c2", size = 354384, upload-time = "2024-12-24T13:06:20.809Z" }, + { url = "https://files.pythonhosted.org/packages/32/38/67695f7a150b3d9d62fadb65242213d96024151570c3cf5d966effa68b0e/djlint-1.36.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6c601dfa68ea253311deb4a29a7362b7a64933bdfcfb5a06618f3e70ad1fa835", size = 322971, upload-time = "2024-12-24T13:06:22.185Z" }, + { url = "https://files.pythonhosted.org/packages/ac/7a/cd851393291b12e7fe17cf5d4d8874b8ea133aebbe9235f5314aabc96a52/djlint-1.36.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bda5014f295002363381969864addeb2db13955f1b26e772657c3b273ed7809f", size = 410972, upload-time = "2024-12-24T13:06:24.077Z" }, + { url = "https://files.pythonhosted.org/packages/6c/31/56469120394b970d4f079a552fde21ed27702ca729595ab0ed459eb6d240/djlint-1.36.4-cp313-cp313-win_amd64.whl", hash = "sha256:16ce37e085afe5a30953b2bd87cbe34c37843d94c701fc68a2dda06c1e428ff4", size = 362053, upload-time = "2024-12-24T13:06:25.432Z" }, + { url = "https://files.pythonhosted.org/packages/4b/67/f7aeea9be6fb3bd984487af8d0d80225a0b1e5f6f7126e3332d349fb13fe/djlint-1.36.4-py3-none-any.whl", hash = "sha256:e9699b8ac3057a6ed04fb90835b89bee954ed1959c01541ce4f8f729c938afdd", size = 52290, upload-time = "2024-12-24T13:06:33.76Z" }, +] + +[[package]] +name = "editorconfig" +version = "0.17.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/88/3a/a61d9a1f319a186b05d14df17daea42fcddea63c213bcd61a929fb3a6796/editorconfig-0.17.1.tar.gz", hash = "sha256:23c08b00e8e08cc3adcddb825251c497478df1dada6aefeb01e626ad37303745", size = 14695, upload-time = "2025-06-09T08:21:37.097Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/fd/a40c621ff207f3ce8e484aa0fc8ba4eb6e3ecf52e15b42ba764b457a9550/editorconfig-0.17.1-py3-none-any.whl", hash = "sha256:1eda9c2c0db8c16dbd50111b710572a5e6de934e39772de1959d41f64fc17c82", size = 16360, upload-time = "2025-06-09T08:21:35.654Z" }, +] + [[package]] name = "execnet" version = "2.1.1" @@ -56,6 +154,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/43/09/2aea36ff60d16dd8879bdb2f5b3ee0ba8d08cbbdcdfe870e695ce3784385/execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc", size = 40612, upload-time = "2024-04-08T09:04:17.414Z" }, ] +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, +] + [[package]] name = "iniconfig" version = "2.1.0" @@ -65,6 +172,28 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, ] +[[package]] +name = "jsbeautifier" +version = "1.15.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "editorconfig" }, + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ea/98/d6cadf4d5a1c03b2136837a435682418c29fdeb66be137128544cecc5b7a/jsbeautifier-1.15.4.tar.gz", hash = "sha256:5bb18d9efb9331d825735fbc5360ee8f1aac5e52780042803943aa7f854f7592", size = 75257, upload-time = "2025-02-27T17:53:53.252Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/14/1c65fccf8413d5f5c6e8425f84675169654395098000d8bddc4e9d3390e1/jsbeautifier-1.15.4-py3-none-any.whl", hash = "sha256:72f65de312a3f10900d7685557f84cb61a9733c50dcc27271a39f5b0051bf528", size = 94707, upload-time = "2025-02-27T17:53:46.152Z" }, +] + +[[package]] +name = "json5" +version = "0.12.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/12/be/c6c745ec4c4539b25a278b70e29793f10382947df0d9efba2fa09120895d/json5-0.12.0.tar.gz", hash = "sha256:0b4b6ff56801a1c7dc817b0241bca4ce474a0e6a163bfef3fc594d3fd263ff3a", size = 51907, upload-time = "2025-04-03T16:33:13.201Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/9f/3500910d5a98549e3098807493851eeef2b89cdd3032227558a104dfe926/json5-0.12.0-py3-none-any.whl", hash = "sha256:6d37aa6c08b0609f16e1ec5ff94697e2cbbfbad5ac112afa05794da9ab7810db", size = 36079, upload-time = "2025-04-03T16:33:11.927Z" }, +] + [[package]] name = "packaging" version = "25.0" @@ -74,6 +203,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, ] +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + [[package]] name = "platformdirs" version = "4.3.8" @@ -171,6 +309,64 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, +] + +[[package]] +name = "regex" +version = "2024.11.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/5f/bd69653fbfb76cf8604468d3b4ec4c403197144c7bfe0e6a5fc9e02a07cb/regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519", size = 399494, upload-time = "2024-11-06T20:12:31.635Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/73/bcb0e36614601016552fa9344544a3a2ae1809dc1401b100eab02e772e1f/regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84", size = 483525, upload-time = "2024-11-06T20:10:45.19Z" }, + { url = "https://files.pythonhosted.org/packages/0f/3f/f1a082a46b31e25291d830b369b6b0c5576a6f7fb89d3053a354c24b8a83/regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4", size = 288324, upload-time = "2024-11-06T20:10:47.177Z" }, + { url = "https://files.pythonhosted.org/packages/09/c9/4e68181a4a652fb3ef5099e077faf4fd2a694ea6e0f806a7737aff9e758a/regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0", size = 284617, upload-time = "2024-11-06T20:10:49.312Z" }, + { url = "https://files.pythonhosted.org/packages/fc/fd/37868b75eaf63843165f1d2122ca6cb94bfc0271e4428cf58c0616786dce/regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0", size = 795023, upload-time = "2024-11-06T20:10:51.102Z" }, + { url = "https://files.pythonhosted.org/packages/c4/7c/d4cd9c528502a3dedb5c13c146e7a7a539a3853dc20209c8e75d9ba9d1b2/regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7", size = 833072, upload-time = "2024-11-06T20:10:52.926Z" }, + { url = "https://files.pythonhosted.org/packages/4f/db/46f563a08f969159c5a0f0e722260568425363bea43bb7ae370becb66a67/regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7", size = 823130, upload-time = "2024-11-06T20:10:54.828Z" }, + { url = "https://files.pythonhosted.org/packages/db/60/1eeca2074f5b87df394fccaa432ae3fc06c9c9bfa97c5051aed70e6e00c2/regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c", size = 796857, upload-time = "2024-11-06T20:10:56.634Z" }, + { url = "https://files.pythonhosted.org/packages/10/db/ac718a08fcee981554d2f7bb8402f1faa7e868c1345c16ab1ebec54b0d7b/regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3", size = 784006, upload-time = "2024-11-06T20:10:59.369Z" }, + { url = "https://files.pythonhosted.org/packages/c2/41/7da3fe70216cea93144bf12da2b87367590bcf07db97604edeea55dac9ad/regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07", size = 781650, upload-time = "2024-11-06T20:11:02.042Z" }, + { url = "https://files.pythonhosted.org/packages/a7/d5/880921ee4eec393a4752e6ab9f0fe28009435417c3102fc413f3fe81c4e5/regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e", size = 789545, upload-time = "2024-11-06T20:11:03.933Z" }, + { url = "https://files.pythonhosted.org/packages/dc/96/53770115e507081122beca8899ab7f5ae28ae790bfcc82b5e38976df6a77/regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6", size = 853045, upload-time = "2024-11-06T20:11:06.497Z" }, + { url = "https://files.pythonhosted.org/packages/31/d3/1372add5251cc2d44b451bd94f43b2ec78e15a6e82bff6a290ef9fd8f00a/regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4", size = 860182, upload-time = "2024-11-06T20:11:09.06Z" }, + { url = "https://files.pythonhosted.org/packages/ed/e3/c446a64984ea9f69982ba1a69d4658d5014bc7a0ea468a07e1a1265db6e2/regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d", size = 787733, upload-time = "2024-11-06T20:11:11.256Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f1/e40c8373e3480e4f29f2692bd21b3e05f296d3afebc7e5dcf21b9756ca1c/regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff", size = 262122, upload-time = "2024-11-06T20:11:13.161Z" }, + { url = "https://files.pythonhosted.org/packages/45/94/bc295babb3062a731f52621cdc992d123111282e291abaf23faa413443ea/regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a", size = 273545, upload-time = "2024-11-06T20:11:15Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + [[package]] name = "sqlparse" version = "0.5.3" @@ -180,13 +376,28 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a9/5c/bfd6bd0bf979426d405cc6e71eceb8701b148b16c21d2dc3c261efc61c7b/sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca", size = 44415, upload-time = "2024-12-10T12:05:27.824Z" }, ] +[[package]] +name = "tqdm" +version = "4.67.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737, upload-time = "2024-11-24T20:12:22.481Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" }, +] + [[package]] name = "ttvdrops" version = "0.1.0" source = { virtual = "." } dependencies = [ { name = "django" }, + { name = "django-browser-reload" }, { name = "django-debug-toolbar" }, + { name = "django-watchfiles" }, + { name = "djlint" }, { name = "platformdirs" }, { name = "python-dotenv" }, ] @@ -201,7 +412,10 @@ dev = [ [package.metadata] requires-dist = [ { name = "django", specifier = ">=5.2.4" }, + { name = "django-browser-reload", specifier = ">=1.18.0" }, { name = "django-debug-toolbar", specifier = ">=5.2.0" }, + { name = "django-watchfiles", specifier = ">=1.1.0" }, + { name = "djlint", specifier = ">=1.36.4" }, { name = "platformdirs", specifier = ">=4.3.8" }, { name = "python-dotenv", specifier = ">=1.1.1" }, ] @@ -221,3 +435,57 @@ sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be76 wheels = [ { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839, upload-time = "2025-03-23T13:54:41.845Z" }, ] + +[[package]] +name = "watchfiles" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2a/9a/d451fcc97d029f5812e898fd30a53fd8c15c7bbd058fd75cfc6beb9bd761/watchfiles-1.1.0.tar.gz", hash = "sha256:693ed7ec72cbfcee399e92c895362b6e66d63dac6b91e2c11ae03d10d503e575", size = 94406, upload-time = "2025-06-15T19:06:59.42Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d3/42/fae874df96595556a9089ade83be34a2e04f0f11eb53a8dbf8a8a5e562b4/watchfiles-1.1.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5007f860c7f1f8df471e4e04aaa8c43673429047d63205d1630880f7637bca30", size = 402004, upload-time = "2025-06-15T19:05:38.499Z" }, + { url = "https://files.pythonhosted.org/packages/fa/55/a77e533e59c3003d9803c09c44c3651224067cbe7fb5d574ddbaa31e11ca/watchfiles-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:20ecc8abbd957046f1fe9562757903f5eaf57c3bce70929fda6c7711bb58074a", size = 393671, upload-time = "2025-06-15T19:05:39.52Z" }, + { url = "https://files.pythonhosted.org/packages/05/68/b0afb3f79c8e832e6571022611adbdc36e35a44e14f129ba09709aa4bb7a/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2f0498b7d2a3c072766dba3274fe22a183dbea1f99d188f1c6c72209a1063dc", size = 449772, upload-time = "2025-06-15T19:05:40.897Z" }, + { url = "https://files.pythonhosted.org/packages/ff/05/46dd1f6879bc40e1e74c6c39a1b9ab9e790bf1f5a2fe6c08b463d9a807f4/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:239736577e848678e13b201bba14e89718f5c2133dfd6b1f7846fa1b58a8532b", size = 456789, upload-time = "2025-06-15T19:05:42.045Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ca/0eeb2c06227ca7f12e50a47a3679df0cd1ba487ea19cf844a905920f8e95/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eff4b8d89f444f7e49136dc695599a591ff769300734446c0a86cba2eb2f9895", size = 482551, upload-time = "2025-06-15T19:05:43.781Z" }, + { url = "https://files.pythonhosted.org/packages/31/47/2cecbd8694095647406645f822781008cc524320466ea393f55fe70eed3b/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12b0a02a91762c08f7264e2e79542f76870c3040bbc847fb67410ab81474932a", size = 597420, upload-time = "2025-06-15T19:05:45.244Z" }, + { url = "https://files.pythonhosted.org/packages/d9/7e/82abc4240e0806846548559d70f0b1a6dfdca75c1b4f9fa62b504ae9b083/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29e7bc2eee15cbb339c68445959108803dc14ee0c7b4eea556400131a8de462b", size = 477950, upload-time = "2025-06-15T19:05:46.332Z" }, + { url = "https://files.pythonhosted.org/packages/25/0d/4d564798a49bf5482a4fa9416dea6b6c0733a3b5700cb8a5a503c4b15853/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9481174d3ed982e269c090f780122fb59cee6c3796f74efe74e70f7780ed94c", size = 451706, upload-time = "2025-06-15T19:05:47.459Z" }, + { url = "https://files.pythonhosted.org/packages/81/b5/5516cf46b033192d544102ea07c65b6f770f10ed1d0a6d388f5d3874f6e4/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:80f811146831c8c86ab17b640801c25dc0a88c630e855e2bef3568f30434d52b", size = 625814, upload-time = "2025-06-15T19:05:48.654Z" }, + { url = "https://files.pythonhosted.org/packages/0c/dd/7c1331f902f30669ac3e754680b6edb9a0dd06dea5438e61128111fadd2c/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:60022527e71d1d1fda67a33150ee42869042bce3d0fcc9cc49be009a9cded3fb", size = 622820, upload-time = "2025-06-15T19:05:50.088Z" }, + { url = "https://files.pythonhosted.org/packages/1b/14/36d7a8e27cd128d7b1009e7715a7c02f6c131be9d4ce1e5c3b73d0e342d8/watchfiles-1.1.0-cp313-cp313-win32.whl", hash = "sha256:32d6d4e583593cb8576e129879ea0991660b935177c0f93c6681359b3654bfa9", size = 279194, upload-time = "2025-06-15T19:05:51.186Z" }, + { url = "https://files.pythonhosted.org/packages/25/41/2dd88054b849aa546dbeef5696019c58f8e0774f4d1c42123273304cdb2e/watchfiles-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:f21af781a4a6fbad54f03c598ab620e3a77032c5878f3d780448421a6e1818c7", size = 292349, upload-time = "2025-06-15T19:05:52.201Z" }, + { url = "https://files.pythonhosted.org/packages/c8/cf/421d659de88285eb13941cf11a81f875c176f76a6d99342599be88e08d03/watchfiles-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:5366164391873ed76bfdf618818c82084c9db7fac82b64a20c44d335eec9ced5", size = 283836, upload-time = "2025-06-15T19:05:53.265Z" }, + { url = "https://files.pythonhosted.org/packages/45/10/6faf6858d527e3599cc50ec9fcae73590fbddc1420bd4fdccfebffeedbc6/watchfiles-1.1.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:17ab167cca6339c2b830b744eaf10803d2a5b6683be4d79d8475d88b4a8a4be1", size = 400343, upload-time = "2025-06-15T19:05:54.252Z" }, + { url = "https://files.pythonhosted.org/packages/03/20/5cb7d3966f5e8c718006d0e97dfe379a82f16fecd3caa7810f634412047a/watchfiles-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:328dbc9bff7205c215a7807da7c18dce37da7da718e798356212d22696404339", size = 392916, upload-time = "2025-06-15T19:05:55.264Z" }, + { url = "https://files.pythonhosted.org/packages/8c/07/d8f1176328fa9e9581b6f120b017e286d2a2d22ae3f554efd9515c8e1b49/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7208ab6e009c627b7557ce55c465c98967e8caa8b11833531fdf95799372633", size = 449582, upload-time = "2025-06-15T19:05:56.317Z" }, + { url = "https://files.pythonhosted.org/packages/66/e8/80a14a453cf6038e81d072a86c05276692a1826471fef91df7537dba8b46/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a8f6f72974a19efead54195bc9bed4d850fc047bb7aa971268fd9a8387c89011", size = 456752, upload-time = "2025-06-15T19:05:57.359Z" }, + { url = "https://files.pythonhosted.org/packages/5a/25/0853b3fe0e3c2f5af9ea60eb2e781eade939760239a72c2d38fc4cc335f6/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d181ef50923c29cf0450c3cd47e2f0557b62218c50b2ab8ce2ecaa02bd97e670", size = 481436, upload-time = "2025-06-15T19:05:58.447Z" }, + { url = "https://files.pythonhosted.org/packages/fe/9e/4af0056c258b861fbb29dcb36258de1e2b857be4a9509e6298abcf31e5c9/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:adb4167043d3a78280d5d05ce0ba22055c266cf8655ce942f2fb881262ff3cdf", size = 596016, upload-time = "2025-06-15T19:05:59.59Z" }, + { url = "https://files.pythonhosted.org/packages/c5/fa/95d604b58aa375e781daf350897aaaa089cff59d84147e9ccff2447c8294/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5701dc474b041e2934a26d31d39f90fac8a3dee2322b39f7729867f932b1d4", size = 476727, upload-time = "2025-06-15T19:06:01.086Z" }, + { url = "https://files.pythonhosted.org/packages/65/95/fe479b2664f19be4cf5ceeb21be05afd491d95f142e72d26a42f41b7c4f8/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b067915e3c3936966a8607f6fe5487df0c9c4afb85226613b520890049deea20", size = 451864, upload-time = "2025-06-15T19:06:02.144Z" }, + { url = "https://files.pythonhosted.org/packages/d3/8a/3c4af14b93a15ce55901cd7a92e1a4701910f1768c78fb30f61d2b79785b/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:9c733cda03b6d636b4219625a4acb5c6ffb10803338e437fb614fef9516825ef", size = 625626, upload-time = "2025-06-15T19:06:03.578Z" }, + { url = "https://files.pythonhosted.org/packages/da/f5/cf6aa047d4d9e128f4b7cde615236a915673775ef171ff85971d698f3c2c/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:cc08ef8b90d78bfac66f0def80240b0197008e4852c9f285907377b2947ffdcb", size = 622744, upload-time = "2025-06-15T19:06:05.066Z" }, + { url = "https://files.pythonhosted.org/packages/2c/00/70f75c47f05dea6fd30df90f047765f6fc2d6eb8b5a3921379b0b04defa2/watchfiles-1.1.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:9974d2f7dc561cce3bb88dfa8eb309dab64c729de85fba32e98d75cf24b66297", size = 402114, upload-time = "2025-06-15T19:06:06.186Z" }, + { url = "https://files.pythonhosted.org/packages/53/03/acd69c48db4a1ed1de26b349d94077cca2238ff98fd64393f3e97484cae6/watchfiles-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c68e9f1fcb4d43798ad8814c4c1b61547b014b667216cb754e606bfade587018", size = 393879, upload-time = "2025-06-15T19:06:07.369Z" }, + { url = "https://files.pythonhosted.org/packages/2f/c8/a9a2a6f9c8baa4eceae5887fecd421e1b7ce86802bcfc8b6a942e2add834/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95ab1594377effac17110e1352989bdd7bdfca9ff0e5eeccd8c69c5389b826d0", size = 450026, upload-time = "2025-06-15T19:06:08.476Z" }, + { url = "https://files.pythonhosted.org/packages/fe/51/d572260d98388e6e2b967425c985e07d47ee6f62e6455cefb46a6e06eda5/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fba9b62da882c1be1280a7584ec4515d0a6006a94d6e5819730ec2eab60ffe12", size = 457917, upload-time = "2025-06-15T19:06:09.988Z" }, + { url = "https://files.pythonhosted.org/packages/c6/2d/4258e52917bf9f12909b6ec314ff9636276f3542f9d3807d143f27309104/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3434e401f3ce0ed6b42569128b3d1e3af773d7ec18751b918b89cd49c14eaafb", size = 483602, upload-time = "2025-06-15T19:06:11.088Z" }, + { url = "https://files.pythonhosted.org/packages/84/99/bee17a5f341a4345fe7b7972a475809af9e528deba056f8963d61ea49f75/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa257a4d0d21fcbca5b5fcba9dca5a78011cb93c0323fb8855c6d2dfbc76eb77", size = 596758, upload-time = "2025-06-15T19:06:12.197Z" }, + { url = "https://files.pythonhosted.org/packages/40/76/e4bec1d59b25b89d2b0716b41b461ed655a9a53c60dc78ad5771fda5b3e6/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fd1b3879a578a8ec2076c7961076df540b9af317123f84569f5a9ddee64ce92", size = 477601, upload-time = "2025-06-15T19:06:13.391Z" }, + { url = "https://files.pythonhosted.org/packages/1f/fa/a514292956f4a9ce3c567ec0c13cce427c158e9f272062685a8a727d08fc/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc7a30eeb0e20ecc5f4bd113cd69dcdb745a07c68c0370cea919f373f65d9e", size = 451936, upload-time = "2025-06-15T19:06:14.656Z" }, + { url = "https://files.pythonhosted.org/packages/32/5d/c3bf927ec3bbeb4566984eba8dd7a8eb69569400f5509904545576741f88/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:891c69e027748b4a73847335d208e374ce54ca3c335907d381fde4e41661b13b", size = 626243, upload-time = "2025-06-15T19:06:16.232Z" }, + { url = "https://files.pythonhosted.org/packages/e6/65/6e12c042f1a68c556802a84d54bb06d35577c81e29fba14019562479159c/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:12fe8eaffaf0faa7906895b4f8bb88264035b3f0243275e0bf24af0436b27259", size = 623073, upload-time = "2025-06-15T19:06:17.457Z" }, + { url = "https://files.pythonhosted.org/packages/89/ab/7f79d9bf57329e7cbb0a6fd4c7bd7d0cee1e4a8ef0041459f5409da3506c/watchfiles-1.1.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:bfe3c517c283e484843cb2e357dd57ba009cff351edf45fb455b5fbd1f45b15f", size = 400872, upload-time = "2025-06-15T19:06:18.57Z" }, + { url = "https://files.pythonhosted.org/packages/df/d5/3f7bf9912798e9e6c516094db6b8932df53b223660c781ee37607030b6d3/watchfiles-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a9ccbf1f129480ed3044f540c0fdbc4ee556f7175e5ab40fe077ff6baf286d4e", size = 392877, upload-time = "2025-06-15T19:06:19.55Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c5/54ec7601a2798604e01c75294770dbee8150e81c6e471445d7601610b495/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba0e3255b0396cac3cc7bbace76404dd72b5438bf0d8e7cefa2f79a7f3649caa", size = 449645, upload-time = "2025-06-15T19:06:20.66Z" }, + { url = "https://files.pythonhosted.org/packages/0a/04/c2f44afc3b2fce21ca0b7802cbd37ed90a29874f96069ed30a36dfe57c2b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4281cd9fce9fc0a9dbf0fc1217f39bf9cf2b4d315d9626ef1d4e87b84699e7e8", size = 457424, upload-time = "2025-06-15T19:06:21.712Z" }, + { url = "https://files.pythonhosted.org/packages/9f/b0/eec32cb6c14d248095261a04f290636da3df3119d4040ef91a4a50b29fa5/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d2404af8db1329f9a3c9b79ff63e0ae7131986446901582067d9304ae8aaf7f", size = 481584, upload-time = "2025-06-15T19:06:22.777Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e2/ca4bb71c68a937d7145aa25709e4f5d68eb7698a25ce266e84b55d591bbd/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e78b6ed8165996013165eeabd875c5dfc19d41b54f94b40e9fff0eb3193e5e8e", size = 596675, upload-time = "2025-06-15T19:06:24.226Z" }, + { url = "https://files.pythonhosted.org/packages/a1/dd/b0e4b7fb5acf783816bc950180a6cd7c6c1d2cf7e9372c0ea634e722712b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:249590eb75ccc117f488e2fabd1bfa33c580e24b96f00658ad88e38844a040bb", size = 477363, upload-time = "2025-06-15T19:06:25.42Z" }, + { url = "https://files.pythonhosted.org/packages/69/c4/088825b75489cb5b6a761a4542645718893d395d8c530b38734f19da44d2/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05686b5487cfa2e2c28ff1aa370ea3e6c5accfe6435944ddea1e10d93872147", size = 452240, upload-time = "2025-06-15T19:06:26.552Z" }, + { url = "https://files.pythonhosted.org/packages/10/8c/22b074814970eeef43b7c44df98c3e9667c1f7bf5b83e0ff0201b0bd43f9/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d0e10e6f8f6dc5762adee7dece33b722282e1f59aa6a55da5d493a97282fedd8", size = 625607, upload-time = "2025-06-15T19:06:27.606Z" }, + { url = "https://files.pythonhosted.org/packages/32/fa/a4f5c2046385492b2273213ef815bf71a0d4c1943b784fb904e184e30201/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:af06c863f152005c7592df1d6a7009c836a247c9d8adb78fef8575a5a98699db", size = 623315, upload-time = "2025-06-15T19:06:29.076Z" }, +]