Changed directory structure and yapped...a lot
Still can start blabbering like crazy in the HTML if I feel like it.
This commit is contained in:
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# Python-generated files
|
||||
__pycache__/
|
||||
*.py[oc]
|
||||
build/
|
||||
dist/
|
||||
wheels/
|
||||
*.egg-info
|
||||
|
||||
# Virtual environments
|
||||
.venv
|
||||
1
.python-version
Normal file
1
.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.12
|
||||
86
README.md
Normal file
86
README.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# sniph-bank
|
||||
This is a super duper simple web server written in Python (ew) that was done primarily to showcase the difference between HTTP and HTTPS.
|
||||
|
||||
`main-doc.py` is a heavily documented, entire yap-sesh dedicated version of `main.py` that tries to explain the code line-by-line. It assumes you have a little knowledge of the underlying syntax of the language, and outside of the `ServerThread` class, is more focused on HTTP servers and networking than the program specifics.
|
||||
|
||||
|
||||
## Running the Program
|
||||
Ideally, you can run the program on Linux or Windows, and streamline the dependency process with [uv](https://docs.astral.sh/uv/).
|
||||
|
||||
Note that the servers bind to the default, well known ports for HTTP (80) and HTTPS (443).
|
||||
(443).
|
||||
This can be problematic as you sometimes need permissions in order to bind to these ports.
|
||||
When I do the demonstration, I temporarily disable the Linux kernel's restriction to only allow root user to bind to ports below 1024 with `sudo sysctl net.ipv4.ip_unprivileged_port_start=0`. This way, the restrictive behavior is reverted on restart.
|
||||
|
||||
##### Bypassing Port restriction
|
||||
You can edit the constants in `main.py` to set the HTTP_PORT and HTTPS_PORT to something like 8080 and 4443 respectively.
|
||||
|
||||
|
||||
If you have Podman/Docker, you can change the contents of `docker-compose.yml` to be like this instead:
|
||||
```yaml
|
||||
# Example for unprivileged:
|
||||
# - 127.0.0.1:8080:80
|
||||
# - 127.0.0.1:4443:443
|
||||
```
|
||||
|
||||
|
||||
Then when you visit it in the web browser, you have to add the port number, Ex:
|
||||
"http://127.0.0.1:8080" and "https://127.0.0.1:4443"
|
||||
|
||||
### Native Python
|
||||
This assumes you have Python (and Git) installed.
|
||||
Although there's a likelihood you don't even need Python if you use `uv`
|
||||
|
||||
If you don't have `uv` installed, first install it with:
|
||||
|
||||
##### Windows:
|
||||
```powershell
|
||||
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
||||
```
|
||||
|
||||
##### Linux/macOS:
|
||||
```bash
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
```
|
||||
|
||||
Then you can clone the Git repo using
|
||||
```bash
|
||||
git clone {repo_url_here} && cd sniph-bank
|
||||
```
|
||||
> [!TIP]
|
||||
> Alternatively, if you don't have Git installed, you can download the code as a ZIP or tar.gz from the "CODE" button at the top of this repository.
|
||||
> Unzip it and open the terminal in the folder containing all the code.
|
||||
|
||||
From there you can run the program using
|
||||
`uv run main.py`
|
||||
|
||||
`uv` will download the packages within a virtual environment and run the program there too.
|
||||
|
||||
### Podman/Docker
|
||||
[Podman](https://podman.io/) and [Docker](https://www.docker.com/) are both containerization platforms, where Docker is the easier to get installed and more well known, and Podman is the most secure and performant option, while also being compatible with the Docker cli and open-source.
|
||||
These can be used if you want to temporarily run the script within an isolated environment and not on your base system, and will allow you to change the IP address and port the script is listening on by editing the `docker-compose.yml` file rather than the `main.py` file.
|
||||
|
||||
However, I do not offer a simple run-and-done image for this app, so you have to clone the source code either way, and I additionally mount this directory to the container when you run it, so all the files are still stored on your system.
|
||||
To top things off, if you don't have podman-compose installed, you can install it with `uv tool install podman-compose`, so you'd want to have `uv` installed anyway.
|
||||
I might change this before I publish.
|
||||
|
||||
Assuming you have Podman and the [podman-compose](https://github.com/containers/podman-compose) script installed on your system:
|
||||
```bash
|
||||
git clone https://git.foreverpyrite.com/ForeverPyrite/sniph-bank && cd sniph-bank
|
||||
podman compose up -d
|
||||
```
|
||||
|
||||
If you have Docker, you can just run
|
||||
```bash
|
||||
git clone https://git.foreverpyrite.com/ForeverPyrite/sniph-bank && cd sniph-bank
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Why is the repo so large?
|
||||
I still have the `tailwindcss` binary in the `website/css/` directory.
|
||||
I could've got rid of it or put it in .gitignore or ignored it locally or something but nah.
|
||||
There is a very low chance that someone wants to tinker, and in that case (assuming you are in the root of the repo), you can rebuild the CSS with
|
||||
```bash
|
||||
./tw-css/tailwindcss -i tw-css/input.css -o website/css/style.css -w
|
||||
```
|
||||
But you have to be on 64-bit AMD Linux/WSL. Otherwise you gotta download your own.
|
||||
31
certs/cert.pem
Normal file
31
certs/cert.pem
Normal file
@@ -0,0 +1,31 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
52
certs/key.pem
Normal file
52
certs/key.pem
Normal file
@@ -0,0 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
PnJB01jPxh+zzNLkW6lna2jWgXQNeQ==
|
||||
-----END PRIVATE KEY-----
|
||||
16
docker-compose.yml
Normal file
16
docker-compose.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
services:
|
||||
sniph-bank:
|
||||
container_name: sniph-bank
|
||||
image: ghcr.io/astral-sh/uv:debian
|
||||
environment:
|
||||
# This just means that Python's print statements will immediately show up on the console
|
||||
- PYTHONUNBUFFERED=1
|
||||
ports:
|
||||
# You can change the IP and first port number to change what the server listens on on the host.
|
||||
# So if you don't have permission to bind, you could change the first 80 to 8080 and 443 to 4443
|
||||
- 127.0.0.1:80:80
|
||||
- 127.0.0.1:443:443
|
||||
volumes:
|
||||
- ./:/sniph-bank:rw
|
||||
working_dir: /sniph-bank
|
||||
entrypoint: ["uv", "run", "main.py"]
|
||||
243
main-doc.py
Normal file
243
main-doc.py
Normal file
@@ -0,0 +1,243 @@
|
||||
# Hi.
|
||||
# I was tempted to implement my own custom HTTP server to show how an HTTP server works.
|
||||
# But I'm pretty sure that's out of the scope of this demo.
|
||||
# After all, HTTPS is just HTTP with TLS on top of it, and I'm not about to program Diffe-Hellman for this.
|
||||
# Anyways, holy yap sesh.
|
||||
|
||||
# Import the HTTPStatus "enumeration" to have more readable code.
|
||||
# An enumeration is just a thing with multiple diffent possibilities, and there are only so many HTTP
|
||||
# status codes outlined by HTTP specifications.
|
||||
# In reality, HTTP statuses are intentgers, with 1XX-5XX, with the first number dictating the category
|
||||
# of error.
|
||||
# For example, the HTTPStatus.NOT_FOUND would be a 404 error status code,
|
||||
# And a HTTPStatus.OK would be the 200 success status code
|
||||
from http import HTTPStatus
|
||||
|
||||
# This (flask) is the HTTP server library we are using.
|
||||
# Response is the Python object representing what we return to the client
|
||||
# Request is the Python object representing the request from the client
|
||||
# send_file is a function that turns the contents of the specified file into a Response
|
||||
# Flask is the server itself.
|
||||
from flask import Flask, Response, request, send_file
|
||||
|
||||
# Cyrptographically secure, random bits.
|
||||
# On Linux this is reading the bits from the special file /dev/urandom
|
||||
# Less specifically, this uses a lot of the system's entropy (non-deterministic things based off practically
|
||||
# random events, like the users recent mouse movements and secure positions) to generate random bits.
|
||||
from os import urandom
|
||||
|
||||
# The threading library allows you to spawn multiple processes from within this one program.
|
||||
# This is called concurrency, with each Thread being a concurrent process spun from a main thread.
|
||||
# The Thread object represents one of those other Threads within the process.
|
||||
# The Event object just allows for cross-thread communications.
|
||||
# In this program, we will spin two threads up, one for the HTTP server and one for the HTTP server.
|
||||
# We will use the Event object as a way to tell the servers to shut down.
|
||||
from threading import Thread, Event
|
||||
|
||||
# The make_server function is just a sort of wrapper for the HTTP server to allow things like shutting down
|
||||
# the server through a function call. Normally the call to run a Flask server is blocking I believe,
|
||||
# meaning it stops program execution until it returns, which doesn't happen under normal circumstances.
|
||||
from werkzeug.serving import make_server
|
||||
|
||||
# This is for type hinting. This is mostly for me, so that I know the type that each variable should be.
|
||||
# Optional means that it can either be the None object, or whatever is within the brackets following the
|
||||
# "Optional" type hint.
|
||||
# For example, Optional[str] means that the value will either be None or a string.
|
||||
from typing import Optional
|
||||
|
||||
# More type hinting...
|
||||
from types import FrameType
|
||||
|
||||
# This is what allows us to handle signals like Ctrl+C (SIGINT), which we will use to trigger the Event
|
||||
# for the Threads to know to shut the server down
|
||||
import signal
|
||||
|
||||
# We only use this as a way to tell the system the program excuted sucessfully, and as intented.
|
||||
import sys
|
||||
|
||||
# Used as a way to encode the password, or way of "hashing" it.
|
||||
from base64 import b64encode as base64_encode
|
||||
|
||||
# The IP address the server will listen on.
|
||||
SERVER_IP: str = "127.0.0.1"
|
||||
# The exepected HTTP host header.
|
||||
# This can use used to only response if the URL in the web browser contains "sniphbank.com"
|
||||
# rather than accessing the IP (127.0.0.1) directly. Right now, this is not enabled.
|
||||
HTTP_HOST: str = "sniphbank.com"
|
||||
# The port for the HTTP socket.
|
||||
# 80 is the default port, and what the browser automatically connects to when given "http://"
|
||||
HTTP_PORT: int = 80
|
||||
# The port for the HTTPS socket.
|
||||
# 443 is the default port, and what the browser automatically connects to when given "https://"
|
||||
HTTPS_PORT: int = 443
|
||||
# This will be used to tell the Flask server whether or not it should be running in Debug mode.
|
||||
DEBUG: bool = False
|
||||
|
||||
# Required to be in global scope
|
||||
# The Flask server itself.
|
||||
app = Flask(__name__)
|
||||
# A secret key required for secure operations.
|
||||
app.secret_key = urandom(24)
|
||||
|
||||
|
||||
# The logic for what happens when someone visits the root of the HTTP server, so
|
||||
# "http(s)://sniphbank.com", as the browser automatically requests "/"
|
||||
@app.route("/")
|
||||
def index():
|
||||
# We simply return the contents of the index.html file stored in the "website" directory in this
|
||||
# projects structure.
|
||||
return send_file("./website/index.html")
|
||||
|
||||
|
||||
# The logic for when a user clicks on the "submit" button.
|
||||
# The HTML login form's submit button sends an HTTP "POST" to "/login", and the response is then
|
||||
# awaited for as if you clicked on a link to a new page.
|
||||
@app.route("/login", methods=["POST"])
|
||||
def login():
|
||||
# There isn't really a reason to validate the user for the demo,
|
||||
# just decide on a username that might pertain to whomever's
|
||||
# personal information
|
||||
|
||||
# The "user" input field in the HTML form.
|
||||
user = request.form["username"]
|
||||
# Likewise, the "password" input field in the HTML form.
|
||||
# We turn this into bytes so we can encode it with base64
|
||||
password = request.form["password"].encode()
|
||||
|
||||
# In a real web application, the values are pulled from a database and not hardcoded.
|
||||
# If the username is not "ronniej"
|
||||
if user != "ronniej":
|
||||
# Then we return the respponse "User not found" with the HTTP 401 status code (UNAUTHORIZED)
|
||||
return Response("User not found", HTTPStatus.UNAUTHORIZED)
|
||||
# Also in a real application, the password will be hashed rather than merely base64 encoded.
|
||||
# The difference with it being hashed is that it's easly reversable, someone with access to this
|
||||
# code (or in a real case, a database) would be able to easily reverse this to get the genuine
|
||||
# password.
|
||||
# The point of this here is to showcase that password is in plaintext until it gets to the server.
|
||||
if base64_encode(password).decode() != "Z29GQUxDT05TMTIzCg==":
|
||||
# Likewise if the password doesn't match, we return a similar response.
|
||||
return Response("Incorrect password", HTTPStatus.UNAUTHORIZED)
|
||||
|
||||
# In order to get this far, the username and password are correct, so we can send the webpage.
|
||||
return send_file("./website/account.html")
|
||||
|
||||
|
||||
# CSS, or Cascading Style Sheets, is the very thing that makes the web useable.
|
||||
# Otherwise, every element in HTML (Hypertext Markup Language, NOT a programming language)
|
||||
# would be completely black text on white background, and blocks placed top to bottom
|
||||
# If you wanna try it yourself, feel free to run this code and rename/move/change the file path
|
||||
# below. The server will return a "404: Not Found" error and the browser won't be able to render
|
||||
# the webpage as expected.
|
||||
@app.route("/css/style.css", methods=["GET"])
|
||||
def stylesheet():
|
||||
return send_file("./website/css/style.css")
|
||||
|
||||
|
||||
# Very similar, the favicon.ico is automatically requested from the server by the Web Browser
|
||||
# This is the lil icon that is displayed on the tab next to the HTML page's title.
|
||||
@app.route("/favicon.ico", methods=["GET"])
|
||||
def favicon():
|
||||
return send_file("./website/favicon.ico")
|
||||
|
||||
|
||||
# This is a lil fancy, but I thought it was a fair obstraction to handle the threading in a...more...
|
||||
# "readable" way...?
|
||||
# Basically, we are creating a class that is based off the "Thread" class, so it shares the same properties
|
||||
# and methods.
|
||||
# Here, we are going to add some things to it, for example, the Flask server, the IP and port we want
|
||||
# to listen on, and the SSL Context if we are using HTTPS
|
||||
class ServerThread(Thread):
|
||||
def __init__(
|
||||
self,
|
||||
app: Flask,
|
||||
host: str,
|
||||
port: int,
|
||||
ssl_context: Optional[tuple[str, str]] = None,
|
||||
name: str = "ServerThread",
|
||||
) -> None:
|
||||
super().__init__(name=name, daemon=True)
|
||||
# threaded=True is telling the werkzeug server that it can use threads to handle multiple
|
||||
# requests at the same time. Not really important for the demo I don't think, and I'll
|
||||
# likely get rid of it.
|
||||
self.server = make_server(
|
||||
host,
|
||||
port,
|
||||
app,
|
||||
threaded=True,
|
||||
# This is either None or the public SSL cert and private key (or is it the other way around...?)
|
||||
ssl_context=ssl_context, # tuple (cert, key) or SSLContext
|
||||
)
|
||||
|
||||
def run(self):
|
||||
# serve_forever blocks until shutdown() is called
|
||||
self.server.serve_forever()
|
||||
|
||||
def shutdown(self):
|
||||
self.server.shutdown()
|
||||
|
||||
|
||||
def _install_signal_handlers(stop_event: Event):
|
||||
def handler(signum: signal.Signals, frame: Optional[FrameType]):
|
||||
stop_event.set()
|
||||
|
||||
# Handle Ctrl+C and SIGTERM
|
||||
signal.signal(signal.SIGINT, handler)
|
||||
try:
|
||||
signal.signal(signal.SIGTERM, handler)
|
||||
except AttributeError:
|
||||
# SIGTERM may not be available on some platforms (e.g., Windows Python in some contexts)
|
||||
# I'm always on Linux, so if you wanna run this, then you should either use WSL or Podman.
|
||||
# (Podman is a generally more performant and secure alternative to Docker, if you are familiar)
|
||||
pass
|
||||
|
||||
|
||||
# This block literally just says "If this is the program being run, do the following"
|
||||
if __name__ == "__main__":
|
||||
# Create the stop event
|
||||
stop_event = Event()
|
||||
# Install the signal handler for SIGINT (Ctrl+C signal)
|
||||
_install_signal_handlers(stop_event)
|
||||
|
||||
# Our HTTP server thread.
|
||||
http_server = ServerThread(
|
||||
app, SERVER_IP, HTTP_PORT, ssl_context=None, name="HTTP-Thread"
|
||||
)
|
||||
# Similarly, the HTTPS server thread.
|
||||
https_server = ServerThread(
|
||||
app,
|
||||
SERVER_IP,
|
||||
HTTPS_PORT,
|
||||
ssl_context=("./certs/cert.pem", "./certs/key.pem"),
|
||||
name="HTTPS-Thread",
|
||||
)
|
||||
|
||||
try:
|
||||
# Start the HTTP and HTTPS server threads
|
||||
http_server.start()
|
||||
https_server.start()
|
||||
# Make sure there's some output to show that the servers running.
|
||||
print(f"HTTP server running at http://{SERVER_IP}:{HTTP_PORT}")
|
||||
print(f"HTTPS server running at https://{SERVER_IP}:{HTTPS_PORT}")
|
||||
print("Press Ctrl+C to stop.")
|
||||
# Wait until a signal requests shutdown
|
||||
stop_event.wait()
|
||||
except KeyboardInterrupt:
|
||||
# Typically how you handle Ctrl+C, but since we have a singal hanlder it's pointless.
|
||||
# Doesn't hurt anyone though.
|
||||
pass
|
||||
finally:
|
||||
# Stop both servers.
|
||||
for srv in (http_server, https_server):
|
||||
try:
|
||||
srv.shutdown()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Join both Threads (meaning take their execution and join it with the main thread's).
|
||||
for srv in (http_server, https_server):
|
||||
srv.join(timeout=5)
|
||||
|
||||
# Output that the servers shut down gracefully (enough)
|
||||
print("Servers stopped!")
|
||||
# This just tells the shell that "hey, we exited as expected."
|
||||
sys.exit(0)
|
||||
125
main.py
Normal file
125
main.py
Normal file
@@ -0,0 +1,125 @@
|
||||
from http import HTTPStatus
|
||||
from flask import Flask, Response, request, send_file
|
||||
from os import urandom
|
||||
from threading import Thread, Event
|
||||
from werkzeug.serving import make_server
|
||||
from typing import Optional
|
||||
from types import FrameType
|
||||
import signal
|
||||
import sys
|
||||
from base64 import b64encode as base64_encode
|
||||
|
||||
SERVER_IP: str = "0.0.0.0"
|
||||
HTTP_HOST: str = "sniphbank.com"
|
||||
HTTP_PORT: int = 80
|
||||
HTTPS_PORT: int = 443
|
||||
DEBUG: bool = False
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = urandom(24)
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
return send_file("./website/index.html")
|
||||
|
||||
|
||||
@app.route("/login", methods=["POST"])
|
||||
def login():
|
||||
# There isn't really a reason to validate the user for the demo,
|
||||
# just decide on a username that might pertain to whomever's
|
||||
# personal information
|
||||
|
||||
user = request.form["username"]
|
||||
password = request.form["password"].encode()
|
||||
|
||||
if user != "ronniej":
|
||||
return Response("User not found", HTTPStatus.UNAUTHORIZED)
|
||||
if base64_encode(password).decode() != "Z29GQUxDT05TMTIzCg==":
|
||||
return Response("Incorrect password", HTTPStatus.UNAUTHORIZED)
|
||||
|
||||
return send_file("./website/account.html")
|
||||
|
||||
|
||||
@app.route("/css/style.css", methods=["GET"])
|
||||
def stylesheet():
|
||||
return send_file("./website/css/style.css")
|
||||
|
||||
|
||||
@app.route("/favicon.ico", methods=["GET"])
|
||||
def favicon():
|
||||
return send_file("./website/favicon.ico")
|
||||
|
||||
|
||||
class ServerThread(Thread):
|
||||
def __init__(
|
||||
self,
|
||||
app: Flask,
|
||||
host: str,
|
||||
port: int,
|
||||
ssl_context: Optional[tuple[str, str]] = None,
|
||||
name: str = "ServerThread",
|
||||
) -> None:
|
||||
super().__init__(name=name, daemon=True)
|
||||
self.server = make_server(
|
||||
host,
|
||||
port,
|
||||
app,
|
||||
threaded=True,
|
||||
ssl_context=ssl_context, # tuple (cert, key) or SSLContext
|
||||
)
|
||||
|
||||
def run(self):
|
||||
self.server.serve_forever()
|
||||
|
||||
def shutdown(self):
|
||||
self.server.shutdown()
|
||||
|
||||
|
||||
def _install_signal_handlers(stop_event: Event):
|
||||
def handler(signum: signal.Signals, frame: Optional[FrameType]):
|
||||
stop_event.set()
|
||||
|
||||
signal.signal(signal.SIGINT, handler)
|
||||
try:
|
||||
signal.signal(signal.SIGTERM, handler)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
stop_event = Event()
|
||||
_install_signal_handlers(stop_event)
|
||||
|
||||
http_server = ServerThread(
|
||||
app, SERVER_IP, HTTP_PORT, ssl_context=None, name="HTTP-Thread"
|
||||
)
|
||||
https_server = ServerThread(
|
||||
app,
|
||||
SERVER_IP,
|
||||
HTTPS_PORT,
|
||||
ssl_context=("./certs/cert.pem", "./certs/key.pem"),
|
||||
name="HTTPS-Thread",
|
||||
)
|
||||
|
||||
try:
|
||||
http_server.start()
|
||||
https_server.start()
|
||||
print(f"HTTP server running at http://{SERVER_IP}:{HTTP_PORT}")
|
||||
print(f"HTTPS server running at https://{SERVER_IP}:{HTTPS_PORT}")
|
||||
print("Press Ctrl+C to stop.")
|
||||
stop_event.wait()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
finally:
|
||||
for srv in (http_server, https_server):
|
||||
try:
|
||||
srv.shutdown()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
for srv in (http_server, https_server):
|
||||
srv.join(timeout=5)
|
||||
|
||||
print("Servers stopped!")
|
||||
sys.exit(0)
|
||||
10
pyproject.toml
Normal file
10
pyproject.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[project]
|
||||
name = "sniph-bank"
|
||||
version = "0.1.3"
|
||||
description = "Simple 'website' to demonstrate HTTP vs HTTPS"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"flask>=3.1.2",
|
||||
"pyopenssl>=25.3.0",
|
||||
]
|
||||
93
tw-css/daisyui-theme.mjs
Normal file
93
tw-css/daisyui-theme.mjs
Normal file
File diff suppressed because one or more lines are too long
1040
tw-css/daisyui.mjs
Normal file
1040
tw-css/daisyui.mjs
Normal file
File diff suppressed because one or more lines are too long
9
tw-css/input.css
Normal file
9
tw-css/input.css
Normal file
@@ -0,0 +1,9 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@source not "./tailwindcss";
|
||||
@source not "./daisyui{,*}.mjs";
|
||||
@source "../*.html";
|
||||
|
||||
@plugin "./daisyui.mjs" {
|
||||
themes: dark --default --prefersdark;
|
||||
}
|
||||
BIN
tw-css/tailwindcss
Executable file
BIN
tw-css/tailwindcss
Executable file
Binary file not shown.
305
uv.lock
generated
Normal file
305
uv.lock
generated
Normal file
@@ -0,0 +1,305 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "blinker"
|
||||
version = "1.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460, upload-time = "2024-11-08T17:25:47.436Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cffi"
|
||||
version = "2.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pycparser", marker = "implementation_name != 'PyPy'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/46/61/de6cd827efad202d7057d93e0fed9294b96952e188f7384832791c7b2254/click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4", size = 276943, upload-time = "2025-09-18T17:32:23.696Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", size = 107295, upload-time = "2025-09-18T17:32:22.42Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
||||
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 = "cryptography"
|
||||
version = "46.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9f/33/c00162f49c0e2fe8064a62cb92b93e50c74a72bc370ab92f86112b33ff62/cryptography-46.0.3.tar.gz", hash = "sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1", size = 749258, upload-time = "2025-10-15T23:18:31.74Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/42/9c391dd801d6cf0d561b5890549d4b27bafcc53b39c31a817e69d87c625b/cryptography-46.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:109d4ddfadf17e8e7779c39f9b18111a09efb969a301a31e987416a0191ed93a", size = 7225004, upload-time = "2025-10-15T23:16:52.239Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/67/38769ca6b65f07461eb200e85fc1639b438bdc667be02cf7f2cd6a64601c/cryptography-46.0.3-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:09859af8466b69bc3c27bdf4f5d84a665e0f7ab5088412e9e2ec49758eca5cbc", size = 4296667, upload-time = "2025-10-15T23:16:54.369Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/49/498c86566a1d80e978b42f0d702795f69887005548c041636df6ae1ca64c/cryptography-46.0.3-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:01ca9ff2885f3acc98c29f1860552e37f6d7c7d013d7334ff2a9de43a449315d", size = 4450807, upload-time = "2025-10-15T23:16:56.414Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/0a/863a3604112174c8624a2ac3c038662d9e59970c7f926acdcfaed8d61142/cryptography-46.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6eae65d4c3d33da080cff9c4ab1f711b15c1d9760809dad6ea763f3812d254cb", size = 4299615, upload-time = "2025-10-15T23:16:58.442Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/02/b73a533f6b64a69f3cd3872acb6ebc12aef924d8d103133bb3ea750dc703/cryptography-46.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5bf0ed4490068a2e72ac03d786693adeb909981cc596425d09032d372bcc849", size = 4016800, upload-time = "2025-10-15T23:17:00.378Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/d5/16e41afbfa450cde85a3b7ec599bebefaef16b5c6ba4ec49a3532336ed72/cryptography-46.0.3-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:5ecfccd2329e37e9b7112a888e76d9feca2347f12f37918facbb893d7bb88ee8", size = 4984707, upload-time = "2025-10-15T23:17:01.98Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/56/e7e69b427c3878352c2fb9b450bd0e19ed552753491d39d7d0a2f5226d41/cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a2c0cd47381a3229c403062f764160d57d4d175e022c1df84e168c6251a22eec", size = 4482541, upload-time = "2025-10-15T23:17:04.078Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/f6/50736d40d97e8483172f1bb6e698895b92a223dba513b0ca6f06b2365339/cryptography-46.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:549e234ff32571b1f4076ac269fcce7a808d3bf98b76c8dd560e42dbc66d7d91", size = 4299464, upload-time = "2025-10-15T23:17:05.483Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/de/d8e26b1a855f19d9994a19c702fa2e93b0456beccbcfe437eda00e0701f2/cryptography-46.0.3-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:c0a7bb1a68a5d3471880e264621346c48665b3bf1c3759d682fc0864c540bd9e", size = 4950838, upload-time = "2025-10-15T23:17:07.425Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/29/798fc4ec461a1c9e9f735f2fc58741b0daae30688f41b2497dcbc9ed1355/cryptography-46.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:10b01676fc208c3e6feeb25a8b83d81767e8059e1fe86e1dc62d10a3018fa926", size = 4481596, upload-time = "2025-10-15T23:17:09.343Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/8d/03cd48b20a573adfff7652b76271078e3045b9f49387920e7f1f631d125e/cryptography-46.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0abf1ffd6e57c67e92af68330d05760b7b7efb243aab8377e583284dbab72c71", size = 4426782, upload-time = "2025-10-15T23:17:11.22Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/b1/ebacbfe53317d55cf33165bda24c86523497a6881f339f9aae5c2e13e57b/cryptography-46.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a04bee9ab6a4da801eb9b51f1b708a1b5b5c9eb48c03f74198464c66f0d344ac", size = 4698381, upload-time = "2025-10-15T23:17:12.829Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/92/8a6a9525893325fc057a01f654d7efc2c64b9de90413adcf605a85744ff4/cryptography-46.0.3-cp311-abi3-win32.whl", hash = "sha256:f260d0d41e9b4da1ed1e0f1ce571f97fe370b152ab18778e9e8f67d6af432018", size = 3055988, upload-time = "2025-10-15T23:17:14.65Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/bf/80fbf45253ea585a1e492a6a17efcb93467701fa79e71550a430c5e60df0/cryptography-46.0.3-cp311-abi3-win_amd64.whl", hash = "sha256:a9a3008438615669153eb86b26b61e09993921ebdd75385ddd748702c5adfddb", size = 3514451, upload-time = "2025-10-15T23:17:16.142Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/af/9b302da4c87b0beb9db4e756386a7c6c5b8003cd0e742277888d352ae91d/cryptography-46.0.3-cp311-abi3-win_arm64.whl", hash = "sha256:5d7f93296ee28f68447397bf5198428c9aeeab45705a55d53a6343455dcb2c3c", size = 2928007, upload-time = "2025-10-15T23:17:18.04Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/e2/a510aa736755bffa9d2f75029c229111a1d02f8ecd5de03078f4c18d91a3/cryptography-46.0.3-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:00a5e7e87938e5ff9ff5447ab086a5706a957137e6e433841e9d24f38a065217", size = 7158012, upload-time = "2025-10-15T23:17:19.982Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/73/dc/9aa866fbdbb95b02e7f9d086f1fccfeebf8953509b87e3f28fff927ff8a0/cryptography-46.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c8daeb2d2174beb4575b77482320303f3d39b8e81153da4f0fb08eb5fe86a6c5", size = 4288728, upload-time = "2025-10-15T23:17:21.527Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/fd/bc1daf8230eaa075184cbbf5f8cd00ba9db4fd32d63fb83da4671b72ed8a/cryptography-46.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:39b6755623145ad5eff1dab323f4eae2a32a77a7abef2c5089a04a3d04366715", size = 4435078, upload-time = "2025-10-15T23:17:23.042Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/98/d3bd5407ce4c60017f8ff9e63ffee4200ab3e23fe05b765cab805a7db008/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:db391fa7c66df6762ee3f00c95a89e6d428f4d60e7abc8328f4fe155b5ac6e54", size = 4293460, upload-time = "2025-10-15T23:17:24.885Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/e9/e23e7900983c2b8af7a08098db406cf989d7f09caea7897e347598d4cd5b/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:78a97cf6a8839a48c49271cdcbd5cf37ca2c1d6b7fdd86cc864f302b5e9bf459", size = 3995237, upload-time = "2025-10-15T23:17:26.449Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/15/af68c509d4a138cfe299d0d7ddb14afba15233223ebd933b4bbdbc7155d3/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:dfb781ff7eaa91a6f7fd41776ec37c5853c795d3b358d4896fdbb5df168af422", size = 4967344, upload-time = "2025-10-15T23:17:28.06Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/e3/8643d077c53868b681af077edf6b3cb58288b5423610f21c62aadcbe99f4/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:6f61efb26e76c45c4a227835ddeae96d83624fb0d29eb5df5b96e14ed1a0afb7", size = 4466564, upload-time = "2025-10-15T23:17:29.665Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/43/c1e8726fa59c236ff477ff2b5dc071e54b21e5a1e51aa2cee1676f1c986f/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:23b1a8f26e43f47ceb6d6a43115f33a5a37d57df4ea0ca295b780ae8546e8044", size = 4292415, upload-time = "2025-10-15T23:17:31.686Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/f9/2f8fefdb1aee8a8e3256a0568cffc4e6d517b256a2fe97a029b3f1b9fe7e/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b419ae593c86b87014b9be7396b385491ad7f320bde96826d0dd174459e54665", size = 4931457, upload-time = "2025-10-15T23:17:33.478Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/30/9b54127a9a778ccd6d27c3da7563e9f2d341826075ceab89ae3b41bf5be2/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:50fc3343ac490c6b08c0cf0d704e881d0d660be923fd3076db3e932007e726e3", size = 4466074, upload-time = "2025-10-15T23:17:35.158Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/68/b4f4a10928e26c941b1b6a179143af9f4d27d88fe84a6a3c53592d2e76bf/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22d7e97932f511d6b0b04f2bfd818d73dcd5928db509460aaf48384778eb6d20", size = 4420569, upload-time = "2025-10-15T23:17:37.188Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/49/3746dab4c0d1979888f125226357d3262a6dd40e114ac29e3d2abdf1ec55/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d55f3dffadd674514ad19451161118fd010988540cee43d8bc20675e775925de", size = 4681941, upload-time = "2025-10-15T23:17:39.236Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/30/27654c1dbaf7e4a3531fa1fc77986d04aefa4d6d78259a62c9dc13d7ad36/cryptography-46.0.3-cp314-cp314t-win32.whl", hash = "sha256:8a6e050cb6164d3f830453754094c086ff2d0b2f3a897a1d9820f6139a1f0914", size = 3022339, upload-time = "2025-10-15T23:17:40.888Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/30/640f34ccd4d2a1bc88367b54b926b781b5a018d65f404d409aba76a84b1c/cryptography-46.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:760f83faa07f8b64e9c33fc963d790a2edb24efb479e3520c14a45741cd9b2db", size = 3494315, upload-time = "2025-10-15T23:17:42.769Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/8b/88cc7e3bd0a8e7b861f26981f7b820e1f46aa9d26cc482d0feba0ecb4919/cryptography-46.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:516ea134e703e9fe26bcd1277a4b59ad30586ea90c365a87781d7887a646fe21", size = 2919331, upload-time = "2025-10-15T23:17:44.468Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/23/45fe7f376a7df8daf6da3556603b36f53475a99ce4faacb6ba2cf3d82021/cryptography-46.0.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:cb3d760a6117f621261d662bccc8ef5bc32ca673e037c83fbe565324f5c46936", size = 7218248, upload-time = "2025-10-15T23:17:46.294Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/32/b68d27471372737054cbd34c84981f9edbc24fe67ca225d389799614e27f/cryptography-46.0.3-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4b7387121ac7d15e550f5cb4a43aef2559ed759c35df7336c402bb8275ac9683", size = 4294089, upload-time = "2025-10-15T23:17:48.269Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/42/fa8389d4478368743e24e61eea78846a0006caffaf72ea24a15159215a14/cryptography-46.0.3-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:15ab9b093e8f09daab0f2159bb7e47532596075139dd74365da52ecc9cb46c5d", size = 4440029, upload-time = "2025-10-15T23:17:49.837Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/eb/f483db0ec5ac040824f269e93dd2bd8a21ecd1027e77ad7bdf6914f2fd80/cryptography-46.0.3-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:46acf53b40ea38f9c6c229599a4a13f0d46a6c3fa9ef19fc1a124d62e338dfa0", size = 4297222, upload-time = "2025-10-15T23:17:51.357Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/cf/da9502c4e1912cb1da3807ea3618a6829bee8207456fbbeebc361ec38ba3/cryptography-46.0.3-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10ca84c4668d066a9878890047f03546f3ae0a6b8b39b697457b7757aaf18dbc", size = 4012280, upload-time = "2025-10-15T23:17:52.964Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/8f/9adb86b93330e0df8b3dcf03eae67c33ba89958fc2e03862ef1ac2b42465/cryptography-46.0.3-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:36e627112085bb3b81b19fed209c05ce2a52ee8b15d161b7c643a7d5a88491f3", size = 4978958, upload-time = "2025-10-15T23:17:54.965Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/a0/5fa77988289c34bdb9f913f5606ecc9ada1adb5ae870bd0d1054a7021cc4/cryptography-46.0.3-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1000713389b75c449a6e979ffc7dcc8ac90b437048766cef052d4d30b8220971", size = 4473714, upload-time = "2025-10-15T23:17:56.754Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/e5/fc82d72a58d41c393697aa18c9abe5ae1214ff6f2a5c18ac470f92777895/cryptography-46.0.3-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:b02cf04496f6576afffef5ddd04a0cb7d49cf6be16a9059d793a30b035f6b6ac", size = 4296970, upload-time = "2025-10-15T23:17:58.588Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/06/5663ed35438d0b09056973994f1aec467492b33bd31da36e468b01ec1097/cryptography-46.0.3-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:71e842ec9bc7abf543b47cf86b9a743baa95f4677d22baa4c7d5c69e49e9bc04", size = 4940236, upload-time = "2025-10-15T23:18:00.897Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/59/873633f3f2dcd8a053b8dd1d38f783043b5fce589c0f6988bf55ef57e43e/cryptography-46.0.3-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:402b58fc32614f00980b66d6e56a5b4118e6cb362ae8f3fda141ba4689bd4506", size = 4472642, upload-time = "2025-10-15T23:18:02.749Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/39/8e71f3930e40f6877737d6f69248cf74d4e34b886a3967d32f919cc50d3b/cryptography-46.0.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ef639cb3372f69ec44915fafcd6698b6cc78fbe0c2ea41be867f6ed612811963", size = 4423126, upload-time = "2025-10-15T23:18:04.85Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/c7/f65027c2810e14c3e7268353b1681932b87e5a48e65505d8cc17c99e36ae/cryptography-46.0.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b51b8ca4f1c6453d8829e1eb7299499ca7f313900dd4d89a24b8b87c0a780d4", size = 4686573, upload-time = "2025-10-15T23:18:06.908Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/6e/1c8331ddf91ca4730ab3086a0f1be19c65510a33b5a441cb334e7a2d2560/cryptography-46.0.3-cp38-abi3-win32.whl", hash = "sha256:6276eb85ef938dc035d59b87c8a7dc559a232f954962520137529d77b18ff1df", size = 3036695, upload-time = "2025-10-15T23:18:08.672Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/90/45/b0d691df20633eff80955a0fc7695ff9051ffce8b69741444bd9ed7bd0db/cryptography-46.0.3-cp38-abi3-win_amd64.whl", hash = "sha256:416260257577718c05135c55958b674000baef9a1c7d9e8f306ec60d71db850f", size = 3501720, upload-time = "2025-10-15T23:18:10.632Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/cb/2da4cc83f5edb9c3257d09e1e7ab7b23f049c7962cae8d842bbef0a9cec9/cryptography-46.0.3-cp38-abi3-win_arm64.whl", hash = "sha256:d89c3468de4cdc4f08a57e214384d0471911a3830fcdaf7a8cc587e42a866372", size = 2918740, upload-time = "2025-10-15T23:18:12.277Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flask"
|
||||
version = "3.1.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "blinker" },
|
||||
{ name = "click" },
|
||||
{ name = "itsdangerous" },
|
||||
{ name = "jinja2" },
|
||||
{ name = "markupsafe" },
|
||||
{ name = "werkzeug" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/dc/6d/cfe3c0fcc5e477df242b98bfe186a4c34357b4847e87ecaef04507332dab/flask-3.1.2.tar.gz", hash = "sha256:bf656c15c80190ed628ad08cdfd3aaa35beb087855e2f494910aa3774cc4fd87", size = 720160, upload-time = "2025-08-19T21:03:21.205Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/f9/7f9263c5695f4bd0023734af91bedb2ff8209e8de6ead162f35d8dc762fd/flask-3.1.2-py3-none-any.whl", hash = "sha256:ca1d8112ec8a6158cc29ea4858963350011b5c846a414cdb7a954aa9e967d03c", size = 103308, upload-time = "2025-08-19T21:03:19.499Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itsdangerous"
|
||||
version = "2.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410, upload-time = "2024-04-16T21:28:15.614Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234, upload-time = "2024-04-16T21:28:14.499Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jinja2"
|
||||
version = "3.1.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markupsafe" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markupsafe"
|
||||
version = "3.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycparser"
|
||||
version = "2.23"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyopenssl"
|
||||
version = "25.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cryptography" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/80/be/97b83a464498a79103036bc74d1038df4a7ef0e402cfaf4d5e113fb14759/pyopenssl-25.3.0.tar.gz", hash = "sha256:c981cb0a3fd84e8602d7afc209522773b94c1c2446a3c710a75b06fe1beae329", size = 184073, upload-time = "2025-09-17T00:32:21.037Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/81/ef2b1dfd1862567d573a4fdbc9f969067621764fbb74338496840a1d2977/pyopenssl-25.3.0-py3-none-any.whl", hash = "sha256:1fda6fc034d5e3d179d39e59c1895c9faeaf40a79de5fc4cbbfbe0d36f4a77b6", size = 57268, upload-time = "2025-09-17T00:32:19.474Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sniph-bank"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "flask" },
|
||||
{ name = "pyopenssl" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "flask", specifier = ">=3.1.2" },
|
||||
{ name = "pyopenssl", specifier = ">=25.3.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.15.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "werkzeug"
|
||||
version = "3.1.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markupsafe" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", size = 806925, upload-time = "2024-11-08T15:52:18.093Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498, upload-time = "2024-11-08T15:52:16.132Z" },
|
||||
]
|
||||
145
website/account.html
Normal file
145
website/account.html
Normal file
@@ -0,0 +1,145 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Account Dashboard - Sniph Bank</title>
|
||||
<link href="./css/style.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-base-200 min-h-[100vh] min-w-[100vw]">
|
||||
|
||||
<!-- Navigation Bar -->
|
||||
<header class="navbar bg-base-100 shadow-lg">
|
||||
<div class="flex-1">
|
||||
<a class="btn btn-ghost text-2xl text-primary">Sniph Bank</a>
|
||||
</div>
|
||||
<div class="flex-none gap-2">
|
||||
<div class="text-right hidden sm:block">
|
||||
<p class="font-bold">Welcome, Alex Doe</p>
|
||||
<p class="text-xs">Last login: Today at 10:45 AM</p>
|
||||
</div>
|
||||
<div class="dropdown dropdown-end">
|
||||
<ul tabindex="0" class="mt-3 z-[1] p-2 shadow menu menu-sm dropdown-content bg-base-100 rounded-box w-52">
|
||||
<li><a class="justify-between">Profile</a></li>
|
||||
<li><a>Settings</a></li>
|
||||
<li><a>Logout</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Main Content Area -->
|
||||
<main class="p-4 md:p-8">
|
||||
<div class="container mx-auto grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
|
||||
<!-- Left Column: Account Summary -->
|
||||
<div class="lg:col-span-2 space-y-8">
|
||||
|
||||
<!-- Balance Summary Card -->
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title text-xl">Account Summary</h2>
|
||||
<div class="stats stats-vertical md:stats-horizontal shadow w-full">
|
||||
<div class="stat">
|
||||
<div class="stat-title">Checking Balance</div>
|
||||
<div class="stat-value text-success">$8,321.45</div>
|
||||
<div class="stat-desc">Acct: ****6789</div>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="stat-title">Savings Balance</div>
|
||||
<div class="stat-value text-info">$22,150.10</div>
|
||||
<div class="stat-desc">Acct: ****4321</div>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="stat-title">Credit Card Due</div>
|
||||
<div class="stat-value text-error">-$789.99</div>
|
||||
<div class="stat-desc">Due in 15 days</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-actions justify-end mt-4">
|
||||
<button class="btn btn-primary">Transfer Funds</button>
|
||||
<button class="btn">Pay Bills</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Transactions Card -->
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title text-xl">Recent Transactions</h2>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Description</th>
|
||||
<th class="text-right">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Transaction Row 1 -->
|
||||
<tr>
|
||||
<td>Oct 26, 2023</td>
|
||||
<td>Direct Deposit - ACME CORP</td>
|
||||
<td class="text-right text-success font-bold">+$2,500.00</td>
|
||||
</tr>
|
||||
<!-- Transaction Row 2 -->
|
||||
<tr>
|
||||
<td>Oct 25, 2023</td>
|
||||
<td>Online Purchase - Scamazon.com</td>
|
||||
<td class="text-right text-error">-$124.50</td>
|
||||
</tr>
|
||||
<!-- Transaction Row 3 -->
|
||||
<tr>
|
||||
<td>Oct 24, 2023</td>
|
||||
<td>Ether Grocery</td>
|
||||
<td class="text-right text-error">-$88.12</td>
|
||||
</tr>
|
||||
<!-- Transaction Row 4 -->
|
||||
<tr>
|
||||
<td>Oct 22, 2023</td>
|
||||
<td>ATM Withdrawal - Downtown</td>
|
||||
<td class="text-right text-error">-$100.00</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Column: Sensitive Information -->
|
||||
<div class="space-y-8">
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title text-xl">Personal & Account Details</h2>
|
||||
<p class="text-warning text-sm">This information is highly sensitive.</p>
|
||||
|
||||
<div class="mt-4 space-y-2">
|
||||
<p><strong>Full Name:</strong>
|
||||
Alex M. Doe</p>
|
||||
<p><strong>Address:</strong>
|
||||
123 Phishing Lane, Anytown, USA 12345</p>
|
||||
<p><strong>Phone:</strong>
|
||||
(555) 123-4567</p>
|
||||
<p><strong>SSN:</strong>
|
||||
<span class="kbd kbd-sm font-mono">***-**-6789</span></p>
|
||||
</div>
|
||||
|
||||
<div class="divider">Account Numbers</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<p><strong>Checking Acct #:</strong>
|
||||
<span class="kbd kbd-sm font-mono">123456789</span></p>
|
||||
<p><strong>Savings Acct #:</strong>
|
||||
<span class="kbd kbd-sm font-mono">987654321</span></p>
|
||||
<p><strong>Routing #:</strong>
|
||||
<span class="kbd kbd-sm font-mono">021000021</span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
1833
website/css/style.css
Normal file
1833
website/css/style.css
Normal file
File diff suppressed because it is too large
Load Diff
BIN
website/favicon.ico
Normal file
BIN
website/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 817 B |
21
website/index.html
Normal file
21
website/index.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Sniph Bank</title>
|
||||
<link href="./css/style.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="min-h-[100vh] min-w-[100vw]">
|
||||
<header class="text-primary flex items-center h-[35vh]">
|
||||
<h1 class="text-8xl text-center text-primary w-full">Sniph Bank</h1>
|
||||
</header>
|
||||
<main class="flex justify-center items-center">
|
||||
<form method="post" action="/login" class="flex gap-y-2 flex-col card w-[20vw]" autocomplete="off">
|
||||
<input type="text" required name="username" placeholder="Username" class="input w-full">
|
||||
<input type="password" required name="password" placeholder="Password" class="input w-full">
|
||||
<input type="submit" class="btn btn-primary">
|
||||
</form>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user