Compare commits
12 Commits
df595e4f19
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b35e208b85 | |||
| bae6bf7a03 | |||
| 53fc3e5bed | |||
| 7db7f9b195 | |||
| 77278bcc56 | |||
| 145f7fdc2e | |||
| 3368c95ae2 | |||
| 219acb3513 | |||
| 5c0289e715 | |||
| 07dcb72deb | |||
| 495dfe7b8e | |||
| 27aac4da8c |
9
.pre-commit-config.yaml
Normal file
9
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.14.9
|
||||
hooks:
|
||||
# Run the linter.
|
||||
- id: ruff-check
|
||||
# Run the formatter.
|
||||
- id: ruff-format
|
||||
@@ -38,7 +38,9 @@ INSTALLED_APPS = [
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
"rest_framework",
|
||||
"knox",
|
||||
"notes",
|
||||
"livereload",
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
@@ -49,6 +51,7 @@ MIDDLEWARE = [
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
"livereload.middleware.LiveReloadScript",
|
||||
]
|
||||
|
||||
ROOT_URLCONF = "appunti.urls"
|
||||
@@ -127,7 +130,20 @@ AUTH_USER_MODEL = "notes.User"
|
||||
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_PERMISSION_CLASSES': [
|
||||
'rest_framework.permissions.IsAuthenticated',
|
||||
"DEFAULT_PERMISSION_CLASSES": [
|
||||
"rest_framework.permissions.IsAuthenticated",
|
||||
],
|
||||
"DEFAULT_AUTHENTICATION_CLASSES": [
|
||||
"knox.auth.TokenAuthentication",
|
||||
"rest_framework.authentication.BasicAuthentication",
|
||||
"rest_framework.authentication.SessionAuthentication",
|
||||
],
|
||||
}
|
||||
|
||||
REST_KNOX = {
|
||||
"TOKEN_TTL": None,
|
||||
}
|
||||
|
||||
LOGIN_URL = "login"
|
||||
LOGIN_REDIRECT_URL = "/"
|
||||
LOGOUT_REDIRECT_URL = "login"
|
||||
|
||||
@@ -20,5 +20,5 @@ from django.urls import include, path
|
||||
|
||||
urlpatterns = [
|
||||
path("admin/", admin.site.urls),
|
||||
path("", include("notes.urls"))
|
||||
path("", include("notes.urls")),
|
||||
]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
"""Django's command-line utility for administrative tasks."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
from django.utils import timezone
|
||||
from rest_framework import generics
|
||||
|
||||
from notes.models import Note
|
||||
from notes.serializers import NoteSerializer
|
||||
|
||||
|
||||
@@ -9,4 +7,4 @@ class NoteListView(generics.ListCreateAPIView):
|
||||
serializer_class = NoteSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return Note.objects.filter(to_user=self.request.user, expiry__gt=timezone.now()).select_related("from_user", "to_user")
|
||||
return self.request.user.alive_received_notes
|
||||
|
||||
9
notes/forms.py
Normal file
9
notes/forms.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from django import forms
|
||||
|
||||
from notes.models import Note
|
||||
|
||||
|
||||
class PostNoteForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Note
|
||||
fields = ["to_user", "note"]
|
||||
@@ -9,7 +9,6 @@ from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
|
||||
@@ -1,16 +1,36 @@
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class User(AbstractUser):
|
||||
allow_notes_from = models.ManyToManyField('User', related_name='allowed_notes_to', blank=True)
|
||||
allow_notes_from = models.ManyToManyField(
|
||||
"User", related_name="allowed_notes_to", blank=True
|
||||
)
|
||||
expiry_seconds = models.PositiveIntegerField(default=86400)
|
||||
|
||||
@property
|
||||
def alive_received_notes(self) -> models.QuerySet["Note"]:
|
||||
return self.received_notes.filter(expiry__gt=timezone.now()).select_related(
|
||||
"from_user", "to_user"
|
||||
)
|
||||
|
||||
@property
|
||||
def visible_name(self) -> str:
|
||||
if self.first_name or self.last_name:
|
||||
return self.get_full_name()
|
||||
return self.username
|
||||
|
||||
|
||||
class Note(models.Model):
|
||||
from_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='created_notes')
|
||||
to_user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='received_notes')
|
||||
from_user = models.ForeignKey(
|
||||
User, on_delete=models.CASCADE, related_name="created_notes"
|
||||
)
|
||||
to_user = models.ForeignKey(
|
||||
User, on_delete=models.SET_NULL, null=True, related_name="received_notes"
|
||||
)
|
||||
note = models.TextField()
|
||||
expiry = models.DateTimeField()
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
@@ -7,10 +7,11 @@ from notes.models import Note, User
|
||||
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
username = serializers.CharField(max_length=150)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ["id", "username", "first_name", "last_name"]
|
||||
read_only_fields = ["id", "first_name", "last_name"]
|
||||
fields = ["id", "username", "first_name", "last_name", "visible_name"]
|
||||
read_only_fields = ["id", "first_name", "last_name", "visible_name"]
|
||||
|
||||
|
||||
class NoteSerializer(serializers.ModelSerializer):
|
||||
@@ -34,20 +35,22 @@ class NoteSerializer(serializers.ModelSerializer):
|
||||
|
||||
def validate_to_user(self, value):
|
||||
try:
|
||||
user = User.objects.get(username=value['username'])
|
||||
user = User.objects.get(username=value["username"])
|
||||
except User.DoesNotExist:
|
||||
raise serializers.ValidationError("User not found")
|
||||
|
||||
current_user = self.context['request'].user
|
||||
current_user = self.context["request"].user
|
||||
if not current_user.allowed_notes_to.filter(pk=user.pk).exists():
|
||||
raise serializers.ValidationError(f"User not allowed to post notes to {user!r}")
|
||||
raise serializers.ValidationError(
|
||||
f"User not allowed to post notes to {user!r}"
|
||||
)
|
||||
return user
|
||||
|
||||
def save(self, **kwargs):
|
||||
to_user = self.validated_data['to_user']
|
||||
to_user = self.validated_data["to_user"]
|
||||
return Note.objects.create(
|
||||
from_user=self.context['request'].user,
|
||||
from_user=self.context["request"].user,
|
||||
to_user=to_user,
|
||||
note=self.validated_data['note'],
|
||||
expiry=timezone.now() + timedelta(seconds=to_user.expiry_seconds)
|
||||
note=self.validated_data["note"],
|
||||
expiry=timezone.now() + timedelta(seconds=to_user.expiry_seconds),
|
||||
)
|
||||
|
||||
BIN
notes/static/notes/images/icons/logout.png
Normal file
BIN
notes/static/notes/images/icons/logout.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
notes/static/notes/images/icons/paw.png
Normal file
BIN
notes/static/notes/images/icons/paw.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
BIN
notes/static/notes/images/icons/post-a-note.png
Normal file
BIN
notes/static/notes/images/icons/post-a-note.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
BIN
notes/static/notes/images/icons/profile.png
Normal file
BIN
notes/static/notes/images/icons/profile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
139
notes/static/notes/stylesheets/style.css
Normal file
139
notes/static/notes/stylesheets/style.css
Normal file
@@ -0,0 +1,139 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f4f0f0;
|
||||
font-family: cursive;
|
||||
}
|
||||
|
||||
header {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
background-color: #e7bbe0;
|
||||
}
|
||||
|
||||
header > .home {
|
||||
flex-grow: 1;
|
||||
font-size: 3em;
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
margin-left: 20px;
|
||||
@media (max-width: 500px) {
|
||||
font-size: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
header img {
|
||||
height: 40px;
|
||||
margin: 20px;
|
||||
@media (max-width: 500px) {
|
||||
height: 25px;
|
||||
margin: 10px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.logout {
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
border: none;
|
||||
min-width: unset;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
input, select, textarea {
|
||||
padding: 5px;
|
||||
min-width: 200px;
|
||||
display: block;
|
||||
box-shadow: 15px 28px 25px -18px rgba(0, 0, 0, 0.1);
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 10px;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.notes {
|
||||
width: 100%;
|
||||
columns: auto 300px;
|
||||
column-gap: 80px;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.notes.notes-grid {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.note {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
padding: 30px;
|
||||
border: 2px solid rgba(30, 30, 30, 0.4);
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
box-shadow: 15px 28px 25px -18px rgba(0, 0, 0, 0.2);
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
select:nth-child(3n), textarea:nth-child(3n), button:nth-child(3n), input:nth-child(3n), .note:nth-child(3n) {
|
||||
border-radius: 155px 25px 15px 25px / 15px 225px 230px 150px;
|
||||
}
|
||||
|
||||
select:nth-child(3n + 1), textarea:nth-child(3n + 1), button:nth-child(3n + 1), input:nth-child(3n + 1), .note:nth-child(3n + 1) {
|
||||
border-radius: 25px 155px 15px 25px / 115px 25px 225px 150px;
|
||||
}
|
||||
|
||||
select:nth-child(3n + 2), textarea:nth-child(3n + 2), button:nth-child(3n + 2), input:nth-child(3n + 2), .note:nth-child(3n + 2) {
|
||||
border-radius: 25px 150px 25px 155px / 115px 25px 225px 50px;
|
||||
}
|
||||
|
||||
.note:nth-child(4n) {
|
||||
background-color: #d4f2d8;
|
||||
}
|
||||
|
||||
.note:nth-child(4n + 1) {
|
||||
background-color: #fac9dc;
|
||||
}
|
||||
|
||||
.note:nth-child(4n + 2) {
|
||||
background-color: #fff372;
|
||||
}
|
||||
|
||||
.note:nth-child(4n + 3) {
|
||||
background-color: #a4d6f7;
|
||||
}
|
||||
|
||||
.note-from, .note-at {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
|
||||
.card {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
padding: 30px;
|
||||
border: 2px solid rgba(30, 30, 30, 0.4);
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
box-shadow: 15px 28px 25px -18px rgba(0, 0, 0, 0.2);
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
border-radius: 25px 155px 15px 25px / 115px 25px 225px 150px;
|
||||
background-color: #fac9dc;
|
||||
}
|
||||
29
notes/templates/notes/base.html
Normal file
29
notes/templates/notes/base.html
Normal file
@@ -0,0 +1,29 @@
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="stylesheet" href="{% static "notes/stylesheets/style.css" %}" type="text/css">
|
||||
<title>{% block title %}{% endblock %} | Appunti</title>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<a href="{% url "home" %}" class="home">Appunti</a>
|
||||
<a href="{% url "post-a-note" %}">
|
||||
<img src="{% static "notes/images/icons/post-a-note.png" %}" alt="Post a note" title="Post a note" />
|
||||
</a>
|
||||
<a href="{% url "profile" %}">
|
||||
<img src="{% static "notes/images/icons/profile.png" %}" alt="Profile" title="Profile" />
|
||||
</a>
|
||||
<form method="post" action="{% url "logout" %}">
|
||||
{% csrf_token %}
|
||||
<button class="logout"><img src="{% static "notes/images/icons/logout.png" %}" alt="Logout" title="Logout" /></button>
|
||||
</form>
|
||||
</header>
|
||||
<main>
|
||||
{% block body %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
23
notes/templates/notes/home.html
Normal file
23
notes/templates/notes/home.html
Normal file
@@ -0,0 +1,23 @@
|
||||
{% extends "notes/base.html" %}
|
||||
|
||||
{% block title %}Dashboard{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Dashboard</h1>
|
||||
{% include "notes/messages.html" %}
|
||||
|
||||
<h2>Notes for you</h2>
|
||||
{% if notes %}
|
||||
<div class="notes">
|
||||
{% for note in notes %}
|
||||
<div class="note">
|
||||
<p>{{ note.note }}</p>
|
||||
<p class="note-from">From {{ note.from_user.visible_name }}</p>
|
||||
<p class="note-at">{{ note.created_at|date:"j M, H:i"}}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="card">No Notes found</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
7
notes/templates/notes/messages.html
Normal file
7
notes/templates/notes/messages.html
Normal file
@@ -0,0 +1,7 @@
|
||||
{% if messages %}
|
||||
<div class="messages">
|
||||
{% for message in messages %}
|
||||
<div class="card">{{ message }}</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
12
notes/templates/notes/note_form.html
Normal file
12
notes/templates/notes/note_form.html
Normal file
@@ -0,0 +1,12 @@
|
||||
{% extends "notes/base.html" %}
|
||||
|
||||
{% block title %}Post a Note{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Post a Note</h1>
|
||||
{% include "notes/messages.html" %}
|
||||
<form method="post">{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<button type="submit">Post!</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
13
notes/templates/notes/user_form.html
Normal file
13
notes/templates/notes/user_form.html
Normal file
@@ -0,0 +1,13 @@
|
||||
{% extends "notes/base.html" %}
|
||||
|
||||
{% block title %}Profile{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Profile</h1>
|
||||
{% include "notes/messages.html" %}
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<button type="submit">Save</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
18
notes/templates/registration/login.html
Normal file
18
notes/templates/registration/login.html
Normal file
@@ -0,0 +1,18 @@
|
||||
{% extends "notes/base.html" %}
|
||||
{% block title %}Login{% endblock %}
|
||||
{% block body %}
|
||||
<div id="header">
|
||||
<h1>Appunti Login Screen</h1>
|
||||
</div>
|
||||
|
||||
<div class="body">
|
||||
{% include "notes/messages.html" %}
|
||||
<form action="{% url 'login' %}" method="POST">
|
||||
{% csrf_token %}
|
||||
<h2>Welcome!</h2>
|
||||
<p>Please login to continue</p>
|
||||
{{ form.as_p }}
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,3 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
from django.contrib.auth.views import LoginView, LogoutView
|
||||
from django.urls import include, path
|
||||
|
||||
from notes import api_views
|
||||
from notes import views, api_views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path("", views.HomePage.as_view(), name="home"),
|
||||
path("post-a-note/", views.PostNoteView.as_view(), name="post-a-note"),
|
||||
path("profile/", views.ProfileView.as_view(), name="profile"),
|
||||
path("login/", LoginView.as_view(), name="login"),
|
||||
path("logout/", LogoutView.as_view(), name="logout"),
|
||||
path("api/notes/", api_views.NoteListView.as_view(), name="api-notes-list"),
|
||||
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")),
|
||||
]
|
||||
|
||||
@@ -1,3 +1,52 @@
|
||||
from django.shortcuts import render
|
||||
from datetime import timedelta
|
||||
from typing import Any
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.views.generic import CreateView, TemplateView, UpdateView
|
||||
from django.views.generic.edit import FormMixin
|
||||
from notes.models import Note, User
|
||||
|
||||
|
||||
# Create your views here.
|
||||
class HomePage(LoginRequiredMixin, TemplateView):
|
||||
template_name = "notes/home.html"
|
||||
|
||||
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx["notes"] = self.request.user.alive_received_notes
|
||||
return ctx
|
||||
|
||||
|
||||
class PostNoteView(LoginRequiredMixin, CreateView):
|
||||
model = Note
|
||||
fields = ["to_user", "note"]
|
||||
success_url = reverse_lazy("post-a-note")
|
||||
|
||||
def get_form(self, form_class=None):
|
||||
form = super().get_form(form_class)
|
||||
form.fields["to_user"].queryset = self.request.user.allowed_notes_to.all()
|
||||
return form
|
||||
|
||||
def form_valid(self, form):
|
||||
self.object = note = form.save(commit=False)
|
||||
note.expiry = timezone.now() + timedelta(seconds=note.to_user.expiry_seconds)
|
||||
note.from_user = self.request.user
|
||||
note.save()
|
||||
messages.success(self.request, "Note has been posted!")
|
||||
return FormMixin.form_valid(self, form)
|
||||
|
||||
|
||||
class ProfileView(LoginRequiredMixin, UpdateView):
|
||||
model = User
|
||||
fields = ["first_name", "last_name", "allow_notes_from", "expiry_seconds"]
|
||||
success_url = reverse_lazy("profile")
|
||||
|
||||
def get_object(self):
|
||||
return self.request.user
|
||||
|
||||
def form_valid(self, form):
|
||||
ret = super().form_valid(form)
|
||||
messages.success(self.request, "Profile has been updated!")
|
||||
return ret
|
||||
|
||||
@@ -6,11 +6,14 @@ readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"django>=5.2.8",
|
||||
"django-rest-knox>=5.0.2",
|
||||
"djangorestframework>=3.16.1",
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"django-livereload-server>=0.5.1",
|
||||
"django-stubs>=5.2.8",
|
||||
"ipdb>=0.13.13",
|
||||
"pre-commit>=4.5.0",
|
||||
]
|
||||
|
||||
204
rainmeter/Appunti/notes/notes.ini
Normal file
204
rainmeter/Appunti/notes/notes.ini
Normal file
@@ -0,0 +1,204 @@
|
||||
[Rainmeter]
|
||||
; update once an hour=60 * 60 * 1000 / 10 (from MeasureNotes.UpdateRate)
|
||||
Update=360000
|
||||
DynamicWindowSize=1
|
||||
LeftMouseUpAction = [#AppuntiServer#]
|
||||
|
||||
[Metadata]
|
||||
Name=Appunti Notes
|
||||
Author=Ceda EI
|
||||
Information=https://gitlab.com/ceda_ei/appunti
|
||||
License=AGPL-3.0
|
||||
|
||||
[Variables]
|
||||
AppuntiServer=
|
||||
AuthToken=
|
||||
|
||||
[MeasureNotes]
|
||||
Measure=WebParser
|
||||
URL=#AppuntiServer#/api/notes/
|
||||
Header="Authorization: Token #AuthToken#"
|
||||
RegExp=(?siU)^(.*)$
|
||||
; low updateRate (like 1 or 2) causes WebParser to spam the webserver
|
||||
; regardless of the high Rainmeter.Update value. Setting it to 10 and
|
||||
; Rainmeter.Update to 360000 makes one request every hour.
|
||||
UpdateRate=10
|
||||
FinishAction=[!Update][!Update]
|
||||
|
||||
[MeasureNote1]
|
||||
Measure=Plugin
|
||||
Plugin=JsonParser.dll
|
||||
Source=[MeasureNotes]
|
||||
Query="[0].note"
|
||||
IFMatch="^$"
|
||||
IFMatchAction=[!HideMeterGroup Note1][!ShowMeterGroup NoNotes]
|
||||
IFNotMatchAction=[!ShowMeterGroup Note1][!HideMeterGroup NoNotes]
|
||||
|
||||
[MeasureNote1.From]
|
||||
Measure=Plugin
|
||||
Plugin=JsonParser.dll
|
||||
Source=[MeasureNotes]
|
||||
Query="[0].from_user.visible_name"
|
||||
|
||||
[MeasureNote1.Created]
|
||||
Measure=Plugin
|
||||
Plugin=JsonParser.dll
|
||||
Source=[MeasureNotes]
|
||||
Query="[0].created_at"
|
||||
|
||||
[MeasureNote2]
|
||||
Measure=Plugin
|
||||
Plugin=JsonParser.dll
|
||||
Source=[MeasureNotes]
|
||||
Query="[1].note"
|
||||
IFMatch="^$"
|
||||
IFMatchAction=[!HideMeterGroup Note2]
|
||||
IFNotMatchAction=[!ShowMeterGroup Note2]
|
||||
|
||||
[MeasureNote2.From]
|
||||
Measure=Plugin
|
||||
Plugin=JsonParser.dll
|
||||
Source=[MeasureNotes]
|
||||
Query="[1].from_user.visible_name"
|
||||
|
||||
[MeasureNote2.Created]
|
||||
Measure=Plugin
|
||||
Plugin=JsonParser.dll
|
||||
Source=[MeasureNotes]
|
||||
Query="[1].created_at"
|
||||
|
||||
[MoreNotes]
|
||||
Measure=Plugin
|
||||
Plugin=JsonParser.dll
|
||||
Source=[MeasureNotes]
|
||||
Query="[2].note"
|
||||
IFMatch="^$"
|
||||
IFMatchAction=[!HideMeterGroup MoreNotes]
|
||||
IFNotMatchAction=[!ShowMeterGroup MoreNotes]
|
||||
|
||||
[MeterNote1.Back]
|
||||
Meter=Shape
|
||||
Shape=Rectangle 0,0,340,([MeterNote1.Created:YH] + 20),10,10 | Fill Color 212,242,216,255 | StrokeWidth 4 | Stroke Color 30,30,30,102
|
||||
AntiAlias=1
|
||||
DynamicVariables=1
|
||||
Group=Note1
|
||||
|
||||
[MeterNote1]
|
||||
Meter=String
|
||||
FontFace=Comic Sans MS
|
||||
FontSize=12
|
||||
X=20
|
||||
Y=20
|
||||
W = 300
|
||||
MeasureName=MeasureNote1
|
||||
ClipString=2
|
||||
Text=%1
|
||||
AntiAlias=1
|
||||
Group=Note1
|
||||
|
||||
[MeterNote1.From]
|
||||
Meter=String
|
||||
FontFace=Comic Sans MS
|
||||
FontSize=12
|
||||
X=320
|
||||
Y=5R
|
||||
W = 300
|
||||
MeasureName=MeasureNote1.From
|
||||
ClipString=2
|
||||
Text=By: %1
|
||||
StringAlign=Right
|
||||
Group=Note1
|
||||
|
||||
[MeterNote1.Created]
|
||||
Meter=String
|
||||
FontFace=Comic Sans MS
|
||||
FontSize=12
|
||||
X=320
|
||||
Y=5R
|
||||
W = 300
|
||||
MeasureName=MeasureNote1.Created
|
||||
ClipString=2
|
||||
Text=At: %1
|
||||
StringAlign=Right
|
||||
Group=Note1
|
||||
|
||||
[MeterNote2.Back]
|
||||
Meter=Shape
|
||||
Shape=Rectangle 360,0,340,([MeterNote2.Created:YH] + 20),10,10 | Fill Color 250,201,220,255 | StrokeWidth 4 | Stroke Color 30,30,30,102
|
||||
DynamicVariables=1
|
||||
Group=Note2
|
||||
|
||||
[MeterNote2]
|
||||
Meter=String
|
||||
FontFace=Comic Sans MS
|
||||
FontSize=12
|
||||
X=380
|
||||
Y=20
|
||||
W = 300
|
||||
MeasureName=MeasureNote2
|
||||
ClipString=2
|
||||
Text=%1
|
||||
AntiAlias=1
|
||||
Group=Note2
|
||||
|
||||
[MeterNote2.From]
|
||||
Meter=String
|
||||
FontFace=Comic Sans MS
|
||||
FontSize=12
|
||||
X=680
|
||||
Y=5R
|
||||
W = 300
|
||||
MeasureName=MeasureNote2.From
|
||||
ClipString=2
|
||||
Text=By: %1
|
||||
StringAlign=Right
|
||||
Group=Note2
|
||||
|
||||
[MeterNote2.Created]
|
||||
Meter=String
|
||||
FontFace=Comic Sans MS
|
||||
FontSize=12
|
||||
X=680
|
||||
Y=5R
|
||||
W = 300
|
||||
MeasureName=MeasureNote2.Created
|
||||
ClipString=2
|
||||
Text=At: %1
|
||||
StringAlign=Right
|
||||
Group=Note2
|
||||
|
||||
[MeterMoreNotes.Back]
|
||||
Meter=Shape
|
||||
Shape=Rectangle 720,0,340,([MeterMoreNotes:YH] + 20),10,10 | Fill Color 164,214,247,255 | StrokeWidth 4 | Stroke Color 30,30,30,102
|
||||
AntiAlias=1
|
||||
DynamicVariables=1
|
||||
Group=MoreNotes
|
||||
|
||||
[MeterMoreNotes]
|
||||
Meter=String
|
||||
FontFace=Comic Sans MS
|
||||
FontSize=12
|
||||
X=740
|
||||
Y=20
|
||||
W = 300
|
||||
Text=Click to View More Notes
|
||||
AntiAlias=1
|
||||
Group=MoreNotes
|
||||
|
||||
[MeterNoNotes.Back]
|
||||
Meter=Shape
|
||||
Shape=Rectangle 0,0,340,([MeterNoNotes:YH] + 20),10,10 | Fill Color 255,243,114,255 | StrokeWidth 4 | Stroke Color 30,30,30,102
|
||||
AntiAlias=1
|
||||
DynamicVariables=1
|
||||
Group=NoNotes
|
||||
|
||||
[MeterNoNotes]
|
||||
Meter=String
|
||||
FontFace=Comic Sans MS
|
||||
FontSize=12
|
||||
X=20
|
||||
Y=20
|
||||
W = 300
|
||||
Text=No Notes
|
||||
AntiAlias=1
|
||||
Group=NoNotes
|
||||
171
uv.lock
generated
171
uv.lock
generated
@@ -8,25 +8,31 @@ version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "django" },
|
||||
{ name = "django-rest-knox" },
|
||||
{ name = "djangorestframework" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "django-livereload-server" },
|
||||
{ name = "django-stubs" },
|
||||
{ name = "ipdb" },
|
||||
{ name = "pre-commit" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "django", specifier = ">=5.2.8" },
|
||||
{ name = "django-rest-knox", specifier = ">=5.0.2" },
|
||||
{ name = "djangorestframework", specifier = ">=3.16.1" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "django-livereload-server", specifier = ">=0.5.1" },
|
||||
{ name = "django-stubs", specifier = ">=5.2.8" },
|
||||
{ name = "ipdb", specifier = ">=0.13.13" },
|
||||
{ name = "pre-commit", specifier = ">=4.5.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -47,6 +53,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfgv"
|
||||
version = "3.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
@@ -65,6 +80,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "distlib"
|
||||
version = "0.4.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django"
|
||||
version = "5.2.8"
|
||||
@@ -79,6 +103,32 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/3d/a035a4ee9b1d4d4beee2ae6e8e12fe6dee5514b21f62504e22efcbd9fb46/django-5.2.8-py3-none-any.whl", hash = "sha256:37e687f7bd73ddf043e2b6b97cfe02fcbb11f2dbb3adccc6a2b18c6daa054d7f", size = 8289692, upload-time = "2025-11-05T14:07:28.761Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django-livereload-server"
|
||||
version = "0.5.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "django" },
|
||||
{ name = "tornado" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/79/56/313c43b871d4cc167260faf2924a72ffa9105cdd78faf028341338115800/django-livereload-server-0.5.1.tar.gz", hash = "sha256:e1fecca2a74ec87235bbfdf8b63365499324d9a87017427e5d297711d1cd532d", size = 23111, upload-time = "2023-12-19T23:22:02.289Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/cd/77566526193cb49e805bd33a6b982ba5a39f3a7f828dd6647a76bf977f3c/django_livereload_server-0.5.1-py2.py3-none-any.whl", hash = "sha256:e03bd65d1679ef1b4a5e22e2a77d11d3cfb0e3d21ae25afba49e280924ba6f58", size = 25920, upload-time = "2023-12-19T23:22:00.494Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django-rest-knox"
|
||||
version = "5.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "django" },
|
||||
{ name = "djangorestframework" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ba/7e/6ef520fbfa0cb902fe32c6f921426b1dcfa50cb2471a0ddca31ba770fa72/django_rest_knox-5.0.2.tar.gz", hash = "sha256:f283622bcf5d28a6a0203845c065d06c7432efa54399ae32070c61ac03af2d6f", size = 16292, upload-time = "2024-09-30T21:21:07.606Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/13/29/09468c086fd19f34b00a9698ee9cc1864dfae8c171be140657b965577472/django_rest_knox-5.0.2-py3-none-any.whl", hash = "sha256:694da5d0ad6eb3edbfd7cdc8d69c089fc074e6b0e548e00ff2750bf2fdfadb6f", size = 14960, upload-time = "2024-09-30T21:21:04.896Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django-stubs"
|
||||
version = "5.2.8"
|
||||
@@ -128,6 +178,24 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filelock"
|
||||
version = "3.20.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/58/46/0028a82567109b5ef6e4d2a1f04a583fb513e6cf9527fcdd09afd817deeb/filelock-3.20.0.tar.gz", hash = "sha256:711e943b4ec6be42e1d4e6690b48dc175c822967466bb31c0c293f34334c13f4", size = 18922, upload-time = "2025-10-08T18:03:50.056Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/91/7216b27286936c16f5b4d0c530087e4a54eead683e6b0b73dd0c64844af6/filelock-3.20.0-py3-none-any.whl", hash = "sha256:339b4732ffda5cd79b13f4e2711a31b0365ce445d95d243bb996273d072546a2", size = 16054, upload-time = "2025-10-08T18:03:48.35Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "identify"
|
||||
version = "2.6.15"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ff/e7/685de97986c916a6d93b3876139e00eef26ad5bbbd61925d670ae8013449/identify-2.6.15.tar.gz", hash = "sha256:e4f4864b96c6557ef2a1e1c951771838f4edc9df3a72ec7118b338801b11c7bf", size = 99311, upload-time = "2025-10-02T17:43:40.631Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/1c/e5fd8f973d4f375adb21565739498e2e9a1e54c858a97b9a8ccfdc81da9b/identify-2.6.15-py2.py3-none-any.whl", hash = "sha256:1181ef7608e00704db228516541eb83a88a9f94433a8c80bb9b5bd54b1d81757", size = 99183, upload-time = "2025-10-02T17:43:39.137Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipdb"
|
||||
version = "0.13.13"
|
||||
@@ -198,6 +266,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nodeenv"
|
||||
version = "1.9.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parso"
|
||||
version = "0.8.5"
|
||||
@@ -219,6 +296,31 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "platformdirs"
|
||||
version = "4.5.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pre-commit"
|
||||
version = "4.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cfgv" },
|
||||
{ name = "identify" },
|
||||
{ name = "nodeenv" },
|
||||
{ name = "pyyaml" },
|
||||
{ name = "virtualenv" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f4/9b/6a4ffb4ed980519da959e1cf3122fc6cb41211daa58dbae1c73c0e519a37/pre_commit-4.5.0.tar.gz", hash = "sha256:dc5a065e932b19fc1d4c653c6939068fe54325af8e741e74e88db4d28a4dd66b", size = 198428, upload-time = "2025-11-22T21:02:42.304Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/c4/b2d28e9d2edf4f1713eb3c29307f1a63f3d67cf09bdda29715a36a68921a/pre_commit-4.5.0-py2.py3-none-any.whl", hash = "sha256:25e2ce09595174d9c97860a95609f9f852c0614ba602de3561e267547f2335e1", size = 226429, upload-time = "2025-11-22T21:02:40.836Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prompt-toolkit"
|
||||
version = "3.0.52"
|
||||
@@ -258,6 +360,42 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlparse"
|
||||
version = "0.5.4"
|
||||
@@ -281,6 +419,25 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tornado"
|
||||
version = "6.5.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/09/ce/1eb500eae19f4648281bb2186927bb062d2438c2e5093d1360391afd2f90/tornado-6.5.2.tar.gz", hash = "sha256:ab53c8f9a0fa351e2c0741284e06c7a45da86afb544133201c5cc8578eb076a0", size = 510821, upload-time = "2025-08-08T18:27:00.78Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/48/6a7529df2c9cc12efd2e8f5dd219516184d703b34c06786809670df5b3bd/tornado-6.5.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:2436822940d37cde62771cff8774f4f00b3c8024fe482e16ca8387b8a2724db6", size = 442563, upload-time = "2025-08-08T18:26:42.945Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/b5/9b575a0ed3e50b00c40b08cbce82eb618229091d09f6d14bce80fc01cb0b/tornado-6.5.2-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:583a52c7aa94ee046854ba81d9ebb6c81ec0fd30386d96f7640c96dad45a03ef", size = 440729, upload-time = "2025-08-08T18:26:44.473Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/4e/619174f52b120efcf23633c817fd3fed867c30bff785e2cd5a53a70e483c/tornado-6.5.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0fe179f28d597deab2842b86ed4060deec7388f1fd9c1b4a41adf8af058907e", size = 444295, upload-time = "2025-08-08T18:26:46.021Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/fa/87b41709552bbd393c85dd18e4e3499dcd8983f66e7972926db8d96aa065/tornado-6.5.2-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b186e85d1e3536d69583d2298423744740986018e393d0321df7340e71898882", size = 443644, upload-time = "2025-08-08T18:26:47.625Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/41/fb15f06e33d7430ca89420283a8762a4e6b8025b800ea51796ab5e6d9559/tornado-6.5.2-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e792706668c87709709c18b353da1f7662317b563ff69f00bab83595940c7108", size = 443878, upload-time = "2025-08-08T18:26:50.599Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/92/fe6d57da897776ad2e01e279170ea8ae726755b045fe5ac73b75357a5a3f/tornado-6.5.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:06ceb1300fd70cb20e43b1ad8aaee0266e69e7ced38fa910ad2e03285009ce7c", size = 444549, upload-time = "2025-08-08T18:26:51.864Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/02/c8f4f6c9204526daf3d760f4aa555a7a33ad0e60843eac025ccfd6ff4a93/tornado-6.5.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:74db443e0f5251be86cbf37929f84d8c20c27a355dd452a5cfa2aada0d001ec4", size = 443973, upload-time = "2025-08-08T18:26:53.625Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/2d/f5f5707b655ce2317190183868cd0f6822a1121b4baeae509ceb9590d0bd/tornado-6.5.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b5e735ab2889d7ed33b32a459cac490eda71a1ba6857b0118de476ab6c366c04", size = 443954, upload-time = "2025-08-08T18:26:55.072Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/59/593bd0f40f7355806bf6573b47b8c22f8e1374c9b6fd03114bd6b7a3dcfd/tornado-6.5.2-cp39-abi3-win32.whl", hash = "sha256:c6f29e94d9b37a95013bb669616352ddb82e3bfe8326fccee50583caebc8a5f0", size = 445023, upload-time = "2025-08-08T18:26:56.677Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/2a/f609b420c2f564a748a2d80ebfb2ee02a73ca80223af712fca591386cafb/tornado-6.5.2-cp39-abi3-win_amd64.whl", hash = "sha256:e56a5af51cc30dd2cae649429af65ca2f6571da29504a07995175df14c18f35f", size = 445427, upload-time = "2025-08-08T18:26:57.91Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/4f/e1f65e8f8c76d73658b33d33b81eed4322fb5085350e4328d5c956f0c8f9/tornado-6.5.2-cp39-abi3-win_arm64.whl", hash = "sha256:d6c33dc3672e3a1f3618eb63b7ef4683a7688e7b9e6e8f0d9aa5726360a004af", size = 444456, upload-time = "2025-08-08T18:26:59.207Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "traitlets"
|
||||
version = "5.14.3"
|
||||
@@ -317,6 +474,20 @@ 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 = "virtualenv"
|
||||
version = "20.35.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "distlib" },
|
||||
{ name = "filelock" },
|
||||
{ name = "platformdirs" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/20/28/e6f1a6f655d620846bd9df527390ecc26b3805a0c5989048c210e22c5ca9/virtualenv-20.35.4.tar.gz", hash = "sha256:643d3914d73d3eeb0c552cbb12d7e82adf0e504dbf86a3182f8771a153a1971c", size = 6028799, upload-time = "2025-10-29T06:57:40.511Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/79/0c/c05523fa3181fdf0c9c52a6ba91a23fbf3246cc095f26f6516f9c60e6771/virtualenv-20.35.4-py3-none-any.whl", hash = "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b", size = 6005095, upload-time = "2025-10-29T06:57:37.598Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wcwidth"
|
||||
version = "0.2.14"
|
||||
|
||||
Reference in New Issue
Block a user