Use FastAPI instead of Django
This commit is contained in:
parent
bfe90aa69d
commit
b462be40af
43 changed files with 1105 additions and 1688 deletions
|
|
@ -35,16 +35,8 @@ repos:
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: mixed-line-ending
|
- id: mixed-line-ending
|
||||||
- id: name-tests-test
|
- id: name-tests-test
|
||||||
args: [--django]
|
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
|
|
||||||
# Automatically upgrade your Django project code
|
|
||||||
- repo: https://github.com/adamchainz/django-upgrade
|
|
||||||
rev: "1.16.0"
|
|
||||||
hooks:
|
|
||||||
- id: django-upgrade
|
|
||||||
args: [--target-version, "5.0"]
|
|
||||||
|
|
||||||
# Run Pyupgrade on all Python files. This will upgrade the code to Python 3.12.
|
# Run Pyupgrade on all Python files. This will upgrade the code to Python 3.12.
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
rev: v3.15.2
|
rev: v3.15.2
|
||||||
|
|
|
||||||
36
.vscode/launch.json
vendored
36
.vscode/launch.json
vendored
|
|
@ -1,24 +1,16 @@
|
||||||
{
|
{
|
||||||
// Use IntelliSense to learn about possible attributes.
|
"version": "0.2.0",
|
||||||
// Hover to view descriptions of existing attributes.
|
"configurations": [
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
{
|
||||||
"version": "0.2.0",
|
"name": "Python Debugger: FastAPI",
|
||||||
"configurations": [
|
"type": "debugpy",
|
||||||
{
|
"request": "launch",
|
||||||
"name": "Python Debugger: Django",
|
"module": "uvicorn",
|
||||||
"type": "debugpy",
|
"args": [
|
||||||
"request": "launch",
|
"app.main:app",
|
||||||
"program": "${workspaceFolder}\\manage.py",
|
"--reload"
|
||||||
"args": ["runserver"],
|
],
|
||||||
"django": true
|
"jinja": true
|
||||||
},
|
}
|
||||||
{
|
]
|
||||||
"name": "Python manage.py command",
|
|
||||||
"type": "debugpy",
|
|
||||||
"request": "launch",
|
|
||||||
"program": "${workspaceFolder}\\manage.py",
|
|
||||||
"args": ["update_feeds"],
|
|
||||||
"justMyCode": false
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
|
"aiofiles",
|
||||||
"airbox",
|
"airbox",
|
||||||
"Aiur",
|
"Aiur",
|
||||||
"arcor",
|
"arcor",
|
||||||
|
|
@ -60,6 +61,7 @@
|
||||||
"mmcdole",
|
"mmcdole",
|
||||||
"Monero",
|
"Monero",
|
||||||
"myfritz",
|
"myfritz",
|
||||||
|
"naturalsize",
|
||||||
"nyaa",
|
"nyaa",
|
||||||
"Nyanpasu",
|
"Nyanpasu",
|
||||||
"Omnis",
|
"Omnis",
|
||||||
|
|
@ -77,6 +79,7 @@
|
||||||
"psql",
|
"psql",
|
||||||
"PUID",
|
"PUID",
|
||||||
"Rawr",
|
"Rawr",
|
||||||
|
"referer",
|
||||||
"regexes",
|
"regexes",
|
||||||
"Retour",
|
"Retour",
|
||||||
"Roboto",
|
"Roboto",
|
||||||
|
|
|
||||||
29
app/cli.py
Normal file
29
app/cli.py
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import click
|
||||||
|
from reader import Reader, UpdateError
|
||||||
|
|
||||||
|
from app.dependencies import get_reader
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from reader import UpdatedFeed
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
def update_feeds() -> None:
|
||||||
|
"""Update all the feeds."""
|
||||||
|
click.echo("Updating feeds...")
|
||||||
|
reader: Reader = get_reader()
|
||||||
|
for feed in reader.update_feeds_iter():
|
||||||
|
value: UpdatedFeed | None | UpdateError = feed.value
|
||||||
|
if value is not None and isinstance(value, UpdateError):
|
||||||
|
click.echo(f"Error updating {feed.url}: {value}")
|
||||||
|
else:
|
||||||
|
click.echo(f"Updated {feed.url}.")
|
||||||
|
click.echo("Feeds updated.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
update_feeds()
|
||||||
41
app/dependencies.py
Normal file
41
app/dependencies.py
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
"""https://fastapi.tiangolo.com/tutorial/dependencies/."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from functools import lru_cache
|
||||||
|
from typing import Annotated
|
||||||
|
|
||||||
|
import humanize
|
||||||
|
from fastapi import Depends
|
||||||
|
from reader import EntryCounts, FeedCounts, Reader, make_reader
|
||||||
|
|
||||||
|
from app.settings import DB_PATH
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=1)
|
||||||
|
def get_reader() -> Reader:
|
||||||
|
"""Return the reader."""
|
||||||
|
return make_reader(url=DB_PATH.as_posix(), search_enabled=True)
|
||||||
|
|
||||||
|
|
||||||
|
def get_stats() -> str:
|
||||||
|
"""Return the stats."""
|
||||||
|
db_size: int = DB_PATH.stat().st_size
|
||||||
|
|
||||||
|
# Get the feed counts.
|
||||||
|
feed_counts: FeedCounts = get_reader().get_feed_counts()
|
||||||
|
total_feed_counts: int | None = feed_counts.total
|
||||||
|
if total_feed_counts is None:
|
||||||
|
total_feed_counts = 0
|
||||||
|
|
||||||
|
# Get the entry counts.
|
||||||
|
entry_counts: EntryCounts = get_reader().get_entry_counts()
|
||||||
|
total_entry_counts: int | None = entry_counts.total
|
||||||
|
if total_entry_counts is None:
|
||||||
|
total_entry_counts = 0
|
||||||
|
|
||||||
|
return f"{total_feed_counts} feeds ({total_entry_counts} entries) ~{humanize.naturalsize(db_size, binary=True)}"
|
||||||
|
|
||||||
|
|
||||||
|
CommonReader = Annotated[Reader, Depends(get_reader)]
|
||||||
|
CommonStats = Annotated[str, Depends(get_stats)]
|
||||||
26
app/main.py
Normal file
26
app/main.py
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import uvicorn
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
|
||||||
|
from app.routers.api import api_router
|
||||||
|
from app.routers.static import static_router
|
||||||
|
|
||||||
|
app = FastAPI(
|
||||||
|
title="FeedVault API",
|
||||||
|
description="An API for FeedVault.",
|
||||||
|
version="0.1.0",
|
||||||
|
openapi_url="/api/v1/openapi.json",
|
||||||
|
redoc_url=None,
|
||||||
|
debug=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app.mount(path="/static", app=StaticFiles(directory="static"), name="static")
|
||||||
|
app.include_router(router=api_router)
|
||||||
|
app.include_router(router=static_router)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
uvicorn.run(app=app, host="0.0.0.0", port=8000) # noqa: S104
|
||||||
61
app/routers/api.py
Normal file
61
app/routers/api.py
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import datetime # noqa: TCH003
|
||||||
|
from urllib.parse import unquote
|
||||||
|
|
||||||
|
from fastapi import APIRouter
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from reader import ExceptionInfo, Feed, FeedNotFoundError
|
||||||
|
|
||||||
|
from app.dependencies import CommonReader # noqa: TCH001
|
||||||
|
from app.validators import uri_validator
|
||||||
|
|
||||||
|
api_router = APIRouter(
|
||||||
|
prefix="/api/v1",
|
||||||
|
tags=["Feeds"],
|
||||||
|
responses={404: {"description": "Not found"}},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class FeedOut(BaseModel):
|
||||||
|
"""The feed we return to the user."""
|
||||||
|
|
||||||
|
url: str
|
||||||
|
updated: datetime.datetime | None = None
|
||||||
|
title: str | None = None
|
||||||
|
link: str | None = None
|
||||||
|
author: str | None = None
|
||||||
|
subtitle: str | None = None
|
||||||
|
version: str | None = None
|
||||||
|
user_title: str | None = None
|
||||||
|
added: datetime.datetime | None = None
|
||||||
|
last_updated: datetime.datetime | None = None
|
||||||
|
last_exception: ExceptionInfo | None = None
|
||||||
|
updates_enabled: bool = True
|
||||||
|
|
||||||
|
|
||||||
|
@api_router.get("/feeds", summary="Get all the feeds in the reader.", tags=["Feeds"])
|
||||||
|
async def api_feeds(reader: CommonReader) -> list[Feed]:
|
||||||
|
"""Return all the feeds in the reader."""
|
||||||
|
return list(reader.get_feeds())
|
||||||
|
|
||||||
|
|
||||||
|
@api_router.get(
|
||||||
|
path="/feed/{feed_url:path}",
|
||||||
|
summary="Get a feed from the reader.",
|
||||||
|
tags=["Feeds"],
|
||||||
|
response_model=FeedOut | dict[str, str],
|
||||||
|
response_model_exclude_unset=True,
|
||||||
|
)
|
||||||
|
async def api_feed(feed_url: str, reader: CommonReader) -> Feed | dict[str, str]:
|
||||||
|
"""Return a feed from the reader."""
|
||||||
|
feed_url = unquote(feed_url)
|
||||||
|
|
||||||
|
if not uri_validator(feed_url):
|
||||||
|
return {"message": "Invalid URL."}
|
||||||
|
|
||||||
|
try:
|
||||||
|
feed: Feed = reader.get_feed(feed_url)
|
||||||
|
except FeedNotFoundError as e:
|
||||||
|
return {"message": str(e)}
|
||||||
|
return feed
|
||||||
131
app/routers/static.py
Normal file
131
app/routers/static.py
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import TYPE_CHECKING, Iterable
|
||||||
|
|
||||||
|
from fastapi import APIRouter, File, Request, UploadFile
|
||||||
|
from fastapi.responses import FileResponse
|
||||||
|
from fastapi.templating import Jinja2Templates
|
||||||
|
|
||||||
|
from app.dependencies import CommonReader, CommonStats # noqa: TCH001
|
||||||
|
from app.settings import MEDIA_ROOT
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from fastapi.datastructures import Address
|
||||||
|
from reader import Feed
|
||||||
|
from reader.types import Entry, EntrySearchResult
|
||||||
|
|
||||||
|
|
||||||
|
logger: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
static_router = APIRouter(tags=["HTML"])
|
||||||
|
templates = Jinja2Templates(directory="templates")
|
||||||
|
|
||||||
|
|
||||||
|
@static_router.get("/favicon.ico", summary="Favicon.", tags=["HTML"])
|
||||||
|
async def favicon(request: Request):
|
||||||
|
"""Favicon."""
|
||||||
|
return FileResponse("static/favicon.ico")
|
||||||
|
|
||||||
|
|
||||||
|
@static_router.get(path="/", summary="Index page.", tags=["HTML"])
|
||||||
|
async def index(request: Request, reader: CommonReader, stats: CommonStats):
|
||||||
|
"""Index page."""
|
||||||
|
feeds: Iterable[Feed] = reader.get_feeds()
|
||||||
|
return templates.TemplateResponse(request=request, name="index.html", context={"feeds": feeds, "stats": stats})
|
||||||
|
|
||||||
|
|
||||||
|
@static_router.get(path="/feeds", summary="Feeds page.", tags=["HTML"])
|
||||||
|
async def feeds(request: Request, reader: CommonReader, stats: CommonStats):
|
||||||
|
"""Feeds page."""
|
||||||
|
feeds: Iterable[Feed] = reader.get_feeds()
|
||||||
|
return templates.TemplateResponse(request=request, name="feeds.html", context={"feeds": feeds, "stats": stats})
|
||||||
|
|
||||||
|
|
||||||
|
@static_router.get(path="/feed/{feed_url:path}", summary="Feed page.", tags=["HTML"])
|
||||||
|
async def feed(request: Request, feed_url: str, reader: CommonReader, stats: CommonStats):
|
||||||
|
"""Feed page."""
|
||||||
|
feed: Feed = reader.get_feed(feed_url)
|
||||||
|
entries: Iterable[Entry] = reader.get_entries(feed=feed.url)
|
||||||
|
return templates.TemplateResponse(
|
||||||
|
request=request,
|
||||||
|
name="feed.html",
|
||||||
|
context={"feed": feed, "entries": entries, "stats": stats},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@static_router.get(path="/search", summary="Search page.", tags=["HTML"])
|
||||||
|
async def search(request: Request, q: str, reader: CommonReader, stats: CommonStats):
|
||||||
|
"""Search page."""
|
||||||
|
# TODO(TheLovinator): We need to show the entries in the search results. # noqa: TD003
|
||||||
|
reader.update_search()
|
||||||
|
entries: Iterable[EntrySearchResult] = reader.search_entries(q)
|
||||||
|
return templates.TemplateResponse(
|
||||||
|
request=request,
|
||||||
|
name="search.html",
|
||||||
|
context={"query": q, "entries": entries, "stats": stats},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@static_router.post(path="/upload", summary="Upload files.", tags=["HTML"])
|
||||||
|
async def upload_files(request: Request, files: list[UploadFile] = File(...)):
|
||||||
|
"""Upload files."""
|
||||||
|
media_root: str = os.getenv(key="MEDIA_ROOT", default=MEDIA_ROOT.as_posix())
|
||||||
|
file_infos: list[dict[str, str]] = []
|
||||||
|
upload_time = int(time.time())
|
||||||
|
|
||||||
|
# Save metadata
|
||||||
|
request_client: Address | None = request.client
|
||||||
|
if request_client:
|
||||||
|
host: str = request_client.host or "unknown"
|
||||||
|
else:
|
||||||
|
host = "unknown"
|
||||||
|
|
||||||
|
metadata = {
|
||||||
|
"upload_time": upload_time,
|
||||||
|
"files": [file.filename for file in files if file.filename],
|
||||||
|
"ip": host,
|
||||||
|
"user_agent": request.headers.get("user-agent") or "unknown",
|
||||||
|
"description": request.headers.get("description") or "No description.",
|
||||||
|
}
|
||||||
|
metadata_path: Path = Path(media_root) / f"{upload_time}.json"
|
||||||
|
metadata_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
metadata_path.write_text(str(metadata))
|
||||||
|
|
||||||
|
# Save uploaded files
|
||||||
|
for file in files:
|
||||||
|
if not file:
|
||||||
|
logger.error("No file uploaded.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not file.filename:
|
||||||
|
logger.error("No file name.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
file_path: Path = Path(media_root) / f"{upload_time}" / file.filename
|
||||||
|
|
||||||
|
content: bytes = b""
|
||||||
|
while chunk := await file.read(1024): # Read in chunks of 1024 bytes
|
||||||
|
content += chunk
|
||||||
|
|
||||||
|
file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
Path(file_path).write_bytes(content)
|
||||||
|
|
||||||
|
file_infos.append({"filename": file.filename})
|
||||||
|
|
||||||
|
return {"files_uploaded": file_infos}
|
||||||
|
|
||||||
|
|
||||||
|
@static_router.get(path="/upload", summary="Upload page.", tags=["HTML"])
|
||||||
|
async def upload_page(request: Request, stats: CommonStats):
|
||||||
|
"""Upload page."""
|
||||||
|
return templates.TemplateResponse(request=request, name="upload.html", context={"stats": stats})
|
||||||
|
|
||||||
|
|
||||||
|
@static_router.get(path="/contact", summary="Contact page.", tags=["HTML"])
|
||||||
|
async def contact(request: Request, stats: CommonStats):
|
||||||
|
"""Contact page."""
|
||||||
|
return templates.TemplateResponse(request=request, name="contact.html", context={"stats": stats})
|
||||||
9
app/settings.py
Normal file
9
app/settings.py
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from platformdirs import user_data_dir
|
||||||
|
|
||||||
|
DATA_DIR: str = user_data_dir(appname="FeedVault", appauthor="TheLovinator", roaming=True)
|
||||||
|
DB_PATH: Path = Path(DATA_DIR) / "reader.sqlite"
|
||||||
|
MEDIA_ROOT: Path = Path(DATA_DIR) / "uploads"
|
||||||
17
app/validators.py
Normal file
17
app/validators.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
from urllib.parse import ParseResult, urlparse
|
||||||
|
|
||||||
|
|
||||||
|
def uri_validator(url: str) -> bool:
|
||||||
|
"""Validate a URI.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
url: The URI to validate.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if the URI is valid, False otherwise.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
result: ParseResult = urlparse(url)
|
||||||
|
return all([result.scheme, result.netloc])
|
||||||
|
except AttributeError:
|
||||||
|
return False
|
||||||
|
|
@ -19,19 +19,6 @@ services:
|
||||||
# volumes:
|
# volumes:
|
||||||
# - /Docker/FeedVault/FeedVault/staticfiles:/app/staticfiles
|
# - /Docker/FeedVault/FeedVault/staticfiles:/app/staticfiles
|
||||||
# - /mnt/Fourteen/Docker/FeedVault/media:/app/media
|
# - /mnt/Fourteen/Docker/FeedVault/media:/app/media
|
||||||
feedvault_postgres:
|
|
||||||
container_name: feedvault_postgres
|
|
||||||
image: postgres:16
|
|
||||||
# user: "1000:1000"
|
|
||||||
restart: always
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
environment:
|
|
||||||
POSTGRES_USER: feedvault
|
|
||||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
|
||||||
POSTGRES_DB: feedvault
|
|
||||||
volumes:
|
|
||||||
- /Docker/FeedVault/PostgreSQL:/var/lib/postgresql/data
|
|
||||||
garnet:
|
garnet:
|
||||||
container_name: garnet
|
container_name: garnet
|
||||||
image: "ghcr.io/microsoft/garnet"
|
image: "ghcr.io/microsoft/garnet"
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
# Register your models here.
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
from django.apps import AppConfig
|
|
||||||
|
|
||||||
|
|
||||||
class FeedsConfig(AppConfig):
|
|
||||||
default_auto_field: str = "django.db.models.BigAutoField"
|
|
||||||
name = "feeds"
|
|
||||||
|
|
@ -1,224 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import logging
|
|
||||||
from functools import lru_cache
|
|
||||||
from typing import TYPE_CHECKING, Any, Iterable, Iterator, Self
|
|
||||||
|
|
||||||
from django.db.models import Q
|
|
||||||
from reader import ExceptionInfo, FeedExistsError, FeedNotFoundError, Reader, make_reader
|
|
||||||
from reader._types import (
|
|
||||||
EntryForUpdate, # noqa: PLC2701
|
|
||||||
EntryUpdateIntent,
|
|
||||||
FeedData,
|
|
||||||
FeedFilter,
|
|
||||||
FeedForUpdate, # noqa: PLC2701
|
|
||||||
FeedUpdateIntent,
|
|
||||||
SearchType, # noqa: PLC2701
|
|
||||||
StorageType, # noqa: PLC2701
|
|
||||||
)
|
|
||||||
|
|
||||||
from .models import Entry, Feed
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
from django.db.models.manager import BaseManager
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class EmptySearch(SearchType): ...
|
|
||||||
|
|
||||||
|
|
||||||
class EntriesForUpdateIterator:
|
|
||||||
def __init__(self, entries: Iterable[tuple[str, str]]) -> None:
|
|
||||||
self.entries: Iterator[tuple[str, str]] = iter(entries)
|
|
||||||
|
|
||||||
def __iter__(self) -> Self:
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __next__(self) -> EntryForUpdate:
|
|
||||||
try:
|
|
||||||
feed_url, entry_id = next(self.entries)
|
|
||||||
except StopIteration:
|
|
||||||
raise StopIteration from None
|
|
||||||
|
|
||||||
print(f"{feed_url=}, {entry_id=}") # noqa: T201
|
|
||||||
entry_data: dict[str, Any] | None = (
|
|
||||||
Entry.objects.filter(Q(feed__url=feed_url) & Q(id=entry_id))
|
|
||||||
.values("updated", "published", "data_hash", "data_hash_changed")
|
|
||||||
.first()
|
|
||||||
)
|
|
||||||
|
|
||||||
if not entry_data:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return EntryForUpdate(
|
|
||||||
updated=entry_data.get("updated"),
|
|
||||||
published=entry_data.get("published"),
|
|
||||||
hash=entry_data.get("data_hash"),
|
|
||||||
hash_changed=entry_data.get("data_hash_changed"),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class DjangoStorage(StorageType):
|
|
||||||
# TODO(TheLovinator): Implement all methods from StorageType.
|
|
||||||
default_search_cls = EmptySearch
|
|
||||||
|
|
||||||
def __enter__(self: DjangoStorage) -> None:
|
|
||||||
"""Called when Reader is used as a context manager."""
|
|
||||||
# TODO(TheLovinator): Should we check if we have migrations to apply?
|
|
||||||
|
|
||||||
def __exit__(self: DjangoStorage, *_: object) -> None:
|
|
||||||
"""Called when Reader is used as a context manager."""
|
|
||||||
# TODO(TheLovinator): Should we close the connection?
|
|
||||||
|
|
||||||
def close(self: DjangoStorage) -> None:
|
|
||||||
"""Called by Reader.close()."""
|
|
||||||
# TODO(TheLovinator): Should we close the connection?
|
|
||||||
|
|
||||||
def add_feed(self, url: str, /, added: datetime.datetime) -> None:
|
|
||||||
"""Called by Reader.add_feed().
|
|
||||||
|
|
||||||
Args:
|
|
||||||
url: The URL of the feed.
|
|
||||||
added: The time the feed was added.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
FeedExistsError: Feed already exists. Bases: FeedError
|
|
||||||
"""
|
|
||||||
if Feed.objects.filter(url=url).exists():
|
|
||||||
msg: str = f"Feed already exists: {url}"
|
|
||||||
raise FeedExistsError(msg)
|
|
||||||
|
|
||||||
feed = Feed(url=url, added=added)
|
|
||||||
feed.save()
|
|
||||||
|
|
||||||
def get_feeds_for_update(self, filter: FeedFilter): # noqa: A002
|
|
||||||
"""Called by update logic.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
filter: The filter to apply.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A lazy iterable.
|
|
||||||
"""
|
|
||||||
logger.debug(f"{filter=}") # noqa: G004
|
|
||||||
feeds: BaseManager[Feed] = Feed.objects.all() # TODO(TheLovinator): Don't get all values, use filter.
|
|
||||||
|
|
||||||
for feed in feeds:
|
|
||||||
yield FeedForUpdate(
|
|
||||||
url=feed.url,
|
|
||||||
updated=feed.updated,
|
|
||||||
http_etag=feed.http_etag,
|
|
||||||
http_last_modified=feed.http_last_modified,
|
|
||||||
stale=feed.stale,
|
|
||||||
last_updated=feed.last_updated,
|
|
||||||
last_exception=bool(feed.last_exception_type_name),
|
|
||||||
hash=feed.data_hash,
|
|
||||||
)
|
|
||||||
|
|
||||||
def update_feed(self, intent: FeedUpdateIntent, /) -> None:
|
|
||||||
"""Called by update logic.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
intent: Data to be passed to Storage when updating a feed.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
FeedNotFoundError
|
|
||||||
|
|
||||||
"""
|
|
||||||
feed: Feed = Feed.objects.get(url=intent.url)
|
|
||||||
if feed is None:
|
|
||||||
msg: str = f"Feed not found: {intent.url}"
|
|
||||||
raise FeedNotFoundError(msg)
|
|
||||||
|
|
||||||
feed.last_updated = intent.last_updated
|
|
||||||
feed.http_etag = intent.http_etag
|
|
||||||
feed.http_last_modified = intent.http_last_modified
|
|
||||||
|
|
||||||
feed_data: FeedData | None = intent.feed
|
|
||||||
if feed_data is not None:
|
|
||||||
feed.title = feed_data.title
|
|
||||||
feed.link = feed_data.link
|
|
||||||
feed.author = feed_data.author
|
|
||||||
feed.subtitle = feed_data.subtitle
|
|
||||||
feed.version = feed_data.version
|
|
||||||
|
|
||||||
if intent.last_exception is not None:
|
|
||||||
last_exception: ExceptionInfo = intent.last_exception
|
|
||||||
feed.last_exception_type_name = last_exception.type_name
|
|
||||||
feed.last_exception_value = last_exception.value_str
|
|
||||||
feed.last_exception_traceback = last_exception.traceback_str
|
|
||||||
|
|
||||||
feed.save()
|
|
||||||
|
|
||||||
def set_feed_stale(self, url: str, stale: bool, /) -> None: # noqa: FBT001
|
|
||||||
"""Used by update logic tests.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
url: The URL of the feed.
|
|
||||||
stale: Whether the next update should update all entries, regardless of their hash or updated.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
FeedNotFoundError
|
|
||||||
"""
|
|
||||||
feed: Feed = Feed.objects.get(url=url)
|
|
||||||
if feed is None:
|
|
||||||
msg: str = f"Feed not found: {url}"
|
|
||||||
raise FeedNotFoundError(msg)
|
|
||||||
|
|
||||||
feed.stale = stale
|
|
||||||
feed.save()
|
|
||||||
|
|
||||||
def get_entries_for_update(self, entries: Iterable[tuple[str, str]], /) -> EntriesForUpdateIterator:
|
|
||||||
for feed_url, entry_id in entries:
|
|
||||||
logger.debug(f"{feed_url=}, {entry_id=}") # noqa: G004
|
|
||||||
|
|
||||||
entries_list = list(entries)
|
|
||||||
print(f"{entries_list=}") # noqa: T201
|
|
||||||
return EntriesForUpdateIterator(entries)
|
|
||||||
|
|
||||||
def add_or_update_entries(self, intents: Iterable[EntryUpdateIntent], /) -> None:
|
|
||||||
"""Called by update logic.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
intents: Data to be passed to Storage when updating a feed.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
FeedNotFoundError
|
|
||||||
"""
|
|
||||||
msg = "Not implemented yet."
|
|
||||||
raise NotImplementedError(msg)
|
|
||||||
for intent in intents:
|
|
||||||
feed_id, entry_id = intent.entry.resource_id
|
|
||||||
logger.debug(f"{feed_id=}, {entry_id=}") # noqa: G004
|
|
||||||
# TODO(TheLovinator): Implement this method. Use Entry.objects.get_or_create()/Entry.objects.bulk_create()?
|
|
||||||
# TODO(TheLovinator): Raise FeedNotFoundError if feed does not exist.
|
|
||||||
|
|
||||||
def make_search(self) -> SearchType:
|
|
||||||
"""Called by Reader.make_search().
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A Search instance.
|
|
||||||
"""
|
|
||||||
return EmptySearch()
|
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=1)
|
|
||||||
def get_reader() -> Reader:
|
|
||||||
"""Create a Reader instance.
|
|
||||||
|
|
||||||
reader = get_reader()
|
|
||||||
reader.add_feed("https://example.com/feed", added=datetime.datetime.now())
|
|
||||||
reader.update_feeds()
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A Reader instance.
|
|
||||||
"""
|
|
||||||
return make_reader(
|
|
||||||
"",
|
|
||||||
_storage=DjangoStorage(),
|
|
||||||
search_enabled=False,
|
|
||||||
)
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from reader import Reader
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
|
||||||
help = "Update feeds"
|
|
||||||
|
|
||||||
def handle(self, *args, **options) -> None:
|
|
||||||
from feeds.get_reader import get_reader # noqa: PLC0415
|
|
||||||
|
|
||||||
reader: Reader = get_reader()
|
|
||||||
reader.update_feeds()
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
# Generated by Django 5.0.6 on 2024-05-20 00:49
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
import feeds.models
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Entry',
|
|
||||||
fields=[
|
|
||||||
('id', models.TextField(help_text='The entry id.', primary_key=True, serialize=False)),
|
|
||||||
('updated', models.DateTimeField(help_text='The date the entry was last updated, according to the feed.', null=True)),
|
|
||||||
('title', models.TextField(help_text='The title of the entry.', null=True)),
|
|
||||||
('link', models.TextField(help_text='The URL of the entry.', null=True)),
|
|
||||||
('author', models.TextField(help_text='The author of the feed.', null=True)),
|
|
||||||
('published', models.DateTimeField(help_text='The date the entry was published.', null=True)),
|
|
||||||
('summary', models.TextField(help_text='A summary of the entry.', null=True)),
|
|
||||||
('read', models.BooleanField(default=False, help_text='Whether the entry has been read.')),
|
|
||||||
('read_modified', models.DateTimeField(help_text='When read was last modified, None if that never.', null=True)),
|
|
||||||
('added', models.DateTimeField(help_text='The date when the entry was added (first updated) to reader.', null=True)),
|
|
||||||
('added_by', models.TextField(help_text="The source of the entry. One of 'feed', 'user'.", null=True)),
|
|
||||||
('last_updated', models.DateTimeField(help_text='The date when the entry was last retrieved by reader.', null=True)),
|
|
||||||
('first_updated', models.DateTimeField(help_text='The date when the entry was first retrieved by reader.', null=True)),
|
|
||||||
('first_updated_epoch', models.DateTimeField(help_text='The date when the entry was first retrieved by reader, as an epoch timestamp.', null=True)),
|
|
||||||
('feed_order', models.PositiveIntegerField(help_text='The order of the entry in the feed.', null=True)),
|
|
||||||
('recent_sort', models.PositiveIntegerField(help_text='The order of the entry in the recent list.', null=True)),
|
|
||||||
('sequence', models.BinaryField(help_text='The sequence of the entry in the feed.', null=True)),
|
|
||||||
('original_feed', models.TextField(help_text='The URL of the original feed of the entry. If the feed URL never changed, the same as feed_url.', null=True)),
|
|
||||||
('data_hash', models.TextField(help_text='The hash of the entry data.', null=True)),
|
|
||||||
('data_hash_changed', models.BooleanField(default=False, help_text='Whether the data hash has changed since the last update.')),
|
|
||||||
('important', models.BooleanField(default=False, help_text='Whether the entry is important.')),
|
|
||||||
('important_modified', models.DateTimeField(help_text='When important was last modified, None if that never.', null=True)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Feed',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('url', models.URLField(help_text='The URL of the feed.', unique=True)),
|
|
||||||
('updated', models.DateTimeField(help_text='The date the feed was last updated, according to the feed.', null=True)),
|
|
||||||
('title', models.TextField(help_text='The title of the feed.', null=True)),
|
|
||||||
('link', models.TextField(help_text='The URL of a page associated with the feed.', null=True)),
|
|
||||||
('author', models.TextField(help_text='The author of the feed.', null=True)),
|
|
||||||
('subtitle', models.TextField(help_text='A description or subtitle for the feed.', null=True)),
|
|
||||||
('version', models.TextField(help_text='The version of the feed.', null=True)),
|
|
||||||
('user_title', models.TextField(help_text='User-defined feed title.', null=True)),
|
|
||||||
('added', models.DateTimeField(auto_now_add=True, help_text='The date when the feed was added.')),
|
|
||||||
('last_updated', models.DateTimeField(help_text='The date when the feed was last retrieved by reader.', null=True)),
|
|
||||||
('last_exception_type_name', models.TextField(help_text='The fully qualified name of the exception type.', null=True)),
|
|
||||||
('last_exception_value', models.TextField(help_text='The exception value.', null=True)),
|
|
||||||
('last_exception_traceback', models.TextField(help_text='The exception traceback.', null=True)),
|
|
||||||
('updates_enabled', models.BooleanField(default=True, help_text='Whether updates are enabled for the feed.')),
|
|
||||||
('stale', models.BooleanField(default=False, help_text='Whether the next update should update all entries, regardless of their hash or updated.')),
|
|
||||||
('http_etag', models.TextField(help_text='The HTTP ETag header.', null=True)),
|
|
||||||
('http_last_modified', models.TextField(help_text='The HTTP Last-Modified header.', null=True)),
|
|
||||||
('data_hash', models.TextField(help_text='The hash of the feed data.', null=True)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='UploadedFeed',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('file', models.FileField(help_text='The file that was uploaded.', upload_to=feeds.models.get_upload_path)),
|
|
||||||
('original_filename', models.TextField(help_text='The original filename of the file.')),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True, help_text='The time the file was uploaded.')),
|
|
||||||
('has_been_processed', models.BooleanField(default=False, help_text='Has the file content been added to the archive?')),
|
|
||||||
('public', models.BooleanField(default=False, help_text='Is the file public?')),
|
|
||||||
('description', models.TextField(blank=True, help_text='Description added by user.')),
|
|
||||||
('notes', models.TextField(blank=True, help_text='Notes from admin.')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Uploaded file',
|
|
||||||
'verbose_name_plural': 'Uploaded files',
|
|
||||||
'ordering': ['-created_at'],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Enclosure',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('href', models.TextField(help_text='The file URL.')),
|
|
||||||
('type', models.TextField(help_text='The file content type.', null=True)),
|
|
||||||
('length', models.PositiveIntegerField(help_text='The file length.', null=True)),
|
|
||||||
('entry', models.ForeignKey(help_text='The entry this enclosure is for.', on_delete=django.db.models.deletion.CASCADE, related_name='enclosures', to='feeds.entry')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Content',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('value', models.TextField(help_text='The content value.')),
|
|
||||||
('type', models.TextField(help_text='The content type.', null=True)),
|
|
||||||
('language', models.TextField(help_text='The content language.', null=True)),
|
|
||||||
('entry', models.ForeignKey(help_text='The entry this content is for.', on_delete=django.db.models.deletion.CASCADE, related_name='content', to='feeds.entry')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='entry',
|
|
||||||
name='feed',
|
|
||||||
field=models.ForeignKey(help_text='The feed this entry is from.', on_delete=django.db.models.deletion.CASCADE, related_name='entries', to='feeds.feed'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 5.0.6 on 2024-05-20 01:19
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('feeds', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='feed',
|
|
||||||
name='data_hash',
|
|
||||||
field=models.BinaryField(help_text='The hash of the feed data.', null=True),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
131
feeds/models.py
131
feeds/models.py
|
|
@ -1,131 +0,0 @@
|
||||||
"""These models are used to store the data from https://reader.readthedocs.io/en/latest/api.html#reader.Feed."""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import typing
|
|
||||||
import uuid
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
def get_upload_path(instance: UploadedFeed, filename: str) -> str:
|
|
||||||
"""Don't save the file with the original filename."""
|
|
||||||
ext: str = Path(filename).suffix
|
|
||||||
unix_time: int = int(instance.created_at.timestamp())
|
|
||||||
filename = f"{unix_time}-{uuid.uuid4().hex}{ext}"
|
|
||||||
return f"uploads/{filename}"
|
|
||||||
|
|
||||||
|
|
||||||
class UploadedFeed(models.Model):
|
|
||||||
"""A file uploaded to the server by a user."""
|
|
||||||
|
|
||||||
file = models.FileField(upload_to=get_upload_path, help_text="The file that was uploaded.")
|
|
||||||
original_filename = models.TextField(help_text="The original filename of the file.")
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True, help_text="The time the file was uploaded.")
|
|
||||||
has_been_processed = models.BooleanField(default=False, help_text="Has the file content been added to the archive?")
|
|
||||||
public = models.BooleanField(default=False, help_text="Is the file public?")
|
|
||||||
description = models.TextField(blank=True, help_text="Description added by user.")
|
|
||||||
notes = models.TextField(blank=True, help_text="Notes from admin.")
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Meta information for the uploaded file model."""
|
|
||||||
|
|
||||||
ordering: typing.ClassVar[list[str]] = ["-created_at"]
|
|
||||||
verbose_name: str = "Uploaded file"
|
|
||||||
verbose_name_plural: str = "Uploaded files"
|
|
||||||
|
|
||||||
def __str__(self: UploadedFeed) -> str:
|
|
||||||
return f"{self.original_filename} - {self.created_at}"
|
|
||||||
|
|
||||||
|
|
||||||
class Feed(models.Model):
|
|
||||||
url = models.URLField(unique=True, help_text="The URL of the feed.")
|
|
||||||
updated = models.DateTimeField(help_text="The date the feed was last updated, according to the feed.", null=True)
|
|
||||||
title = models.TextField(help_text="The title of the feed.", null=True)
|
|
||||||
link = models.TextField(help_text="The URL of a page associated with the feed.", null=True)
|
|
||||||
author = models.TextField(help_text="The author of the feed.", null=True)
|
|
||||||
subtitle = models.TextField(help_text="A description or subtitle for the feed.", null=True)
|
|
||||||
version = models.TextField(help_text="The version of the feed.", null=True)
|
|
||||||
user_title = models.TextField(help_text="User-defined feed title.", null=True)
|
|
||||||
added = models.DateTimeField(help_text="The date when the feed was added.", auto_now_add=True)
|
|
||||||
last_updated = models.DateTimeField(help_text="The date when the feed was last retrieved by reader.", null=True)
|
|
||||||
last_exception_type_name = models.TextField(help_text="The fully qualified name of the exception type.", null=True)
|
|
||||||
last_exception_value = models.TextField(help_text="The exception value.", null=True)
|
|
||||||
last_exception_traceback = models.TextField(help_text="The exception traceback.", null=True)
|
|
||||||
updates_enabled = models.BooleanField(help_text="Whether updates are enabled for the feed.", default=True)
|
|
||||||
stale = models.BooleanField(
|
|
||||||
help_text="Whether the next update should update all entries, regardless of their hash or updated.",
|
|
||||||
default=False,
|
|
||||||
)
|
|
||||||
http_etag = models.TextField(help_text="The HTTP ETag header.", null=True)
|
|
||||||
http_last_modified = models.TextField(help_text="The HTTP Last-Modified header.", null=True)
|
|
||||||
data_hash = models.BinaryField(help_text="The hash of the feed data.", null=True)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return f"{self.title} ({self.url})" if self.title else self.url
|
|
||||||
|
|
||||||
|
|
||||||
class Entry(models.Model):
|
|
||||||
feed = models.ForeignKey(
|
|
||||||
Feed, on_delete=models.CASCADE, help_text="The feed this entry is from.", related_name="entries"
|
|
||||||
)
|
|
||||||
id = models.TextField(primary_key=True, help_text="The entry id.")
|
|
||||||
updated = models.DateTimeField(help_text="The date the entry was last updated, according to the feed.", null=True)
|
|
||||||
title = models.TextField(help_text="The title of the entry.", null=True)
|
|
||||||
link = models.TextField(help_text="The URL of the entry.", null=True)
|
|
||||||
author = models.TextField(help_text="The author of the feed.", null=True)
|
|
||||||
published = models.DateTimeField(help_text="The date the entry was published.", null=True)
|
|
||||||
summary = models.TextField(help_text="A summary of the entry.", null=True)
|
|
||||||
read = models.BooleanField(help_text="Whether the entry has been read.", default=False)
|
|
||||||
read_modified = models.DateTimeField(help_text="When read was last modified, None if that never.", null=True)
|
|
||||||
added = models.DateTimeField(help_text="The date when the entry was added (first updated) to reader.", null=True)
|
|
||||||
added_by = models.TextField(help_text="The source of the entry. One of 'feed', 'user'.", null=True)
|
|
||||||
last_updated = models.DateTimeField(help_text="The date when the entry was last retrieved by reader.", null=True)
|
|
||||||
first_updated = models.DateTimeField(help_text="The date when the entry was first retrieved by reader.", null=True)
|
|
||||||
first_updated_epoch = models.DateTimeField(
|
|
||||||
help_text="The date when the entry was first retrieved by reader, as an epoch timestamp.", null=True
|
|
||||||
)
|
|
||||||
feed_order = models.PositiveIntegerField(help_text="The order of the entry in the feed.", null=True)
|
|
||||||
recent_sort = models.PositiveIntegerField(help_text="The order of the entry in the recent list.", null=True)
|
|
||||||
sequence = models.BinaryField(help_text="The sequence of the entry in the feed.", null=True)
|
|
||||||
original_feed = models.TextField(
|
|
||||||
help_text="The URL of the original feed of the entry. If the feed URL never changed, the same as feed_url.",
|
|
||||||
null=True,
|
|
||||||
)
|
|
||||||
data_hash = models.TextField(help_text="The hash of the entry data.", null=True)
|
|
||||||
data_hash_changed = models.BooleanField(
|
|
||||||
help_text="Whether the data hash has changed since the last update.", default=False
|
|
||||||
)
|
|
||||||
important = models.BooleanField(help_text="Whether the entry is important.", default=False)
|
|
||||||
important_modified = models.DateTimeField(
|
|
||||||
help_text="When important was last modified, None if that never.", null=True
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return f"{self.title} ({self.link})" if self.title and self.link else self.id
|
|
||||||
|
|
||||||
|
|
||||||
class Content(models.Model):
|
|
||||||
entry = models.ForeignKey(
|
|
||||||
Entry, on_delete=models.CASCADE, help_text="The entry this content is for.", related_name="content"
|
|
||||||
)
|
|
||||||
value = models.TextField(help_text="The content value.")
|
|
||||||
type = models.TextField(help_text="The content type.", null=True)
|
|
||||||
language = models.TextField(help_text="The content language.", null=True)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
max_length = 50
|
|
||||||
return self.value[:max_length] + "..." if len(self.value) > max_length else self.value
|
|
||||||
|
|
||||||
|
|
||||||
class Enclosure(models.Model):
|
|
||||||
entry = models.ForeignKey(
|
|
||||||
Entry, on_delete=models.CASCADE, help_text="The entry this enclosure is for.", related_name="enclosures"
|
|
||||||
)
|
|
||||||
href = models.TextField(help_text="The file URL.")
|
|
||||||
type = models.TextField(help_text="The file content type.", null=True)
|
|
||||||
length = models.PositiveIntegerField(help_text="The file length.", null=True)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return self.href
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
# Create your tests here.
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from django.contrib.sitemaps import GenericSitemap
|
|
||||||
from django.urls import include, path
|
|
||||||
|
|
||||||
from feedvault.sitemaps import StaticViewSitemap
|
|
||||||
|
|
||||||
from .models import Feed
|
|
||||||
from .views import AddView, FeedsView, FeedView, IndexView, SearchView, UploadView
|
|
||||||
|
|
||||||
app_name: str = "feeds"
|
|
||||||
|
|
||||||
sitemaps = {
|
|
||||||
"static": StaticViewSitemap,
|
|
||||||
"feeds": GenericSitemap({"queryset": Feed.objects.all(), "date_field": "created_at"}),
|
|
||||||
}
|
|
||||||
|
|
||||||
urlpatterns: list = [
|
|
||||||
path(route="", view=IndexView.as_view(), name="index"),
|
|
||||||
path("__debug__/", include("debug_toolbar.urls")),
|
|
||||||
path(route="feed/<int:feed_id>/", view=FeedView.as_view(), name="feed"),
|
|
||||||
path(route="feeds/", view=FeedsView.as_view(), name="feeds"),
|
|
||||||
path(route="add/", view=AddView.as_view(), name="add"),
|
|
||||||
path(route="upload/", view=UploadView.as_view(), name="upload"),
|
|
||||||
path(route="search/", view=SearchView.as_view(), name="search"),
|
|
||||||
]
|
|
||||||
175
feeds/views.py
175
feeds/views.py
|
|
@ -1,175 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import logging
|
|
||||||
from typing import TYPE_CHECKING, Any
|
|
||||||
|
|
||||||
from django.contrib import messages
|
|
||||||
from django.core.paginator import EmptyPage, Page, Paginator
|
|
||||||
from django.db.models.manager import BaseManager
|
|
||||||
from django.http import HttpRequest, HttpResponse
|
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
|
||||||
from django.template import loader
|
|
||||||
from django.views import View
|
|
||||||
from reader import InvalidFeedURLError
|
|
||||||
|
|
||||||
from feeds.get_reader import get_reader
|
|
||||||
from feeds.models import Entry, Feed, UploadedFeed
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.core.files.uploadedfile import UploadedFile
|
|
||||||
from django.db.models.manager import BaseManager
|
|
||||||
from reader import Reader
|
|
||||||
|
|
||||||
logger: logging.Logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class HtmxHttpRequest(HttpRequest):
|
|
||||||
htmx: Any
|
|
||||||
|
|
||||||
|
|
||||||
class IndexView(View):
|
|
||||||
"""Index path."""
|
|
||||||
|
|
||||||
def get(self, request: HttpRequest) -> HttpResponse:
|
|
||||||
"""Load the index page."""
|
|
||||||
template = loader.get_template(template_name="index.html")
|
|
||||||
context: dict[str, str] = {
|
|
||||||
"description": "FeedVault allows users to archive and search their favorite web feeds.",
|
|
||||||
"keywords": "feed, rss, atom, archive, rss list",
|
|
||||||
"author": "TheLovinator",
|
|
||||||
"canonical": "https://feedvault.se/",
|
|
||||||
"title": "FeedVault",
|
|
||||||
}
|
|
||||||
return HttpResponse(content=template.render(context=context, request=request))
|
|
||||||
|
|
||||||
|
|
||||||
class FeedView(View):
|
|
||||||
"""A single feed."""
|
|
||||||
|
|
||||||
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: # noqa: ANN002, ANN003
|
|
||||||
"""Load the feed page."""
|
|
||||||
feed_id: str = kwargs.get("feed_id", None)
|
|
||||||
if not feed_id:
|
|
||||||
return HttpResponse(content="No id", status=400)
|
|
||||||
|
|
||||||
feed: Feed = get_object_or_404(Feed, pk=feed_id)
|
|
||||||
entries: BaseManager[Entry] = Entry.objects.filter(feed=feed).order_by("-added")[:100]
|
|
||||||
|
|
||||||
context: dict[str, Any] = {
|
|
||||||
"feed": feed,
|
|
||||||
"entries": entries,
|
|
||||||
"description": f"{feed.subtitle}" or f"Archive of {feed.url}",
|
|
||||||
"keywords": "feed, rss, atom, archive, rss list",
|
|
||||||
"author": f"{feed.author}" or "FeedVault",
|
|
||||||
"canonical": f"https://feedvault.se/feed/{feed.pk}/",
|
|
||||||
"title": f"{feed.title}" or "FeedVault",
|
|
||||||
}
|
|
||||||
|
|
||||||
return render(request=request, template_name="feed.html", context=context)
|
|
||||||
|
|
||||||
|
|
||||||
class FeedsView(View):
|
|
||||||
"""All feeds."""
|
|
||||||
|
|
||||||
def get(self, request: HtmxHttpRequest) -> HttpResponse:
|
|
||||||
"""All feeds."""
|
|
||||||
feeds: BaseManager[Feed] = Feed.objects.only("id", "url")
|
|
||||||
|
|
||||||
paginator = Paginator(object_list=feeds, per_page=100)
|
|
||||||
page_number = int(request.GET.get("page", default=1))
|
|
||||||
|
|
||||||
try:
|
|
||||||
pages: Page = paginator.get_page(page_number)
|
|
||||||
except EmptyPage:
|
|
||||||
return HttpResponse("")
|
|
||||||
|
|
||||||
context: dict[str, str | Page | int] = {
|
|
||||||
"feeds": pages,
|
|
||||||
"description": "An archive of web feeds",
|
|
||||||
"keywords": "feed, rss, atom, archive, rss list",
|
|
||||||
"author": "TheLovinator",
|
|
||||||
"canonical": "https://feedvault.se/feeds/",
|
|
||||||
"title": "Feeds",
|
|
||||||
"page": page_number,
|
|
||||||
}
|
|
||||||
|
|
||||||
template_name = "partials/feeds.html" if request.htmx else "feeds.html"
|
|
||||||
return render(request, template_name, context)
|
|
||||||
|
|
||||||
|
|
||||||
class AddView(View):
|
|
||||||
"""Add a feed."""
|
|
||||||
|
|
||||||
def get(self, request: HttpRequest) -> HttpResponse:
|
|
||||||
"""Load the index page."""
|
|
||||||
template = loader.get_template(template_name="index.html")
|
|
||||||
context: dict[str, str] = {
|
|
||||||
"description": "FeedVault allows users to archive and search their favorite web feeds.",
|
|
||||||
"keywords": "feed, rss, atom, archive, rss list",
|
|
||||||
"author": "TheLovinator",
|
|
||||||
"canonical": "https://feedvault.se/",
|
|
||||||
}
|
|
||||||
return HttpResponse(content=template.render(context=context, request=request))
|
|
||||||
|
|
||||||
def post(self, request: HttpRequest) -> HttpResponse:
|
|
||||||
"""Add a feed."""
|
|
||||||
urls: str | None = request.POST.get("urls", None)
|
|
||||||
if not urls:
|
|
||||||
return HttpResponse(content="No urls", status=400)
|
|
||||||
|
|
||||||
reader: Reader = get_reader()
|
|
||||||
for url in urls.split("\n"):
|
|
||||||
clean_url: str = url.strip()
|
|
||||||
try:
|
|
||||||
reader.add_feed(clean_url)
|
|
||||||
messages.success(request, f"Added {clean_url}")
|
|
||||||
except InvalidFeedURLError:
|
|
||||||
logger.exception("Error adding %s", clean_url)
|
|
||||||
messages.error(request, f"Error adding {clean_url}")
|
|
||||||
|
|
||||||
messages.success(request, "Feeds added")
|
|
||||||
return redirect("feeds:index")
|
|
||||||
|
|
||||||
|
|
||||||
class UploadView(View):
|
|
||||||
"""Upload a file."""
|
|
||||||
|
|
||||||
def post(self, request: HttpRequest) -> HttpResponse:
|
|
||||||
"""Upload a file."""
|
|
||||||
file: UploadedFile | None = request.FILES.get("file", None)
|
|
||||||
if not file:
|
|
||||||
return HttpResponse(content="No file", status=400)
|
|
||||||
|
|
||||||
# Save file to media folder
|
|
||||||
UploadedFeed.objects.create(user=request.user, file=file, original_filename=file.name)
|
|
||||||
|
|
||||||
# Render the index page.
|
|
||||||
messages.success(request, f"{file.name} uploaded")
|
|
||||||
messages.info(request, "If the file was marked as public, it will be shown on the feeds page. ")
|
|
||||||
return redirect("feeds:index")
|
|
||||||
|
|
||||||
|
|
||||||
class SearchView(View):
|
|
||||||
"""Search view."""
|
|
||||||
|
|
||||||
def get(self, request: HtmxHttpRequest) -> HttpResponse:
|
|
||||||
"""Load the search page."""
|
|
||||||
query: str | None = request.GET.get("q", None)
|
|
||||||
if not query:
|
|
||||||
return FeedsView().get(request)
|
|
||||||
|
|
||||||
# TODO(TheLovinator): #20 Search more fields
|
|
||||||
# https://github.com/TheLovinator1/FeedVault/issues/20
|
|
||||||
feeds: BaseManager[Feed] = Feed.objects.filter(url__icontains=query).order_by("-added")[:100]
|
|
||||||
|
|
||||||
context = {
|
|
||||||
"feeds": feeds,
|
|
||||||
"description": f"Search results for {query}",
|
|
||||||
"keywords": f"feed, rss, atom, archive, rss list, {query}",
|
|
||||||
"author": "TheLovinator",
|
|
||||||
"canonical": f"https://feedvault.se/search/?q={query}",
|
|
||||||
"title": f"Search results for {query}",
|
|
||||||
"query": query,
|
|
||||||
}
|
|
||||||
|
|
||||||
return render(request, "search.html", context)
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
from django.apps import AppConfig
|
|
||||||
|
|
||||||
|
|
||||||
class FeedVaultConfig(AppConfig):
|
|
||||||
default_auto_field: str = "django.db.models.BigAutoField"
|
|
||||||
name: str = "feedvault"
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.http import HttpRequest
|
|
||||||
|
|
||||||
|
|
||||||
def add_global_context(request: HttpRequest) -> dict[str, str | int]:
|
|
||||||
"""Add global context to all templates.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request: The request object.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A dictionary with the global context.
|
|
||||||
"""
|
|
||||||
from feeds.models import Feed # noqa: PLC0415
|
|
||||||
|
|
||||||
amount_of_feeds: int = Feed.objects.count()
|
|
||||||
return {"amount_of_feeds": amount_of_feeds}
|
|
||||||
|
|
@ -1,199 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from dotenv import find_dotenv, load_dotenv
|
|
||||||
|
|
||||||
load_dotenv(dotenv_path=find_dotenv(), verbose=True)
|
|
||||||
TESTING: bool = len(sys.argv) > 1 and sys.argv[1] == "test"
|
|
||||||
|
|
||||||
BASE_DIR: Path = Path(__file__).resolve().parent.parent
|
|
||||||
|
|
||||||
DEBUG: bool = os.getenv(key="DEBUG", default="True").lower() == "true"
|
|
||||||
SECRET_KEY: str = os.getenv("SECRET_KEY", default="")
|
|
||||||
|
|
||||||
TIME_ZONE = "Europe/Stockholm"
|
|
||||||
LANGUAGE_CODE = "en-us"
|
|
||||||
USE_I18N = True
|
|
||||||
USE_TZ = True
|
|
||||||
|
|
||||||
ADMINS: list[tuple[str, str]] = [("Joakim Hellsén", "tlovinator@gmail.com")]
|
|
||||||
ALLOWED_HOSTS: list[str] = [".feedvault.se", ".localhost", "127.0.0.1"]
|
|
||||||
USE_X_FORWARDED_HOST = True
|
|
||||||
INTERNAL_IPS: list[str] = ["127.0.0.1", "localhost", "192.168.1.143"]
|
|
||||||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
|
||||||
WSGI_APPLICATION = "feedvault.wsgi.application"
|
|
||||||
ROOT_URLCONF = "feedvault.urls"
|
|
||||||
SITE_ID = 1
|
|
||||||
|
|
||||||
if not DEBUG:
|
|
||||||
CSRF_COOKIE_DOMAIN = ".feedvault.se"
|
|
||||||
CSRF_TRUSTED_ORIGINS: list[str] = ["https://feedvault.se", "https://www.feedvault.se"]
|
|
||||||
|
|
||||||
TIME_ZONE = "Europe/Stockholm"
|
|
||||||
|
|
||||||
EMAIL_HOST = "smtp.gmail.com"
|
|
||||||
EMAIL_PORT = 587
|
|
||||||
EMAIL_USE_TLS = True
|
|
||||||
EMAIL_HOST_USER: str = os.getenv(key="EMAIL_HOST_USER", default="")
|
|
||||||
EMAIL_HOST_PASSWORD: str = os.getenv(key="EMAIL_HOST_PASSWORD", default="")
|
|
||||||
EMAIL_SUBJECT_PREFIX = "[FeedVault] "
|
|
||||||
EMAIL_USE_LOCALTIME = True
|
|
||||||
EMAIL_TIMEOUT = 10
|
|
||||||
DEFAULT_FROM_EMAIL: str = os.getenv(key="EMAIL_HOST_USER", default="webmaster@localhost")
|
|
||||||
SERVER_EMAIL: str = os.getenv(key="EMAIL_HOST_USER", default="webmaster@localhost")
|
|
||||||
|
|
||||||
|
|
||||||
STATIC_URL = "static/"
|
|
||||||
STATIC_ROOT: Path = BASE_DIR / "staticfiles"
|
|
||||||
STATIC_ROOT.mkdir(parents=True, exist_ok=True)
|
|
||||||
STATICFILES_DIRS: list[Path] = [BASE_DIR / "static"]
|
|
||||||
for static_dir in STATICFILES_DIRS:
|
|
||||||
static_dir.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
|
|
||||||
MEDIA_URL = "media/"
|
|
||||||
MEDIA_ROOT: Path = BASE_DIR / "media"
|
|
||||||
MEDIA_ROOT.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
|
|
||||||
INSTALLED_APPS: list[str] = [
|
|
||||||
"feeds.apps.FeedsConfig",
|
|
||||||
"debug_toolbar",
|
|
||||||
"django.contrib.auth",
|
|
||||||
"whitenoise.runserver_nostatic",
|
|
||||||
"django.contrib.staticfiles",
|
|
||||||
"django.contrib.contenttypes",
|
|
||||||
"django.contrib.sessions",
|
|
||||||
"django.contrib.messages",
|
|
||||||
"django.contrib.sitemaps",
|
|
||||||
"django_htmx",
|
|
||||||
]
|
|
||||||
|
|
||||||
MIDDLEWARE: list[str] = [
|
|
||||||
"debug_toolbar.middleware.DebugToolbarMiddleware",
|
|
||||||
"django.middleware.security.SecurityMiddleware",
|
|
||||||
"whitenoise.middleware.WhiteNoiseMiddleware",
|
|
||||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
||||||
"django.middleware.common.CommonMiddleware",
|
|
||||||
"django.middleware.csrf.CsrfViewMiddleware",
|
|
||||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
||||||
"django.contrib.messages.middleware.MessageMiddleware",
|
|
||||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
||||||
"django_htmx.middleware.HtmxMiddleware",
|
|
||||||
]
|
|
||||||
|
|
||||||
# TODO(TheLovinator): #1 Use unix socket for postgres in production
|
|
||||||
# https://github.com/TheLovinator1/feedvault.se/issues/1
|
|
||||||
DATABASES: dict[str, dict[str, str]] = {
|
|
||||||
"default": {
|
|
||||||
"ENGINE": "django.db.backends.postgresql",
|
|
||||||
"NAME": os.getenv("DB_NAME", ""),
|
|
||||||
"USER": os.getenv("DB_USER", ""),
|
|
||||||
"PASSWORD": os.getenv("DB_PASSWORD", ""),
|
|
||||||
"HOST": os.getenv("DB_HOST", ""),
|
|
||||||
"PORT": os.getenv("DB_PORT", ""),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if not DEBUG:
|
|
||||||
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
|
|
||||||
SESSION_CACHE_ALIAS: str = "default"
|
|
||||||
|
|
||||||
# TODO(TheLovinator): #2 Use unix socket for redis in production
|
|
||||||
# https://github.com/TheLovinator1/feedvault.se/issues/2
|
|
||||||
REDIS_LOCATION: str = f"redis://{os.getenv('REDIS_HOST', "")}:{os.getenv('REDIS_PORT', "")}/1"
|
|
||||||
CACHES: dict[str, dict[str, str | dict[str, str]]] = {
|
|
||||||
"default": {
|
|
||||||
"BACKEND": "django_redis.cache.RedisCache",
|
|
||||||
"LOCATION": REDIS_LOCATION,
|
|
||||||
"KEY_PREFIX": "feedvault-dev" if DEBUG else "feedvault",
|
|
||||||
"OPTIONS": {
|
|
||||||
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
|
||||||
"PARSER_CLASS": "redis.connection._HiredisParser",
|
|
||||||
"PASSWORD": os.getenv("REDIS_PASSWORD", ""),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
# A list containing the settings for all template engines to be used with Django.
|
|
||||||
TEMPLATES = [
|
|
||||||
{
|
|
||||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
|
||||||
"DIRS": [BASE_DIR / "templates"],
|
|
||||||
"OPTIONS": {
|
|
||||||
"context_processors": [
|
|
||||||
"django.template.context_processors.debug",
|
|
||||||
"django.template.context_processors.request",
|
|
||||||
"django.contrib.auth.context_processors.auth",
|
|
||||||
"django.contrib.messages.context_processors.messages",
|
|
||||||
"feedvault.context_processors.add_global_context",
|
|
||||||
],
|
|
||||||
"loaders": [
|
|
||||||
(
|
|
||||||
"django.template.loaders.cached.Loader",
|
|
||||||
[
|
|
||||||
"django.template.loaders.filesystem.Loader",
|
|
||||||
"django.template.loaders.app_directories.Loader",
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
LOGGING = {
|
|
||||||
"version": 1,
|
|
||||||
"disable_existing_loggers": False,
|
|
||||||
"handlers": {
|
|
||||||
"console": {
|
|
||||||
"level": "DEBUG",
|
|
||||||
"class": "logging.StreamHandler",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"loggers": {
|
|
||||||
"django": {
|
|
||||||
"handlers": ["console"],
|
|
||||||
"level": "INFO",
|
|
||||||
"propagate": True,
|
|
||||||
},
|
|
||||||
"django.utils.autoreload": {
|
|
||||||
"handlers": ["console"],
|
|
||||||
"level": "INFO",
|
|
||||||
"propagate": True,
|
|
||||||
},
|
|
||||||
"": {
|
|
||||||
"handlers": ["console"],
|
|
||||||
"level": "DEBUG",
|
|
||||||
"propagate": True,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
STORAGES: dict[str, dict[str, str]] = {
|
|
||||||
"default": {
|
|
||||||
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
|
||||||
},
|
|
||||||
"staticfiles": {
|
|
||||||
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage"
|
|
||||||
if TESTING
|
|
||||||
else "whitenoise.storage.CompressedManifestStaticFilesStorage",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS: list[dict[str, str]] = [
|
|
||||||
{
|
|
||||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from django.contrib.sitemaps import Sitemap
|
|
||||||
from django.urls import reverse
|
|
||||||
|
|
||||||
|
|
||||||
class StaticViewSitemap(Sitemap):
|
|
||||||
"""Sitemap for static views."""
|
|
||||||
|
|
||||||
changefreq: str = "daily"
|
|
||||||
priority: float = 0.5
|
|
||||||
|
|
||||||
def items(self: StaticViewSitemap) -> list[str]:
|
|
||||||
"""Return all the items in the sitemap."""
|
|
||||||
return ["index", "feeds", "domains"]
|
|
||||||
|
|
||||||
def location(self: StaticViewSitemap, item: str) -> str:
|
|
||||||
"""Return the location of the item."""
|
|
||||||
return reverse(item)
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from django.contrib.sitemaps import GenericSitemap, Sitemap
|
|
||||||
from django.contrib.sitemaps.views import sitemap
|
|
||||||
from django.urls import include, path
|
|
||||||
from django.views.decorators.cache import cache_page
|
|
||||||
|
|
||||||
from feeds.models import Feed
|
|
||||||
from feedvault import views
|
|
||||||
from feedvault.sitemaps import StaticViewSitemap
|
|
||||||
|
|
||||||
app_name: str = "feedvault"
|
|
||||||
|
|
||||||
sitemaps: dict[str, type[Sitemap] | Sitemap] = {
|
|
||||||
"static": StaticViewSitemap,
|
|
||||||
"feeds": GenericSitemap({"queryset": Feed.objects.all(), "date_field": "created_at"}),
|
|
||||||
}
|
|
||||||
|
|
||||||
urlpatterns: list = [
|
|
||||||
path(route="", view=include("feeds.urls")),
|
|
||||||
path("__debug__/", include("debug_toolbar.urls")),
|
|
||||||
path(route="robots.txt", view=cache_page(timeout=60 * 60 * 365)(views.RobotsView.as_view()), name="robots"),
|
|
||||||
path(
|
|
||||||
"sitemap.xml",
|
|
||||||
sitemap,
|
|
||||||
{"sitemaps": sitemaps},
|
|
||||||
name="django.contrib.sitemaps.views.sitemap",
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
from django.http import HttpRequest, HttpResponse
|
|
||||||
from django.views import View
|
|
||||||
|
|
||||||
|
|
||||||
class RobotsView(View):
|
|
||||||
"""Robots.txt view."""
|
|
||||||
|
|
||||||
def get(self, request: HttpRequest) -> HttpResponse:
|
|
||||||
"""Load the robots.txt file."""
|
|
||||||
return HttpResponse(
|
|
||||||
content="User-agent: *\nDisallow: /add\nDisallow: /upload\nDisallow: /accounts/\n\nSitemap: https://feedvault.se/sitemap.xml",
|
|
||||||
content_type="text/plain",
|
|
||||||
)
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
import os
|
|
||||||
|
|
||||||
from django.core.handlers.wsgi import WSGIHandler
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
|
||||||
|
|
||||||
os.environ.setdefault(key="DJANGO_SETTINGS_MODULE", value="feedvault.settings")
|
|
||||||
|
|
||||||
application: WSGIHandler = get_wsgi_application()
|
|
||||||
1176
poetry.lock
generated
1176
poetry.lock
generated
|
|
@ -12,18 +12,24 @@ files = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asgiref"
|
name = "anyio"
|
||||||
version = "3.8.1"
|
version = "4.3.0"
|
||||||
description = "ASGI specs, helper code, and adapters"
|
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"},
|
{file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"},
|
||||||
{file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"},
|
{file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
idna = ">=2.8"
|
||||||
|
sniffio = ">=1.1"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
|
doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
|
||||||
|
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
|
||||||
|
trio = ["trio (>=0.23)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "beautifulsoup4"
|
name = "beautifulsoup4"
|
||||||
|
|
@ -46,98 +52,6 @@ charset-normalizer = ["charset-normalizer"]
|
||||||
html5lib = ["html5lib"]
|
html5lib = ["html5lib"]
|
||||||
lxml = ["lxml"]
|
lxml = ["lxml"]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "brotli"
|
|
||||||
version = "1.1.0"
|
|
||||||
description = "Python bindings for the Brotli compression library"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1140c64812cb9b06c922e77f1c26a75ec5e3f0fb2bf92cc8c58720dec276752"},
|
|
||||||
{file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8fd5270e906eef71d4a8d19b7c6a43760c6abcfcc10c9101d14eb2357418de9"},
|
|
||||||
{file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ae56aca0402a0f9a3431cddda62ad71666ca9d4dc3a10a142b9dce2e3c0cda3"},
|
|
||||||
{file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43ce1b9935bfa1ede40028054d7f48b5469cd02733a365eec8a329ffd342915d"},
|
|
||||||
{file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7c4855522edb2e6ae7fdb58e07c3ba9111e7621a8956f481c68d5d979c93032e"},
|
|
||||||
{file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:38025d9f30cf4634f8309c6874ef871b841eb3c347e90b0851f63d1ded5212da"},
|
|
||||||
{file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e6a904cb26bfefc2f0a6f240bdf5233be78cd2488900a2f846f3c3ac8489ab80"},
|
|
||||||
{file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a37b8f0391212d29b3a91a799c8e4a2855e0576911cdfb2515487e30e322253d"},
|
|
||||||
{file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0"},
|
|
||||||
{file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e"},
|
|
||||||
{file = "Brotli-1.1.0-cp310-cp310-win32.whl", hash = "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2"},
|
|
||||||
{file = "Brotli-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128"},
|
|
||||||
{file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc"},
|
|
||||||
{file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6"},
|
|
||||||
{file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd"},
|
|
||||||
{file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf"},
|
|
||||||
{file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61"},
|
|
||||||
{file = "Brotli-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327"},
|
|
||||||
{file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd"},
|
|
||||||
{file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9"},
|
|
||||||
{file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265"},
|
|
||||||
{file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8"},
|
|
||||||
{file = "Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50"},
|
|
||||||
{file = "Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1"},
|
|
||||||
{file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409"},
|
|
||||||
{file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2"},
|
|
||||||
{file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451"},
|
|
||||||
{file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91"},
|
|
||||||
{file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408"},
|
|
||||||
{file = "Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0"},
|
|
||||||
{file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc"},
|
|
||||||
{file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180"},
|
|
||||||
{file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248"},
|
|
||||||
{file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966"},
|
|
||||||
{file = "Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0"},
|
|
||||||
{file = "Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951"},
|
|
||||||
{file = "Brotli-1.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a090ca607cbb6a34b0391776f0cb48062081f5f60ddcce5d11838e67a01928d1"},
|
|
||||||
{file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de9d02f5bda03d27ede52e8cfe7b865b066fa49258cbab568720aa5be80a47d"},
|
|
||||||
{file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2333e30a5e00fe0fe55903c8832e08ee9c3b1382aacf4db26664a16528d51b4b"},
|
|
||||||
{file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4d4a848d1837973bf0f4b5e54e3bec977d99be36a7895c61abb659301b02c112"},
|
|
||||||
{file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fdc3ff3bfccdc6b9cc7c342c03aa2400683f0cb891d46e94b64a197910dc4064"},
|
|
||||||
{file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:5eeb539606f18a0b232d4ba45adccde4125592f3f636a6182b4a8a436548b914"},
|
|
||||||
{file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:fd5f17ff8f14003595ab414e45fce13d073e0762394f957182e69035c9f3d7c2"},
|
|
||||||
{file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:069a121ac97412d1fe506da790b3e69f52254b9df4eb665cd42460c837193354"},
|
|
||||||
{file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e93dfc1a1165e385cc8239fab7c036fb2cd8093728cbd85097b284d7b99249a2"},
|
|
||||||
{file = "Brotli-1.1.0-cp36-cp36m-win32.whl", hash = "sha256:a599669fd7c47233438a56936988a2478685e74854088ef5293802123b5b2460"},
|
|
||||||
{file = "Brotli-1.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d143fd47fad1db3d7c27a1b1d66162e855b5d50a89666af46e1679c496e8e579"},
|
|
||||||
{file = "Brotli-1.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:11d00ed0a83fa22d29bc6b64ef636c4552ebafcef57154b4ddd132f5638fbd1c"},
|
|
||||||
{file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f733d788519c7e3e71f0855c96618720f5d3d60c3cb829d8bbb722dddce37985"},
|
|
||||||
{file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:929811df5462e182b13920da56c6e0284af407d1de637d8e536c5cd00a7daf60"},
|
|
||||||
{file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b63b949ff929fbc2d6d3ce0e924c9b93c9785d877a21a1b678877ffbbc4423a"},
|
|
||||||
{file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d192f0f30804e55db0d0e0a35d83a9fead0e9a359a9ed0285dbacea60cc10a84"},
|
|
||||||
{file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f296c40e23065d0d6650c4aefe7470d2a25fffda489bcc3eb66083f3ac9f6643"},
|
|
||||||
{file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:919e32f147ae93a09fe064d77d5ebf4e35502a8df75c29fb05788528e330fe74"},
|
|
||||||
{file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:23032ae55523cc7bccb4f6a0bf368cd25ad9bcdcc1990b64a647e7bbcce9cb5b"},
|
|
||||||
{file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:224e57f6eac61cc449f498cc5f0e1725ba2071a3d4f48d5d9dffba42db196438"},
|
|
||||||
{file = "Brotli-1.1.0-cp37-cp37m-win32.whl", hash = "sha256:587ca6d3cef6e4e868102672d3bd9dc9698c309ba56d41c2b9c85bbb903cdb95"},
|
|
||||||
{file = "Brotli-1.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2954c1c23f81c2eaf0b0717d9380bd348578a94161a65b3a2afc62c86467dd68"},
|
|
||||||
{file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:efa8b278894b14d6da122a72fefcebc28445f2d3f880ac59d46c90f4c13be9a3"},
|
|
||||||
{file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:03d20af184290887bdea3f0f78c4f737d126c74dc2f3ccadf07e54ceca3bf208"},
|
|
||||||
{file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6172447e1b368dcbc458925e5ddaf9113477b0ed542df258d84fa28fc45ceea7"},
|
|
||||||
{file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a743e5a28af5f70f9c080380a5f908d4d21d40e8f0e0c8901604d15cfa9ba751"},
|
|
||||||
{file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0541e747cce78e24ea12d69176f6a7ddb690e62c425e01d31cc065e69ce55b48"},
|
|
||||||
{file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cdbc1fc1bc0bff1cef838eafe581b55bfbffaed4ed0318b724d0b71d4d377619"},
|
|
||||||
{file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:890b5a14ce214389b2cc36ce82f3093f96f4cc730c1cffdbefff77a7c71f2a97"},
|
|
||||||
{file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ab4fbee0b2d9098c74f3057b2bc055a8bd92ccf02f65944a241b4349229185a"},
|
|
||||||
{file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:141bd4d93984070e097521ed07e2575b46f817d08f9fa42b16b9b5f27b5ac088"},
|
|
||||||
{file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fce1473f3ccc4187f75b4690cfc922628aed4d3dd013d047f95a9b3919a86596"},
|
|
||||||
{file = "Brotli-1.1.0-cp38-cp38-win32.whl", hash = "sha256:db85ecf4e609a48f4b29055f1e144231b90edc90af7481aa731ba2d059226b1b"},
|
|
||||||
{file = "Brotli-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3d7954194c36e304e1523f55d7042c59dc53ec20dd4e9ea9d151f1b62b4415c0"},
|
|
||||||
{file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5fb2ce4b8045c78ebbc7b8f3c15062e435d47e7393cc57c25115cfd49883747a"},
|
|
||||||
{file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7905193081db9bfa73b1219140b3d315831cbff0d8941f22da695832f0dd188f"},
|
|
||||||
{file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a77def80806c421b4b0af06f45d65a136e7ac0bdca3c09d9e2ea4e515367c7e9"},
|
|
||||||
{file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dadd1314583ec0bf2d1379f7008ad627cd6336625d6679cf2f8e67081b83acf"},
|
|
||||||
{file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:901032ff242d479a0efa956d853d16875d42157f98951c0230f69e69f9c09bac"},
|
|
||||||
{file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22fc2a8549ffe699bfba2256ab2ed0421a7b8fadff114a3d201794e45a9ff578"},
|
|
||||||
{file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ae15b066e5ad21366600ebec29a7ccbc86812ed267e4b28e860b8ca16a2bc474"},
|
|
||||||
{file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:949f3b7c29912693cee0afcf09acd6ebc04c57af949d9bf77d6101ebb61e388c"},
|
|
||||||
{file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:89f4988c7203739d48c6f806f1e87a1d96e0806d44f0fba61dba81392c9e474d"},
|
|
||||||
{file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:de6551e370ef19f8de1807d0a9aa2cdfdce2e85ce88b122fe9f6b2b076837e59"},
|
|
||||||
{file = "Brotli-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f0d8a7a6b5983c2496e364b969f0e526647a06b075d034f3297dc66f3b360c64"},
|
|
||||||
{file = "Brotli-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cdad5b9014d83ca68c25d2e9444e28e967ef16e80f6b436918c700c117a85467"},
|
|
||||||
{file = "Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "certifi"
|
name = "certifi"
|
||||||
version = "2024.2.2"
|
version = "2024.2.2"
|
||||||
|
|
@ -299,28 +213,6 @@ editorconfig = ">=0.12.2"
|
||||||
jsbeautifier = "*"
|
jsbeautifier = "*"
|
||||||
six = ">=1.13.0"
|
six = ">=1.13.0"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dateparser"
|
|
||||||
version = "1.2.0"
|
|
||||||
description = "Date parsing library designed to parse dates from HTML pages"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "dateparser-1.2.0-py2.py3-none-any.whl", hash = "sha256:0b21ad96534e562920a0083e97fd45fa959882d4162acc358705144520a35830"},
|
|
||||||
{file = "dateparser-1.2.0.tar.gz", hash = "sha256:7975b43a4222283e0ae15be7b4999d08c9a70e2d378ac87385b1ccf2cffbbb30"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
python-dateutil = "*"
|
|
||||||
pytz = "*"
|
|
||||||
regex = "<2019.02.19 || >2019.02.19,<2021.8.27 || >2021.8.27"
|
|
||||||
tzlocal = "*"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
calendars = ["convertdate", "hijri-converter"]
|
|
||||||
fasttext = ["fasttext"]
|
|
||||||
langdetect = ["langdetect"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "distlib"
|
name = "distlib"
|
||||||
version = "0.3.8"
|
version = "0.3.8"
|
||||||
|
|
@ -332,97 +224,6 @@ files = [
|
||||||
{file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
|
{file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "django"
|
|
||||||
version = "5.0.6"
|
|
||||||
description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.10"
|
|
||||||
files = [
|
|
||||||
{file = "Django-5.0.6-py3-none-any.whl", hash = "sha256:8363ac062bb4ef7c3f12d078f6fa5d154031d129a15170a1066412af49d30905"},
|
|
||||||
{file = "Django-5.0.6.tar.gz", hash = "sha256:ff1b61005004e476e0aeea47c7f79b85864c70124030e95146315396f1e7951f"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
asgiref = ">=3.7.0,<4"
|
|
||||||
sqlparse = ">=0.3.1"
|
|
||||||
tzdata = {version = "*", markers = "sys_platform == \"win32\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
argon2 = ["argon2-cffi (>=19.1.0)"]
|
|
||||||
bcrypt = ["bcrypt"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "django-debug-toolbar"
|
|
||||||
version = "4.3.0"
|
|
||||||
description = "A configurable set of panels that display various debug information about the current request/response."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "django_debug_toolbar-4.3.0-py3-none-any.whl", hash = "sha256:e09b7dcb8417b743234dfc57c95a7c1d1d87a88844abd13b4c5387f807b31bf6"},
|
|
||||||
{file = "django_debug_toolbar-4.3.0.tar.gz", hash = "sha256:0b0dddee5ea29b9cb678593bc0d7a6d76b21d7799cb68e091a2148341a80f3c4"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
django = ">=3.2.4"
|
|
||||||
sqlparse = ">=0.2"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "django-htmx"
|
|
||||||
version = "1.17.3"
|
|
||||||
description = "Extensions for using Django with htmx."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "django-htmx-1.17.3.tar.gz", hash = "sha256:a2069219920d7ef0883ddbf5e8d931069db145a0d4a8a032a2708f840c7a68a6"},
|
|
||||||
{file = "django_htmx-1.17.3-py3-none-any.whl", hash = "sha256:0de964ca257eda2a4ebeeaa8181320119378fa5f95a2fc2f2bfbdd35034ed424"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
asgiref = ">=3.6"
|
|
||||||
Django = ">=3.2"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "django-ninja"
|
|
||||||
version = "1.1.0"
|
|
||||||
description = "Django Ninja - Fast Django REST framework"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "django_ninja-1.1.0-py3-none-any.whl", hash = "sha256:6330c3497061d9fd1f43c1200f85c13aab7687110e2899f8304e5aa476c10b44"},
|
|
||||||
{file = "django_ninja-1.1.0.tar.gz", hash = "sha256:87bff046416a2653ed2fbef1408e101292bf8170684821bac82accfd73bef059"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
Django = ">=3.1"
|
|
||||||
pydantic = ">=2.0,<3.0.0"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
dev = ["pre-commit"]
|
|
||||||
doc = ["markdown-include", "mkdocs", "mkdocs-material", "mkdocstrings"]
|
|
||||||
test = ["django-stubs", "mypy (==1.7.1)", "psycopg2-binary", "pytest", "pytest-asyncio", "pytest-cov", "pytest-django", "ruff (==0.1.7)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "django-redis"
|
|
||||||
version = "5.4.0"
|
|
||||||
description = "Full featured redis cache backend for Django."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "django-redis-5.4.0.tar.gz", hash = "sha256:6a02abaa34b0fea8bf9b707d2c363ab6adc7409950b2db93602e6cb292818c42"},
|
|
||||||
{file = "django_redis-5.4.0-py3-none-any.whl", hash = "sha256:ebc88df7da810732e2af9987f7f426c96204bf89319df4c6da6ca9a2942edd5b"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
Django = ">=3.2"
|
|
||||||
redis = [
|
|
||||||
{version = ">=3,<4.0.0 || >4.0.0,<4.0.1 || >4.0.1"},
|
|
||||||
{version = ">=3,<4.0.0 || >4.0.0,<4.0.1 || >4.0.1", extras = ["hiredis"], optional = true, markers = "extra == \"hiredis\""},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
hiredis = ["redis[hiredis] (>=3,!=4.0.0,!=4.0.1)"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "djlint"
|
name = "djlint"
|
||||||
version = "1.34.1"
|
version = "1.34.1"
|
||||||
|
|
@ -447,6 +248,26 @@ PyYAML = ">=6.0,<7.0"
|
||||||
regex = ">=2023.0.0,<2024.0.0"
|
regex = ">=2023.0.0,<2024.0.0"
|
||||||
tqdm = ">=4.62.2,<5.0.0"
|
tqdm = ">=4.62.2,<5.0.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dnspython"
|
||||||
|
version = "2.6.1"
|
||||||
|
description = "DNS toolkit"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"},
|
||||||
|
{file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"]
|
||||||
|
dnssec = ["cryptography (>=41)"]
|
||||||
|
doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"]
|
||||||
|
doq = ["aioquic (>=0.9.25)"]
|
||||||
|
idna = ["idna (>=3.6)"]
|
||||||
|
trio = ["trio (>=0.23)"]
|
||||||
|
wmi = ["wmi (>=1.5.1)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "editorconfig"
|
name = "editorconfig"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
|
|
@ -457,6 +278,65 @@ files = [
|
||||||
{file = "EditorConfig-0.12.4.tar.gz", hash = "sha256:24857fa1793917dd9ccf0c7810a07e05404ce9b823521c7dce22a4fb5d125f80"},
|
{file = "EditorConfig-0.12.4.tar.gz", hash = "sha256:24857fa1793917dd9ccf0c7810a07e05404ce9b823521c7dce22a4fb5d125f80"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "email-validator"
|
||||||
|
version = "2.1.1"
|
||||||
|
description = "A robust email address syntax and deliverability validation library."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "email_validator-2.1.1-py3-none-any.whl", hash = "sha256:97d882d174e2a65732fb43bfce81a3a834cbc1bde8bf419e30ef5ea976370a05"},
|
||||||
|
{file = "email_validator-2.1.1.tar.gz", hash = "sha256:200a70680ba08904be6d1eef729205cc0d687634399a5924d842533efb824b84"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
dnspython = ">=2.0.0"
|
||||||
|
idna = ">=2.0.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastapi"
|
||||||
|
version = "0.111.0"
|
||||||
|
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "fastapi-0.111.0-py3-none-any.whl", hash = "sha256:97ecbf994be0bcbdadedf88c3150252bed7b2087075ac99735403b1b76cc8fc0"},
|
||||||
|
{file = "fastapi-0.111.0.tar.gz", hash = "sha256:b9db9dd147c91cb8b769f7183535773d8741dd46f9dc6676cd82eab510228cd7"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
email_validator = ">=2.0.0"
|
||||||
|
fastapi-cli = ">=0.0.2"
|
||||||
|
httpx = ">=0.23.0"
|
||||||
|
jinja2 = ">=2.11.2"
|
||||||
|
orjson = ">=3.2.1"
|
||||||
|
pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
|
||||||
|
python-multipart = ">=0.0.7"
|
||||||
|
starlette = ">=0.37.2,<0.38.0"
|
||||||
|
typing-extensions = ">=4.8.0"
|
||||||
|
ujson = ">=4.0.1,<4.0.2 || >4.0.2,<4.1.0 || >4.1.0,<4.2.0 || >4.2.0,<4.3.0 || >4.3.0,<5.0.0 || >5.0.0,<5.1.0 || >5.1.0"
|
||||||
|
uvicorn = {version = ">=0.12.0", extras = ["standard"]}
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
all = ["email_validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastapi-cli"
|
||||||
|
version = "0.0.4"
|
||||||
|
description = "Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "fastapi_cli-0.0.4-py3-none-any.whl", hash = "sha256:a2552f3a7ae64058cdbb530be6fa6dbfc975dc165e4fa66d224c3d396e25e809"},
|
||||||
|
{file = "fastapi_cli-0.0.4.tar.gz", hash = "sha256:e2e9ffaffc1f7767f488d6da34b6f5a377751c996f397902eb6abb99a67bde32"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
typer = ">=0.12.3"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
standard = ["fastapi", "uvicorn[standard] (>=0.15.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "feedparser"
|
name = "feedparser"
|
||||||
version = "6.0.11"
|
version = "6.0.11"
|
||||||
|
|
@ -488,141 +368,14 @@ testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)",
|
||||||
typing = ["typing-extensions (>=4.8)"]
|
typing = ["typing-extensions (>=4.8)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gunicorn"
|
name = "h11"
|
||||||
version = "21.2.0"
|
version = "0.14.0"
|
||||||
description = "WSGI HTTP Server for UNIX"
|
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.5"
|
|
||||||
files = [
|
|
||||||
{file = "gunicorn-21.2.0-py3-none-any.whl", hash = "sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0"},
|
|
||||||
{file = "gunicorn-21.2.0.tar.gz", hash = "sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
packaging = "*"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
eventlet = ["eventlet (>=0.24.1)"]
|
|
||||||
gevent = ["gevent (>=1.4.0)"]
|
|
||||||
setproctitle = ["setproctitle"]
|
|
||||||
tornado = ["tornado (>=0.2)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hiredis"
|
|
||||||
version = "2.3.2"
|
|
||||||
description = "Python wrapper for hiredis"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:742093f33d374098aa21c1696ac6e4874b52658c870513a297a89265a4d08fe5"},
|
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:9e14fb70ca4f7efa924f508975199353bf653f452e4ef0a1e47549e208f943d7"},
|
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d7302b4b17fcc1cc727ce84ded7f6be4655701e8d58744f73b09cb9ed2b13df"},
|
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed63e8b75c193c5e5a8288d9d7b011da076cc314fafc3bfd59ec1d8a750d48c8"},
|
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b4edee59dc089bc3948f4f6fba309f51aa2ccce63902364900aa0a553a85e97"},
|
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6481c3b7673a86276220140456c2a6fbfe8d1fb5c613b4728293c8634134824"},
|
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:684840b014ce83541a087fcf2d48227196576f56ae3e944d4dfe14c0a3e0ccb7"},
|
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c4c0bcf786f0eac9593367b6279e9b89534e008edbf116dcd0de956524702c8"},
|
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66ab949424ac6504d823cba45c4c4854af5c59306a1531edb43b4dd22e17c102"},
|
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:322c668ee1c12d6c5750a4b1057e6b4feee2a75b3d25d630922a463cfe5e7478"},
|
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bfa73e3f163c6e8b2ec26f22285d717a5f77ab2120c97a2605d8f48b26950dac"},
|
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:7f39f28ffc65de577c3bc0c7615f149e35bc927802a0f56e612db9b530f316f9"},
|
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:55ce31bf4711da879b96d511208efb65a6165da4ba91cb3a96d86d5a8d9d23e6"},
|
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-win32.whl", hash = "sha256:3dd63d0bbbe75797b743f35d37a4cca7ca7ba35423a0de742ae2985752f20c6d"},
|
|
||||||
{file = "hiredis-2.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:ea002656a8d974daaf6089863ab0a306962c8b715db6b10879f98b781a2a5bf5"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:adfbf2e9c38b77d0db2fb32c3bdaea638fa76b4e75847283cd707521ad2475ef"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:80b02d27864ebaf9b153d4b99015342382eeaed651f5591ce6f07e840307c56d"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd40d2e2f82a483de0d0a6dfd8c3895a02e55e5c9949610ecbded18188fd0a56"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfa904045d7cebfb0f01dad51352551cce1d873d7c3f80c7ded7d42f8cac8f89"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:28bd184b33e0dd6d65816c16521a4ba1ffbe9ff07d66873c42ea4049a62fed83"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f70481213373d44614148f0f2e38e7905be3f021902ae5167289413196de4ba4"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8797b528c1ff81eef06713623562b36db3dafa106b59f83a6468df788ff0d1"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02fc71c8333586871602db4774d3a3e403b4ccf6446dc4603ec12df563127cee"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0da56915bda1e0a49157191b54d3e27689b70960f0685fdd5c415dacdee2fbed"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e2674a5a3168349435b08fa0b82998ed2536eb9acccf7087efe26e4cd088a525"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:dc1c3fd49930494a67dcec37d0558d99d84eca8eb3f03b17198424538f2608d7"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:14c7b43205e515f538a9defb4e411e0f0576caaeeda76bb9993ed505486f7562"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7bac7e02915b970c3723a7a7c5df4ba7a11a3426d2a3f181e041aa506a1ff028"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-win32.whl", hash = "sha256:63a090761ddc3c1f7db5e67aa4e247b4b3bb9890080bdcdadd1b5200b8b89ac4"},
|
|
||||||
{file = "hiredis-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:70d226ab0306a5b8d408235cabe51d4bf3554c9e8a72d53ce0b3c5c84cf78881"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:5c614552c6bd1d0d907f448f75550f6b24fb56cbfce80c094908b7990cad9702"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:9c431431abf55b64347ddc8df68b3ef840269cb0aa5bc2d26ad9506eb4b1b866"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a45857e87e9d2b005e81ddac9d815a33efd26ec67032c366629f023fe64fb415"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e138d141ec5a6ec800b6d01ddc3e5561ce1c940215e0eb9960876bfde7186aae"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:387f655444d912a963ab68abf64bf6e178a13c8e4aa945cb27388fd01a02e6f1"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4852f4bf88f0e2d9bdf91279892f5740ed22ae368335a37a52b92a5c88691140"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d711c107e83117129b7f8bd08e9820c43ceec6204fff072a001fd82f6d13db9f"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92830c16885f29163e1c2da1f3c1edb226df1210ec7e8711aaabba3dd0d5470a"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:16b01d9ceae265d4ab9547be0cd628ecaff14b3360357a9d30c029e5ae8b7e7f"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:5986fb5f380169270a0293bebebd95466a1c85010b4f1afc2727e4d17c452512"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:49532d7939cc51f8e99efc326090c54acf5437ed88b9c904cc8015b3c4eda9c9"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:8f34801b251ca43ad70691fb08b606a2e55f06b9c9fb1fc18fd9402b19d70f7b"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7298562a49d95570ab1c7fc4051e72824c6a80e907993a21a41ba204223e7334"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-win32.whl", hash = "sha256:e1d86b75de787481b04d112067a4033e1ecfda2a060e50318a74e4e1c9b2948c"},
|
|
||||||
{file = "hiredis-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:6dbfe1887ffa5cf3030451a56a8f965a9da2fa82b7149357752b67a335a05fc6"},
|
|
||||||
{file = "hiredis-2.3.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:4fc242e9da4af48714199216eb535b61e8f8d66552c8819e33fc7806bd465a09"},
|
|
||||||
{file = "hiredis-2.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e81aa4e9a1fcf604c8c4b51aa5d258e195a6ba81efe1da82dea3204443eba01c"},
|
|
||||||
{file = "hiredis-2.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:419780f8583ddb544ffa86f9d44a7fcc183cd826101af4e5ffe535b6765f5f6b"},
|
|
||||||
{file = "hiredis-2.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6871306d8b98a15e53a5f289ec1106a3a1d43e7ab6f4d785f95fcef9a7bd9504"},
|
|
||||||
{file = "hiredis-2.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88cb0b35b63717ef1e41d62f4f8717166f7c6245064957907cfe177cc144357c"},
|
|
||||||
{file = "hiredis-2.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c490191fa1218851f8a80c5a21a05a6f680ac5aebc2e688b71cbfe592f8fec6"},
|
|
||||||
{file = "hiredis-2.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4baf4b579b108062e91bd2a991dc98b9dc3dc06e6288db2d98895eea8acbac22"},
|
|
||||||
{file = "hiredis-2.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e627d8ef5e100556e09fb44c9571a432b10e11596d3c4043500080ca9944a91a"},
|
|
||||||
{file = "hiredis-2.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:ba3dc0af0def8c21ce7d903c59ea1e8ec4cb073f25ece9edaec7f92a286cd219"},
|
|
||||||
{file = "hiredis-2.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:56e9b7d6051688ca94e68c0c8a54a243f8db841911b683cedf89a29d4de91509"},
|
|
||||||
{file = "hiredis-2.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:380e029bb4b1d34cf560fcc8950bf6b57c2ef0c9c8b7c7ac20b7c524a730fadd"},
|
|
||||||
{file = "hiredis-2.3.2-cp37-cp37m-win32.whl", hash = "sha256:948d9f2ca7841794dd9b204644963a4bcd69ced4e959b0d4ecf1b8ce994a6daa"},
|
|
||||||
{file = "hiredis-2.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:cfa67afe2269b2d203cd1389c00c5bc35a287cd57860441fb0e53b371ea6a029"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:bcbe47da0aebc00a7cfe3ebdcff0373b86ce2b1856251c003e3d69c9db44b5a7"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f2c9c0d910dd3f7df92f0638e7f65d8edd7f442203caf89c62fc79f11b0b73f8"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:01b6c24c0840ac7afafbc4db236fd55f56a9a0919a215c25a238f051781f4772"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1f567489f422d40c21e53212a73bef4638d9f21043848150f8544ef1f3a6ad1"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:28adecb308293e705e44087a1c2d557a816f032430d8a2a9bb7873902a1c6d48"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27e9619847e9dc70b14b1ad2d0fb4889e7ca18996585c3463cff6c951fd6b10b"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a0026cfbf29f07649b0e34509091a2a6016ff8844b127de150efce1c3aff60b"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9de7586522e5da6bee83c9cf0dcccac0857a43249cb4d721a2e312d98a684d1"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e58494f282215fc461b06709e9a195a24c12ba09570f25bdf9efb036acc05101"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3a32b4b76d46f1eb42b24a918d51d8ca52411a381748196241d59a895f7c5c"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:1979334ccab21a49c544cd1b8d784ffb2747f99a51cb0bd0976eebb517628382"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:0c0773266e1c38a06e7593bd08870ac1503f5f0ce0f5c63f2b4134b090b5d6a4"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bd1cee053416183adcc8e6134704c46c60c3f66b8faaf9e65bf76191ca59a2f7"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-win32.whl", hash = "sha256:5341ce3d01ef3c7418a72e370bf028c7aeb16895e79e115fe4c954fff990489e"},
|
|
||||||
{file = "hiredis-2.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:8fc7197ff33047ce43a67851ccf190acb5b05c52fd4a001bb55766358f04da68"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:f47775e27388b58ce52f4f972f80e45b13c65113e9e6b6bf60148f893871dc9b"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:9412a06b8a8e09abd6313d96864b6d7713c6003a365995a5c70cfb9209df1570"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3020b60e3fc96d08c2a9b011f1c2e2a6bdcc09cb55df93c509b88be5cb791df"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53d0f2c59bce399b8010a21bc779b4f8c32d0f582b2284ac8c98dc7578b27bc4"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57c0d0c7e308ed5280a4900d4468bbfec51f0e1b4cde1deae7d4e639bc6b7766"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d63318ca189fddc7e75f6a4af8eae9c0545863619fb38cfba5f43e81280b286"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e741ffe4e2db78a1b9dd6e5d29678ce37fbaaf65dfe132e5b82a794413302ef1"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb98038ccd368e0d88bd92ee575c58cfaf33e77f788c36b2a89a84ee1936dc6b"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:eae62ed60d53b3561148bcd8c2383e430af38c0deab9f2dd15f8874888ffd26f"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ca33c175c1cf60222d9c6d01c38fc17ec3a484f32294af781de30226b003e00f"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c5f6972d2bdee3cd301d5c5438e31195cf1cabf6fd9274491674d4ceb46914d"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:a6b54dabfaa5dbaa92f796f0c32819b4636e66aa8e9106c3d421624bd2a2d676"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e96cd35df012a17c87ae276196ea8f215e77d6eeca90709eb03999e2d5e3fd8a"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-win32.whl", hash = "sha256:63b99b5ea9fe4f21469fb06a16ca5244307678636f11917359e3223aaeca0b67"},
|
|
||||||
{file = "hiredis-2.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:a50c8af811b35b8a43b1590cf890b61ff2233225257a3cad32f43b3ec7ff1b9f"},
|
|
||||||
{file = "hiredis-2.3.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7e8bf4444b09419b77ce671088db9f875b26720b5872d97778e2545cd87dba4a"},
|
|
||||||
{file = "hiredis-2.3.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bd42d0d45ea47a2f96babd82a659fbc60612ab9423a68e4a8191e538b85542a"},
|
|
||||||
{file = "hiredis-2.3.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80441b55edbef868e2563842f5030982b04349408396e5ac2b32025fb06b5212"},
|
|
||||||
{file = "hiredis-2.3.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec444ab8f27562a363672d6a7372bc0700a1bdc9764563c57c5f9efa0e592b5f"},
|
|
||||||
{file = "hiredis-2.3.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f9f606e810858207d4b4287b4ef0dc622c2aa469548bf02b59dcc616f134f811"},
|
|
||||||
{file = "hiredis-2.3.2-pp37-pypy37_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c3dde4ca00fe9eee3b76209711f1941bb86db42b8a75d7f2249ff9dfc026ab0e"},
|
|
||||||
{file = "hiredis-2.3.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4dd676107a1d3c724a56a9d9db38166ad4cf44f924ee701414751bd18a784a0"},
|
|
||||||
{file = "hiredis-2.3.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce42649e2676ad783186264d5ffc788a7612ecd7f9effb62d51c30d413a3eefe"},
|
|
||||||
{file = "hiredis-2.3.2-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e3f8b1733078ac663dad57e20060e16389a60ab542f18a97931f3a2a2dd64a4"},
|
|
||||||
{file = "hiredis-2.3.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:532a84a82156a82529ec401d1c25d677c6543c791e54a263aa139541c363995f"},
|
|
||||||
{file = "hiredis-2.3.2-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4d59f88c4daa36b8c38e59ac7bffed6f5d7f68eaccad471484bf587b28ccc478"},
|
|
||||||
{file = "hiredis-2.3.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a91a14dd95e24dc078204b18b0199226ee44644974c645dc54ee7b00c3157330"},
|
|
||||||
{file = "hiredis-2.3.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb777a38797c8c7df0444533119570be18d1a4ce5478dffc00c875684df7bfcb"},
|
|
||||||
{file = "hiredis-2.3.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d47c915897a99d0d34a39fad4be97b4b709ab3d0d3b779ebccf2b6024a8c681e"},
|
|
||||||
{file = "hiredis-2.3.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:333b5e04866758b11bda5f5315b4e671d15755fc6ed3b7969721bc6311d0ee36"},
|
|
||||||
{file = "hiredis-2.3.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c8937f1100435698c18e4da086968c4b5d70e86ea718376f833475ab3277c9aa"},
|
|
||||||
{file = "hiredis-2.3.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa45f7d771094b8145af10db74704ab0f698adb682fbf3721d8090f90e42cc49"},
|
|
||||||
{file = "hiredis-2.3.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33d5ebc93c39aed4b5bc769f8ce0819bc50e74bb95d57a35f838f1c4378978e0"},
|
|
||||||
{file = "hiredis-2.3.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a797d8c7df9944314d309b0d9e1b354e2fa4430a05bb7604da13b6ad291bf959"},
|
|
||||||
{file = "hiredis-2.3.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e15a408f71a6c8c87b364f1f15a6cd9c1baca12bbc47a326ac8ab99ec7ad3c64"},
|
|
||||||
{file = "hiredis-2.3.2.tar.gz", hash = "sha256:733e2456b68f3f126ddaf2cd500a33b25146c3676b97ea843665717bda0c5d43"},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -647,6 +400,113 @@ files = [
|
||||||
{file = "html_void_elements-0.1.0-py3-none-any.whl", hash = "sha256:784cf39db03cdeb017320d9301009f8f3480f9d7b254d0974272e80e0cb5e0d2"},
|
{file = "html_void_elements-0.1.0-py3-none-any.whl", hash = "sha256:784cf39db03cdeb017320d9301009f8f3480f9d7b254d0974272e80e0cb5e0d2"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httpcore"
|
||||||
|
version = "1.0.5"
|
||||||
|
description = "A minimal low-level HTTP client."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"},
|
||||||
|
{file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
certifi = "*"
|
||||||
|
h11 = ">=0.13,<0.15"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
asyncio = ["anyio (>=4.0,<5.0)"]
|
||||||
|
http2 = ["h2 (>=3,<5)"]
|
||||||
|
socks = ["socksio (==1.*)"]
|
||||||
|
trio = ["trio (>=0.22.0,<0.26.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httptools"
|
||||||
|
version = "0.6.1"
|
||||||
|
description = "A collection of framework independent HTTP protocol utils."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8.0"
|
||||||
|
files = [
|
||||||
|
{file = "httptools-0.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f"},
|
||||||
|
{file = "httptools-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563"},
|
||||||
|
{file = "httptools-0.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58"},
|
||||||
|
{file = "httptools-0.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185"},
|
||||||
|
{file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142"},
|
||||||
|
{file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658"},
|
||||||
|
{file = "httptools-0.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b"},
|
||||||
|
{file = "httptools-0.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1"},
|
||||||
|
{file = "httptools-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0"},
|
||||||
|
{file = "httptools-0.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc"},
|
||||||
|
{file = "httptools-0.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2"},
|
||||||
|
{file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837"},
|
||||||
|
{file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d"},
|
||||||
|
{file = "httptools-0.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3"},
|
||||||
|
{file = "httptools-0.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0"},
|
||||||
|
{file = "httptools-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2"},
|
||||||
|
{file = "httptools-0.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90"},
|
||||||
|
{file = "httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503"},
|
||||||
|
{file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84"},
|
||||||
|
{file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb"},
|
||||||
|
{file = "httptools-0.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949"},
|
||||||
|
{file = "httptools-0.6.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8e216a038d2d52ea13fdd9b9c9c7459fb80d78302b257828285eca1c773b99b3"},
|
||||||
|
{file = "httptools-0.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3e802e0b2378ade99cd666b5bffb8b2a7cc8f3d28988685dc300469ea8dd86cb"},
|
||||||
|
{file = "httptools-0.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd3e488b447046e386a30f07af05f9b38d3d368d1f7b4d8f7e10af85393db97"},
|
||||||
|
{file = "httptools-0.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe467eb086d80217b7584e61313ebadc8d187a4d95bb62031b7bab4b205c3ba3"},
|
||||||
|
{file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3c3b214ce057c54675b00108ac42bacf2ab8f85c58e3f324a4e963bbc46424f4"},
|
||||||
|
{file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ae5b97f690badd2ca27cbf668494ee1b6d34cf1c464271ef7bfa9ca6b83ffaf"},
|
||||||
|
{file = "httptools-0.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:405784577ba6540fa7d6ff49e37daf104e04f4b4ff2d1ac0469eaa6a20fde084"},
|
||||||
|
{file = "httptools-0.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:95fb92dd3649f9cb139e9c56604cc2d7c7bf0fc2e7c8d7fbd58f96e35eddd2a3"},
|
||||||
|
{file = "httptools-0.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dcbab042cc3ef272adc11220517278519adf8f53fd3056d0e68f0a6f891ba94e"},
|
||||||
|
{file = "httptools-0.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf2372e98406efb42e93bfe10f2948e467edfd792b015f1b4ecd897903d3e8d"},
|
||||||
|
{file = "httptools-0.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:678fcbae74477a17d103b7cae78b74800d795d702083867ce160fc202104d0da"},
|
||||||
|
{file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e0b281cf5a125c35f7f6722b65d8542d2e57331be573e9e88bc8b0115c4a7a81"},
|
||||||
|
{file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95658c342529bba4e1d3d2b1a874db16c7cca435e8827422154c9da76ac4e13a"},
|
||||||
|
{file = "httptools-0.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ebaec1bf683e4bf5e9fbb49b8cc36da482033596a415b3e4ebab5a4c0d7ec5e"},
|
||||||
|
{file = "httptools-0.6.1.tar.gz", hash = "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
test = ["Cython (>=0.29.24,<0.30.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httpx"
|
||||||
|
version = "0.27.0"
|
||||||
|
description = "The next generation HTTP client."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"},
|
||||||
|
{file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
anyio = "*"
|
||||||
|
certifi = "*"
|
||||||
|
httpcore = "==1.*"
|
||||||
|
idna = "*"
|
||||||
|
sniffio = "*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
brotli = ["brotli", "brotlicffi"]
|
||||||
|
cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
|
||||||
|
http2 = ["h2 (>=3,<5)"]
|
||||||
|
socks = ["socksio (==1.*)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humanize"
|
||||||
|
version = "4.9.0"
|
||||||
|
description = "Python humanize utilities"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "humanize-4.9.0-py3-none-any.whl", hash = "sha256:ce284a76d5b1377fd8836733b983bfb0b76f1aa1c090de2566fcf008d7f6ab16"},
|
||||||
|
{file = "humanize-4.9.0.tar.gz", hash = "sha256:582a265c931c683a7e9b8ed9559089dea7edcf6cc95be39a3cbc2c5d5ac2bcfa"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
tests = ["freezegun", "pytest", "pytest-cov"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "identify"
|
name = "identify"
|
||||||
version = "2.5.36"
|
version = "2.5.36"
|
||||||
|
|
@ -683,6 +543,23 @@ files = [
|
||||||
{file = "iso8601-2.1.0.tar.gz", hash = "sha256:6b1d3829ee8921c4301998c909f7829fa9ed3cbdac0d3b16af2d743aed1ba8df"},
|
{file = "iso8601-2.1.0.tar.gz", hash = "sha256:6b1d3829ee8921c4301998c909f7829fa9ed3cbdac0d3b16af2d743aed1ba8df"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jinja2"
|
||||||
|
version = "3.1.4"
|
||||||
|
description = "A very fast and expressive template engine."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
|
||||||
|
{file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
MarkupSafe = ">=2.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
i18n = ["Babel (>=2.7)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsbeautifier"
|
name = "jsbeautifier"
|
||||||
version = "1.15.1"
|
version = "1.15.1"
|
||||||
|
|
@ -827,14 +704,58 @@ files = [
|
||||||
setuptools = "*"
|
setuptools = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "packaging"
|
name = "orjson"
|
||||||
version = "24.0"
|
version = "3.10.3"
|
||||||
description = "Core utilities for Python packages"
|
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"},
|
{file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"},
|
||||||
{file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"},
|
{file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"},
|
||||||
|
{file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"},
|
||||||
|
{file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"},
|
||||||
|
{file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"},
|
||||||
|
{file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"},
|
||||||
|
{file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"},
|
||||||
|
{file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"},
|
||||||
|
{file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"},
|
||||||
|
{file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"},
|
||||||
|
{file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"},
|
||||||
|
{file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"},
|
||||||
|
{file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"},
|
||||||
|
{file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"},
|
||||||
|
{file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"},
|
||||||
|
{file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"},
|
||||||
|
{file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"},
|
||||||
|
{file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"},
|
||||||
|
{file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"},
|
||||||
|
{file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"},
|
||||||
|
{file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"},
|
||||||
|
{file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"},
|
||||||
|
{file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"},
|
||||||
|
{file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"},
|
||||||
|
{file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"},
|
||||||
|
{file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"},
|
||||||
|
{file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"},
|
||||||
|
{file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"},
|
||||||
|
{file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"},
|
||||||
|
{file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"},
|
||||||
|
{file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"},
|
||||||
|
{file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"},
|
||||||
|
{file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"},
|
||||||
|
{file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"},
|
||||||
|
{file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"},
|
||||||
|
{file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"},
|
||||||
|
{file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"},
|
||||||
|
{file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"},
|
||||||
|
{file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"},
|
||||||
|
{file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"},
|
||||||
|
{file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"},
|
||||||
|
{file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"},
|
||||||
|
{file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"},
|
||||||
|
{file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"},
|
||||||
|
{file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"},
|
||||||
|
{file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -882,102 +803,6 @@ nodeenv = ">=0.11.1"
|
||||||
pyyaml = ">=5.1"
|
pyyaml = ">=5.1"
|
||||||
virtualenv = ">=20.10.0"
|
virtualenv = ">=20.10.0"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "psycopg"
|
|
||||||
version = "3.1.19"
|
|
||||||
description = "PostgreSQL database adapter for Python"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "psycopg-3.1.19-py3-none-any.whl", hash = "sha256:dca5e5521c859f6606686432ae1c94e8766d29cc91f2ee595378c510cc5b0731"},
|
|
||||||
{file = "psycopg-3.1.19.tar.gz", hash = "sha256:92d7b78ad82426cdcf1a0440678209faa890c6e1721361c2f8901f0dccd62961"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
psycopg-binary = {version = "3.1.19", optional = true, markers = "implementation_name != \"pypy\" and extra == \"binary\""}
|
|
||||||
typing-extensions = ">=4.1"
|
|
||||||
tzdata = {version = "*", markers = "sys_platform == \"win32\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
binary = ["psycopg-binary (==3.1.19)"]
|
|
||||||
c = ["psycopg-c (==3.1.19)"]
|
|
||||||
dev = ["black (>=24.1.0)", "codespell (>=2.2)", "dnspython (>=2.1)", "flake8 (>=4.0)", "mypy (>=1.4.1)", "types-setuptools (>=57.4)", "wheel (>=0.37)"]
|
|
||||||
docs = ["Sphinx (>=5.0)", "furo (==2022.6.21)", "sphinx-autobuild (>=2021.3.14)", "sphinx-autodoc-typehints (>=1.12)"]
|
|
||||||
pool = ["psycopg-pool"]
|
|
||||||
test = ["anyio (>=3.6.2,<4.0)", "mypy (>=1.4.1)", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "psycopg-binary"
|
|
||||||
version = "3.1.19"
|
|
||||||
description = "PostgreSQL database adapter for Python -- C optimisation distribution"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "psycopg_binary-3.1.19-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7204818f05151dd08f8f851defb01972ec9d2cc925608eb0de232563f203f354"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d4e67fd86758dbeac85641419a54f84d74495a8683b58ad5dfad08b7fc37a8f"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e12173e34b176e93ad2da913de30f774d5119c2d4d4640c6858d2d77dfa6c9bf"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:052f5193304066318853b4b2e248f523c8f52b371fc4e95d4ef63baee3f30955"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29008f3f8977f600b8a7fb07c2e041b01645b08121760609cc45e861a0364dc9"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c6a9a651a08d876303ed059c9553df18b3c13c3406584a70a8f37f1a1fe2709"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:91a645e6468c4f064b7f4f3b81074bdd68fe5aa2b8c5107de15dcd85ba6141be"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5c6956808fd5cf0576de5a602243af8e04594b25b9a28675feddc71c5526410a"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:1622ca27d5a7a98f7d8f35e8b146dc7efda4a4b6241d2edf7e076bd6bcecbeb4"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a100482950a55228f648bd382bb71bfaff520002f29845274fccbbf02e28bd52"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp310-cp310-win_amd64.whl", hash = "sha256:955ca8905c0251fc4af7ce0a20999e824a25652f53a558ab548b60969f1f368e"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cf49e91dcf699b8a449944ed898ef1466b39b92720613838791a551bc8f587a"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:964c307e400c5f33fa762ba1e19853e048814fcfbd9679cc923431adb7a2ead2"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3433924e1b14074798331dc2bfae2af452ed7888067f2fc145835704d8981b15"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00879d4c6be4b3afc510073f48a5e960f797200e261ab3d9bd9b7746a08c669d"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34a6997c80f86d3dd80a4f078bb3b200079c47eeda4fd409d8899b883c90d2ac"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0106e42b481677c41caa69474fe530f786dcef88b11b70000f0e45a03534bc8f"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81efe09ba27533e35709905c3061db4dc9fb814f637360578d065e2061fbb116"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d312d6dddc18d9c164e1893706269c293cba1923118349d375962b1188dafb01"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:bfd2c734da9950f7afaad5f132088e0e1478f32f042881fca6651bb0c8d14206"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8a732610a5a6b4f06dadcf9288688a8ff202fd556d971436a123b7adb85596e2"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp311-cp311-win_amd64.whl", hash = "sha256:321814a9a3ad785855a821b842aba08ca1b7de7dfb2979a2f0492dca9ec4ae70"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4aa0ca13bb8a725bb6d12c13999217fd5bc8b86a12589f28a74b93e076fbb959"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:469424e354ebcec949aa6aa30e5a9edc352a899d9a68ad7a48f97df83cc914cf"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b04f5349313529ae1f1c42fe1aa0443faaf50fdf12d13866c2cc49683bfa53d0"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:959feabddc7fffac89b054d6f23f3b3c62d7d3c90cd414a02e3747495597f150"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e9da624a6ca4bc5f7fa1f03f8485446b5b81d5787b6beea2b4f8d9dbef878ad7"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1823221a6b96e38b15686170d4fc5b36073efcb87cce7d3da660440b50077f6"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:866db42f986298f0cf15d805225eb8df2228bf19f7997d7f1cb5f388cbfc6a0f"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:738c34657305b5973af6dbb6711b07b179dfdd21196d60039ca30a74bafe9648"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb9758473200384a04374d0e0cac6f451218ff6945a024f65a1526802c34e56e"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0e991632777e217953ac960726158987da684086dd813ac85038c595e7382c91"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp312-cp312-win_amd64.whl", hash = "sha256:1d87484dd42c8783c44a30400949efb3d81ef2487eaa7d64d1c54df90cf8b97a"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d1d1723d7449c12bb61aca7eb6e0c6ab2863cd8dc0019273cc4d4a1982f84bdb"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e538a8671005641fa195eab962f85cf0504defbd3b548c4c8fc27102a59f687b"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c50592bc8517092f40979e4a5d934f96a1737a77724bb1d121eb78b614b30fc8"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:95f16ae82bc242b76cd3c3e5156441e2bd85ff9ec3a9869d750aad443e46073c"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aebd1e98e865e9a28ce0cb2c25b7dfd752f0d1f0a423165b55cd32a431dcc0f4"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:49cd7af7d49e438a39593d1dd8cab106a1912536c2b78a4d814ebdff2786094e"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:affebd61aa3b7a8880fd4ac3ee94722940125ff83ff485e1a7c76be9adaabb38"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:d1bac282f140fa092f2bbb6c36ed82270b4a21a6fc55d4b16748ed9f55e50fdb"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1285aa54449e362b1d30d92b2dc042ad3ee80f479cc4e323448d0a0a8a1641fa"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp37-cp37m-win_amd64.whl", hash = "sha256:6cff31af8155dc9ee364098a328bab688c887c732c66b8d027e5b03818ca0287"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d9b689c4a17dd3130791dcbb8c30dbf05602f7c2d56c792e193fb49adc7bf5f8"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:017518bd2de4851adc826a224fb105411e148ad845e11355edd6786ba3dfedf5"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c35fd811f339a3cbe7f9b54b2d9a5e592e57426c6cc1051632a62c59c4810208"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38ed45ec9673709bfa5bc17f140e71dd4cca56d4e58ef7fd50d5a5043a4f55c6"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:433f1c256108f9e26f480a8cd6ddb0fb37dbc87d7f5a97e4540a9da9b881f23f"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ed61e43bf5dc8d0936daf03a19fef3168d64191dbe66483f7ad08c4cea0bc36b"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4ae8109ff9fdf1fa0cb87ab6645298693fdd2666a7f5f85660df88f6965e0bb7"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a53809ee02e3952fae7977c19b30fd828bd117b8f5edf17a3a94212feb57faaf"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9d39d5ffc151fb33bcd55b99b0e8957299c0b1b3e5a1a5f4399c1287ef0051a9"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp38-cp38-win_amd64.whl", hash = "sha256:e14bc8250000921fcccd53722f86b3b3d1b57db901e206e49e2ab2afc5919c2d"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cd88c5cea4efe614d5004fb5f5dcdea3d7d59422be796689e779e03363102d24"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:621a814e60825162d38760c66351b4df679fd422c848b7c2f86ad399bff27145"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:46e50c05952b59a214e27d3606f6d510aaa429daed898e16b8a37bfbacc81acc"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03354a9db667c27946e70162cb0042c3929154167f3678a30d23cebfe0ad55b5"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:703c2f3b79037581afec7baa2bdbcb0a1787f1758744a7662099b0eca2d721cb"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6469ebd9e93327e9f5f36dcf8692fb1e7aeaf70087c1c15d4f2c020e0be3a891"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:85bca9765c04b6be90cb46e7566ffe0faa2d7480ff5c8d5e055ac427f039fd24"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:a836610d5c75e9cff98b9fdb3559c007c785c09eaa84a60d5d10ef6f85f671e8"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ef8de7a1d9fb3518cc6b58e3c80b75a824209ad52b90c542686c912db8553dad"},
|
|
||||||
{file = "psycopg_binary-3.1.19-cp39-cp39-win_amd64.whl", hash = "sha256:76fcd33342f38e35cd6b5408f1bc117d55ab8b16e5019d99b6d3ce0356c51717"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pydantic"
|
name = "pydantic"
|
||||||
version = "2.7.1"
|
version = "2.7.1"
|
||||||
|
|
@ -1102,20 +927,6 @@ files = [
|
||||||
[package.extras]
|
[package.extras]
|
||||||
windows-terminal = ["colorama (>=0.4.6)"]
|
windows-terminal = ["colorama (>=0.4.6)"]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "python-dateutil"
|
|
||||||
version = "2.9.0.post0"
|
|
||||||
description = "Extensions to the standard Python datetime module"
|
|
||||||
optional = false
|
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
|
||||||
files = [
|
|
||||||
{file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"},
|
|
||||||
{file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
six = ">=1.5"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "python-dotenv"
|
name = "python-dotenv"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
|
@ -1131,16 +942,19 @@ files = [
|
||||||
cli = ["click (>=5.0)"]
|
cli = ["click (>=5.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytz"
|
name = "python-multipart"
|
||||||
version = "2024.1"
|
version = "0.0.9"
|
||||||
description = "World timezone definitions, modern and historical"
|
description = "A streaming multipart parser for Python"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"},
|
{file = "python_multipart-0.0.9-py3-none-any.whl", hash = "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215"},
|
||||||
{file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"},
|
{file = "python_multipart-0.0.9.tar.gz", hash = "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["atomicwrites (==1.4.1)", "attrs (==23.2.0)", "coverage (==7.4.1)", "hatch", "invoke (==2.2.0)", "more-itertools (==10.2.0)", "pbr (==6.0.0)", "pluggy (==1.4.0)", "py (==1.11.0)", "pytest (==8.0.0)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.2.0)", "pyyaml (==6.0.1)", "ruff (==0.2.1)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyyaml"
|
name = "pyyaml"
|
||||||
version = "6.0.1"
|
version = "6.0.1"
|
||||||
|
|
@ -1228,24 +1042,6 @@ docs = ["click (>=7)", "setuptools", "sphinx", "sphinx-click", "sphinx-hoverxref
|
||||||
tests = ["coverage", "flaky", "html5lib", "lxml", "mechanicalsoup", "mypy", "numpy", "pytest (>=4)", "pytest-cov", "pytest-randomly", "pytest-subtests", "requests-mock", "requests-wsgi-adapter", "types-beautifulsoup4", "types-requests"]
|
tests = ["coverage", "flaky", "html5lib", "lxml", "mechanicalsoup", "mypy", "numpy", "pytest (>=4)", "pytest-cov", "pytest-randomly", "pytest-subtests", "requests-mock", "requests-wsgi-adapter", "types-beautifulsoup4", "types-requests"]
|
||||||
unstable-plugins = ["beautifulsoup4", "blinker (>=1.4)", "mutagen", "requests", "tabulate"]
|
unstable-plugins = ["beautifulsoup4", "blinker (>=1.4)", "mutagen", "requests", "tabulate"]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "redis"
|
|
||||||
version = "5.0.4"
|
|
||||||
description = "Python client for Redis database and key-value store"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "redis-5.0.4-py3-none-any.whl", hash = "sha256:7adc2835c7a9b5033b7ad8f8918d09b7344188228809c98df07af226d39dec91"},
|
|
||||||
{file = "redis-5.0.4.tar.gz", hash = "sha256:ec31f2ed9675cc54c21ba854cfe0462e6faf1d83c8ce5944709db8a4700b9c61"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
hiredis = {version = ">=1.0.0", optional = true, markers = "extra == \"hiredis\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
hiredis = ["hiredis (>=1.0.0)"]
|
|
||||||
ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "2023.12.25"
|
version = "2023.12.25"
|
||||||
|
|
@ -1439,6 +1235,17 @@ files = [
|
||||||
{file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"},
|
{file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shellingham"
|
||||||
|
version = "1.5.4"
|
||||||
|
description = "Tool to Detect Surrounding Shell"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"},
|
||||||
|
{file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "six"
|
name = "six"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
|
|
@ -1450,6 +1257,17 @@ files = [
|
||||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sniffio"
|
||||||
|
version = "1.3.1"
|
||||||
|
description = "Sniff out which async library your code is running under"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
|
||||||
|
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "soupsieve"
|
name = "soupsieve"
|
||||||
version = "2.5"
|
version = "2.5"
|
||||||
|
|
@ -1462,19 +1280,21 @@ files = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlparse"
|
name = "starlette"
|
||||||
version = "0.5.0"
|
version = "0.37.2"
|
||||||
description = "A non-validating SQL parser."
|
description = "The little ASGI library that shines."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "sqlparse-0.5.0-py3-none-any.whl", hash = "sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663"},
|
{file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"},
|
||||||
{file = "sqlparse-0.5.0.tar.gz", hash = "sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93"},
|
{file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
anyio = ">=3.4.0,<5"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["build", "hatch"]
|
full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"]
|
||||||
doc = ["sphinx"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tqdm"
|
name = "tqdm"
|
||||||
|
|
@ -1496,6 +1316,23 @@ notebook = ["ipywidgets (>=6)"]
|
||||||
slack = ["slack-sdk"]
|
slack = ["slack-sdk"]
|
||||||
telegram = ["requests"]
|
telegram = ["requests"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typer"
|
||||||
|
version = "0.12.3"
|
||||||
|
description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "typer-0.12.3-py3-none-any.whl", hash = "sha256:070d7ca53f785acbccba8e7d28b08dcd88f79f1fbda035ade0aecec71ca5c914"},
|
||||||
|
{file = "typer-0.12.3.tar.gz", hash = "sha256:49e73131481d804288ef62598d97a1ceef3058905aa536a1134f90891ba35482"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
click = ">=8.0.0"
|
||||||
|
rich = ">=10.11.0"
|
||||||
|
shellingham = ">=1.3.0"
|
||||||
|
typing-extensions = ">=3.7.4.3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typing-extensions"
|
name = "typing-extensions"
|
||||||
version = "4.11.0"
|
version = "4.11.0"
|
||||||
|
|
@ -1508,33 +1345,92 @@ files = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tzdata"
|
name = "ujson"
|
||||||
version = "2024.1"
|
version = "5.10.0"
|
||||||
description = "Provider of IANA time zone data"
|
description = "Ultra fast JSON encoder and decoder for Python"
|
||||||
optional = false
|
|
||||||
python-versions = ">=2"
|
|
||||||
files = [
|
|
||||||
{file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"},
|
|
||||||
{file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tzlocal"
|
|
||||||
version = "5.2"
|
|
||||||
description = "tzinfo object for the local timezone"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8"},
|
{file = "ujson-5.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd"},
|
||||||
{file = "tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e"},
|
{file = "ujson-5.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf"},
|
||||||
|
{file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6"},
|
||||||
|
{file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569"},
|
||||||
|
{file = "ujson-5.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770"},
|
||||||
|
{file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1"},
|
||||||
|
{file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5"},
|
||||||
|
{file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51"},
|
||||||
|
{file = "ujson-5.10.0-cp310-cp310-win32.whl", hash = "sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518"},
|
||||||
|
{file = "ujson-5.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f"},
|
||||||
|
{file = "ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00"},
|
||||||
|
{file = "ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126"},
|
||||||
|
{file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8"},
|
||||||
|
{file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b"},
|
||||||
|
{file = "ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9"},
|
||||||
|
{file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f"},
|
||||||
|
{file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4"},
|
||||||
|
{file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1"},
|
||||||
|
{file = "ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f"},
|
||||||
|
{file = "ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720"},
|
||||||
|
{file = "ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5"},
|
||||||
|
{file = "ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e"},
|
||||||
|
{file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043"},
|
||||||
|
{file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1"},
|
||||||
|
{file = "ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3"},
|
||||||
|
{file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21"},
|
||||||
|
{file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2"},
|
||||||
|
{file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e"},
|
||||||
|
{file = "ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e"},
|
||||||
|
{file = "ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc"},
|
||||||
|
{file = "ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287"},
|
||||||
|
{file = "ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e"},
|
||||||
|
{file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557"},
|
||||||
|
{file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988"},
|
||||||
|
{file = "ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816"},
|
||||||
|
{file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20"},
|
||||||
|
{file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0"},
|
||||||
|
{file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f"},
|
||||||
|
{file = "ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165"},
|
||||||
|
{file = "ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539"},
|
||||||
|
{file = "ujson-5.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a984a3131da7f07563057db1c3020b1350a3e27a8ec46ccbfbf21e5928a43050"},
|
||||||
|
{file = "ujson-5.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73814cd1b9db6fc3270e9d8fe3b19f9f89e78ee9d71e8bd6c9a626aeaeaf16bd"},
|
||||||
|
{file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61e1591ed9376e5eddda202ec229eddc56c612b61ac6ad07f96b91460bb6c2fb"},
|
||||||
|
{file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2c75269f8205b2690db4572a4a36fe47cd1338e4368bc73a7a0e48789e2e35a"},
|
||||||
|
{file = "ujson-5.10.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7223f41e5bf1f919cd8d073e35b229295aa8e0f7b5de07ed1c8fddac63a6bc5d"},
|
||||||
|
{file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc2fd6b3067c0782e7002ac3b38cf48608ee6366ff176bbd02cf969c9c20fe"},
|
||||||
|
{file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:232cc85f8ee3c454c115455195a205074a56ff42608fd6b942aa4c378ac14dd7"},
|
||||||
|
{file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cc6139531f13148055d691e442e4bc6601f6dba1e6d521b1585d4788ab0bfad4"},
|
||||||
|
{file = "ujson-5.10.0-cp38-cp38-win32.whl", hash = "sha256:e7ce306a42b6b93ca47ac4a3b96683ca554f6d35dd8adc5acfcd55096c8dfcb8"},
|
||||||
|
{file = "ujson-5.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:e82d4bb2138ab05e18f089a83b6564fee28048771eb63cdecf4b9b549de8a2cc"},
|
||||||
|
{file = "ujson-5.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dfef2814c6b3291c3c5f10065f745a1307d86019dbd7ea50e83504950136ed5b"},
|
||||||
|
{file = "ujson-5.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4734ee0745d5928d0ba3a213647f1c4a74a2a28edc6d27b2d6d5bd9fa4319e27"},
|
||||||
|
{file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d47ebb01bd865fdea43da56254a3930a413f0c5590372a1241514abae8aa7c76"},
|
||||||
|
{file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dee5e97c2496874acbf1d3e37b521dd1f307349ed955e62d1d2f05382bc36dd5"},
|
||||||
|
{file = "ujson-5.10.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7490655a2272a2d0b072ef16b0b58ee462f4973a8f6bbe64917ce5e0a256f9c0"},
|
||||||
|
{file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba17799fcddaddf5c1f75a4ba3fd6441f6a4f1e9173f8a786b42450851bd74f1"},
|
||||||
|
{file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2aff2985cef314f21d0fecc56027505804bc78802c0121343874741650a4d3d1"},
|
||||||
|
{file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad88ac75c432674d05b61184178635d44901eb749786c8eb08c102330e6e8996"},
|
||||||
|
{file = "ujson-5.10.0-cp39-cp39-win32.whl", hash = "sha256:2544912a71da4ff8c4f7ab5606f947d7299971bdd25a45e008e467ca638d13c9"},
|
||||||
|
{file = "ujson-5.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:3ff201d62b1b177a46f113bb43ad300b424b7847f9c5d38b1b4ad8f75d4a282a"},
|
||||||
|
{file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64"},
|
||||||
|
{file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3"},
|
||||||
|
{file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a"},
|
||||||
|
{file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746"},
|
||||||
|
{file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88"},
|
||||||
|
{file = "ujson-5.10.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b"},
|
||||||
|
{file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7663960f08cd5a2bb152f5ee3992e1af7690a64c0e26d31ba7b3ff5b2ee66337"},
|
||||||
|
{file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:d8640fb4072d36b08e95a3a380ba65779d356b2fee8696afeb7794cf0902d0a1"},
|
||||||
|
{file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78778a3aa7aafb11e7ddca4e29f46bc5139131037ad628cc10936764282d6753"},
|
||||||
|
{file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0111b27f2d5c820e7f2dbad7d48e3338c824e7ac4d2a12da3dc6061cc39c8e6"},
|
||||||
|
{file = "ujson-5.10.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c66962ca7565605b355a9ed478292da628b8f18c0f2793021ca4425abf8b01e5"},
|
||||||
|
{file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4"},
|
||||||
|
{file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8"},
|
||||||
|
{file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b"},
|
||||||
|
{file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804"},
|
||||||
|
{file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e"},
|
||||||
|
{file = "ujson-5.10.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7"},
|
||||||
|
{file = "ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
tzdata = {version = "*", markers = "platform_system == \"Windows\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "urllib3"
|
name = "urllib3"
|
||||||
version = "2.2.1"
|
version = "2.2.1"
|
||||||
|
|
@ -1552,6 +1448,75 @@ h2 = ["h2 (>=4,<5)"]
|
||||||
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||||
zstd = ["zstandard (>=0.18.0)"]
|
zstd = ["zstandard (>=0.18.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uvicorn"
|
||||||
|
version = "0.29.0"
|
||||||
|
description = "The lightning-fast ASGI server."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "uvicorn-0.29.0-py3-none-any.whl", hash = "sha256:2c2aac7ff4f4365c206fd773a39bf4ebd1047c238f8b8268ad996829323473de"},
|
||||||
|
{file = "uvicorn-0.29.0.tar.gz", hash = "sha256:6a69214c0b6a087462412670b3ef21224fa48cae0e452b5883e8e8bdfdd11dd0"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
click = ">=7.0"
|
||||||
|
colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""}
|
||||||
|
h11 = ">=0.8"
|
||||||
|
httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""}
|
||||||
|
python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""}
|
||||||
|
pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""}
|
||||||
|
uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""}
|
||||||
|
watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""}
|
||||||
|
websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""}
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uvloop"
|
||||||
|
version = "0.19.0"
|
||||||
|
description = "Fast implementation of asyncio event loop on top of libuv"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8.0"
|
||||||
|
files = [
|
||||||
|
{file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"},
|
||||||
|
{file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428"},
|
||||||
|
{file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8"},
|
||||||
|
{file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849"},
|
||||||
|
{file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957"},
|
||||||
|
{file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd"},
|
||||||
|
{file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef"},
|
||||||
|
{file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2"},
|
||||||
|
{file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1"},
|
||||||
|
{file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24"},
|
||||||
|
{file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533"},
|
||||||
|
{file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12"},
|
||||||
|
{file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650"},
|
||||||
|
{file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec"},
|
||||||
|
{file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc"},
|
||||||
|
{file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6"},
|
||||||
|
{file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593"},
|
||||||
|
{file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3"},
|
||||||
|
{file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd"},
|
||||||
|
{file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd"},
|
||||||
|
{file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be"},
|
||||||
|
{file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797"},
|
||||||
|
{file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d"},
|
||||||
|
{file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7"},
|
||||||
|
{file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b"},
|
||||||
|
{file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67"},
|
||||||
|
{file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7"},
|
||||||
|
{file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256"},
|
||||||
|
{file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17"},
|
||||||
|
{file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5"},
|
||||||
|
{file = "uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"]
|
||||||
|
test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtualenv"
|
name = "virtualenv"
|
||||||
version = "20.26.2"
|
version = "20.26.2"
|
||||||
|
|
@ -1572,6 +1537,174 @@ platformdirs = ">=3.9.1,<5"
|
||||||
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
|
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
|
||||||
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
|
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "watchfiles"
|
||||||
|
version = "0.21.0"
|
||||||
|
description = "Simple, modern and high performance file watching and code reload in python."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "watchfiles-0.21.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:27b4035013f1ea49c6c0b42d983133b136637a527e48c132d368eb19bf1ac6aa"},
|
||||||
|
{file = "watchfiles-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c81818595eff6e92535ff32825f31c116f867f64ff8cdf6562cd1d6b2e1e8f3e"},
|
||||||
|
{file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c107ea3cf2bd07199d66f156e3ea756d1b84dfd43b542b2d870b77868c98c03"},
|
||||||
|
{file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d9ac347653ebd95839a7c607608703b20bc07e577e870d824fa4801bc1cb124"},
|
||||||
|
{file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5eb86c6acb498208e7663ca22dbe68ca2cf42ab5bf1c776670a50919a56e64ab"},
|
||||||
|
{file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f564bf68404144ea6b87a78a3f910cc8de216c6b12a4cf0b27718bf4ec38d303"},
|
||||||
|
{file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d0f32ebfaa9c6011f8454994f86108c2eb9c79b8b7de00b36d558cadcedaa3d"},
|
||||||
|
{file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d45d9b699ecbac6c7bd8e0a2609767491540403610962968d258fd6405c17c"},
|
||||||
|
{file = "watchfiles-0.21.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:aff06b2cac3ef4616e26ba17a9c250c1fe9dd8a5d907d0193f84c499b1b6e6a9"},
|
||||||
|
{file = "watchfiles-0.21.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d9792dff410f266051025ecfaa927078b94cc7478954b06796a9756ccc7e14a9"},
|
||||||
|
{file = "watchfiles-0.21.0-cp310-none-win32.whl", hash = "sha256:214cee7f9e09150d4fb42e24919a1e74d8c9b8a9306ed1474ecaddcd5479c293"},
|
||||||
|
{file = "watchfiles-0.21.0-cp310-none-win_amd64.whl", hash = "sha256:1ad7247d79f9f55bb25ab1778fd47f32d70cf36053941f07de0b7c4e96b5d235"},
|
||||||
|
{file = "watchfiles-0.21.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:668c265d90de8ae914f860d3eeb164534ba2e836811f91fecc7050416ee70aa7"},
|
||||||
|
{file = "watchfiles-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a23092a992e61c3a6a70f350a56db7197242f3490da9c87b500f389b2d01eef"},
|
||||||
|
{file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e7941bbcfdded9c26b0bf720cb7e6fd803d95a55d2c14b4bd1f6a2772230c586"},
|
||||||
|
{file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11cd0c3100e2233e9c53106265da31d574355c288e15259c0d40a4405cbae317"},
|
||||||
|
{file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78f30cbe8b2ce770160d3c08cff01b2ae9306fe66ce899b73f0409dc1846c1b"},
|
||||||
|
{file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6674b00b9756b0af620aa2a3346b01f8e2a3dc729d25617e1b89cf6af4a54eb1"},
|
||||||
|
{file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd7ac678b92b29ba630d8c842d8ad6c555abda1b9ef044d6cc092dacbfc9719d"},
|
||||||
|
{file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c873345680c1b87f1e09e0eaf8cf6c891b9851d8b4d3645e7efe2ec20a20cc7"},
|
||||||
|
{file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:49f56e6ecc2503e7dbe233fa328b2be1a7797d31548e7a193237dcdf1ad0eee0"},
|
||||||
|
{file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:02d91cbac553a3ad141db016e3350b03184deaafeba09b9d6439826ee594b365"},
|
||||||
|
{file = "watchfiles-0.21.0-cp311-none-win32.whl", hash = "sha256:ebe684d7d26239e23d102a2bad2a358dedf18e462e8808778703427d1f584400"},
|
||||||
|
{file = "watchfiles-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:4566006aa44cb0d21b8ab53baf4b9c667a0ed23efe4aaad8c227bfba0bf15cbe"},
|
||||||
|
{file = "watchfiles-0.21.0-cp311-none-win_arm64.whl", hash = "sha256:c550a56bf209a3d987d5a975cdf2063b3389a5d16caf29db4bdddeae49f22078"},
|
||||||
|
{file = "watchfiles-0.21.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:51ddac60b96a42c15d24fbdc7a4bfcd02b5a29c047b7f8bf63d3f6f5a860949a"},
|
||||||
|
{file = "watchfiles-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:511f0b034120cd1989932bf1e9081aa9fb00f1f949fbd2d9cab6264916ae89b1"},
|
||||||
|
{file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cfb92d49dbb95ec7a07511bc9efb0faff8fe24ef3805662b8d6808ba8409a71a"},
|
||||||
|
{file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f92944efc564867bbf841c823c8b71bb0be75e06b8ce45c084b46411475a915"},
|
||||||
|
{file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:642d66b75eda909fd1112d35c53816d59789a4b38c141a96d62f50a3ef9b3360"},
|
||||||
|
{file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d23bcd6c8eaa6324fe109d8cac01b41fe9a54b8c498af9ce464c1aeeb99903d6"},
|
||||||
|
{file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18d5b4da8cf3e41895b34e8c37d13c9ed294954907929aacd95153508d5d89d7"},
|
||||||
|
{file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b8d1eae0f65441963d805f766c7e9cd092f91e0c600c820c764a4ff71a0764c"},
|
||||||
|
{file = "watchfiles-0.21.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1fd9a5205139f3c6bb60d11f6072e0552f0a20b712c85f43d42342d162be1235"},
|
||||||
|
{file = "watchfiles-0.21.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a1e3014a625bcf107fbf38eece0e47fa0190e52e45dc6eee5a8265ddc6dc5ea7"},
|
||||||
|
{file = "watchfiles-0.21.0-cp312-none-win32.whl", hash = "sha256:9d09869f2c5a6f2d9df50ce3064b3391d3ecb6dced708ad64467b9e4f2c9bef3"},
|
||||||
|
{file = "watchfiles-0.21.0-cp312-none-win_amd64.whl", hash = "sha256:18722b50783b5e30a18a8a5db3006bab146d2b705c92eb9a94f78c72beb94094"},
|
||||||
|
{file = "watchfiles-0.21.0-cp312-none-win_arm64.whl", hash = "sha256:a3b9bec9579a15fb3ca2d9878deae789df72f2b0fdaf90ad49ee389cad5edab6"},
|
||||||
|
{file = "watchfiles-0.21.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:4ea10a29aa5de67de02256a28d1bf53d21322295cb00bd2d57fcd19b850ebd99"},
|
||||||
|
{file = "watchfiles-0.21.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:40bca549fdc929b470dd1dbfcb47b3295cb46a6d2c90e50588b0a1b3bd98f429"},
|
||||||
|
{file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9b37a7ba223b2f26122c148bb8d09a9ff312afca998c48c725ff5a0a632145f7"},
|
||||||
|
{file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec8c8900dc5c83650a63dd48c4d1d245343f904c4b64b48798c67a3767d7e165"},
|
||||||
|
{file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ad3fe0a3567c2f0f629d800409cd528cb6251da12e81a1f765e5c5345fd0137"},
|
||||||
|
{file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d353c4cfda586db2a176ce42c88f2fc31ec25e50212650c89fdd0f560ee507b"},
|
||||||
|
{file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83a696da8922314ff2aec02987eefb03784f473281d740bf9170181829133765"},
|
||||||
|
{file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a03651352fc20975ee2a707cd2d74a386cd303cc688f407296064ad1e6d1562"},
|
||||||
|
{file = "watchfiles-0.21.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3ad692bc7792be8c32918c699638b660c0de078a6cbe464c46e1340dadb94c19"},
|
||||||
|
{file = "watchfiles-0.21.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06247538e8253975bdb328e7683f8515ff5ff041f43be6c40bff62d989b7d0b0"},
|
||||||
|
{file = "watchfiles-0.21.0-cp38-none-win32.whl", hash = "sha256:9a0aa47f94ea9a0b39dd30850b0adf2e1cd32a8b4f9c7aa443d852aacf9ca214"},
|
||||||
|
{file = "watchfiles-0.21.0-cp38-none-win_amd64.whl", hash = "sha256:8d5f400326840934e3507701f9f7269247f7c026d1b6cfd49477d2be0933cfca"},
|
||||||
|
{file = "watchfiles-0.21.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7f762a1a85a12cc3484f77eee7be87b10f8c50b0b787bb02f4e357403cad0c0e"},
|
||||||
|
{file = "watchfiles-0.21.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6e9be3ef84e2bb9710f3f777accce25556f4a71e15d2b73223788d528fcc2052"},
|
||||||
|
{file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4c48a10d17571d1275701e14a601e36959ffada3add8cdbc9e5061a6e3579a5d"},
|
||||||
|
{file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c889025f59884423428c261f212e04d438de865beda0b1e1babab85ef4c0f01"},
|
||||||
|
{file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:66fac0c238ab9a2e72d026b5fb91cb902c146202bbd29a9a1a44e8db7b710b6f"},
|
||||||
|
{file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4a21f71885aa2744719459951819e7bf5a906a6448a6b2bbce8e9cc9f2c8128"},
|
||||||
|
{file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c9198c989f47898b2c22201756f73249de3748e0fc9de44adaf54a8b259cc0c"},
|
||||||
|
{file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f57c4461cd24fda22493109c45b3980863c58a25b8bec885ca8bea6b8d4b28"},
|
||||||
|
{file = "watchfiles-0.21.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:853853cbf7bf9408b404754b92512ebe3e3a83587503d766d23e6bf83d092ee6"},
|
||||||
|
{file = "watchfiles-0.21.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d5b1dc0e708fad9f92c296ab2f948af403bf201db8fb2eb4c8179db143732e49"},
|
||||||
|
{file = "watchfiles-0.21.0-cp39-none-win32.whl", hash = "sha256:59137c0c6826bd56c710d1d2bda81553b5e6b7c84d5a676747d80caf0409ad94"},
|
||||||
|
{file = "watchfiles-0.21.0-cp39-none-win_amd64.whl", hash = "sha256:6cb8fdc044909e2078c248986f2fc76f911f72b51ea4a4fbbf472e01d14faa58"},
|
||||||
|
{file = "watchfiles-0.21.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ab03a90b305d2588e8352168e8c5a1520b721d2d367f31e9332c4235b30b8994"},
|
||||||
|
{file = "watchfiles-0.21.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:927c589500f9f41e370b0125c12ac9e7d3a2fd166b89e9ee2828b3dda20bfe6f"},
|
||||||
|
{file = "watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd467213195e76f838caf2c28cd65e58302d0254e636e7c0fca81efa4a2e62c"},
|
||||||
|
{file = "watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02b73130687bc3f6bb79d8a170959042eb56eb3a42df3671c79b428cd73f17cc"},
|
||||||
|
{file = "watchfiles-0.21.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:08dca260e85ffae975448e344834d765983237ad6dc308231aa16e7933db763e"},
|
||||||
|
{file = "watchfiles-0.21.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:3ccceb50c611c433145502735e0370877cced72a6c70fd2410238bcbc7fe51d8"},
|
||||||
|
{file = "watchfiles-0.21.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57d430f5fb63fea141ab71ca9c064e80de3a20b427ca2febcbfcef70ff0ce895"},
|
||||||
|
{file = "watchfiles-0.21.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dd5fad9b9c0dd89904bbdea978ce89a2b692a7ee8a0ce19b940e538c88a809c"},
|
||||||
|
{file = "watchfiles-0.21.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:be6dd5d52b73018b21adc1c5d28ac0c68184a64769052dfeb0c5d9998e7f56a2"},
|
||||||
|
{file = "watchfiles-0.21.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b3cab0e06143768499384a8a5efb9c4dc53e19382952859e4802f294214f36ec"},
|
||||||
|
{file = "watchfiles-0.21.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6ed10c2497e5fedadf61e465b3ca12a19f96004c15dcffe4bd442ebadc2d85"},
|
||||||
|
{file = "watchfiles-0.21.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43babacef21c519bc6631c5fce2a61eccdfc011b4bcb9047255e9620732c8097"},
|
||||||
|
{file = "watchfiles-0.21.0.tar.gz", hash = "sha256:c76c635fabf542bb78524905718c39f736a98e5ab25b23ec6d4abede1a85a6a3"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
anyio = ">=3.0.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "websockets"
|
||||||
|
version = "12.0"
|
||||||
|
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"},
|
||||||
|
{file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"},
|
||||||
|
{file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"},
|
||||||
|
{file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"},
|
||||||
|
{file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"},
|
||||||
|
{file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"},
|
||||||
|
{file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"},
|
||||||
|
{file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"},
|
||||||
|
{file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"},
|
||||||
|
{file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"},
|
||||||
|
{file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"},
|
||||||
|
{file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"},
|
||||||
|
{file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"},
|
||||||
|
{file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"},
|
||||||
|
{file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"},
|
||||||
|
{file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"},
|
||||||
|
{file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"},
|
||||||
|
{file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"},
|
||||||
|
{file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"},
|
||||||
|
{file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"},
|
||||||
|
{file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"},
|
||||||
|
{file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"},
|
||||||
|
{file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"},
|
||||||
|
{file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"},
|
||||||
|
{file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"},
|
||||||
|
{file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"},
|
||||||
|
{file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"},
|
||||||
|
{file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"},
|
||||||
|
{file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"},
|
||||||
|
{file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"},
|
||||||
|
{file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"},
|
||||||
|
{file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"},
|
||||||
|
{file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"},
|
||||||
|
{file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"},
|
||||||
|
{file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"},
|
||||||
|
{file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"},
|
||||||
|
{file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"},
|
||||||
|
{file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"},
|
||||||
|
{file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"},
|
||||||
|
{file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"},
|
||||||
|
{file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"},
|
||||||
|
{file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"},
|
||||||
|
{file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"},
|
||||||
|
{file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"},
|
||||||
|
{file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"},
|
||||||
|
{file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"},
|
||||||
|
{file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"},
|
||||||
|
{file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"},
|
||||||
|
{file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"},
|
||||||
|
{file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"},
|
||||||
|
{file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"},
|
||||||
|
{file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"},
|
||||||
|
{file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"},
|
||||||
|
{file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"},
|
||||||
|
{file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"},
|
||||||
|
{file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"},
|
||||||
|
{file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"},
|
||||||
|
{file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"},
|
||||||
|
{file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"},
|
||||||
|
{file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"},
|
||||||
|
{file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"},
|
||||||
|
{file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"},
|
||||||
|
{file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"},
|
||||||
|
{file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"},
|
||||||
|
{file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"},
|
||||||
|
{file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"},
|
||||||
|
{file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"},
|
||||||
|
{file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"},
|
||||||
|
{file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"},
|
||||||
|
{file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"},
|
||||||
|
{file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"},
|
||||||
|
{file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "werkzeug"
|
name = "werkzeug"
|
||||||
version = "3.0.3"
|
version = "3.0.3"
|
||||||
|
|
@ -1589,24 +1722,7 @@ MarkupSafe = ">=2.1.1"
|
||||||
[package.extras]
|
[package.extras]
|
||||||
watchdog = ["watchdog (>=2.3)"]
|
watchdog = ["watchdog (>=2.3)"]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "whitenoise"
|
|
||||||
version = "6.6.0"
|
|
||||||
description = "Radically simplified static file serving for WSGI applications"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "whitenoise-6.6.0-py3-none-any.whl", hash = "sha256:b1f9db9bf67dc183484d760b99f4080185633136a273a03f6436034a41064146"},
|
|
||||||
{file = "whitenoise-6.6.0.tar.gz", hash = "sha256:8998f7370973447fac1e8ef6e8ded2c5209a7b1f67c1012866dbcd09681c3251"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
Brotli = {version = "*", optional = true, markers = "extra == \"brotli\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
brotli = ["Brotli"]
|
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.12"
|
python-versions = "^3.12"
|
||||||
content-hash = "7e636d161791c07443e9ed457317703ac8cd0f52a2de870ff7aa869e877640eb"
|
content-hash = "1306d3bb68f23a7887a7cb506ea7095ab0d66a779b0ccfaf36ab886b552cd186"
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,18 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "feedvault"
|
name = "feedvault"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "FeedVault is a Django app for archiving RSS feeds."
|
description = "RSS Archive"
|
||||||
authors = ["Joakim Hellsén <tlovinator@gmail.com>"]
|
authors = ["Joakim Hellsén <tlovinator@gmail.com>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.12"
|
python = "^3.12"
|
||||||
django = "^5.0.6"
|
|
||||||
python-dotenv = "^1.0.1"
|
python-dotenv = "^1.0.1"
|
||||||
gunicorn = "^21.2.0"
|
|
||||||
dateparser = "^1.2.0"
|
|
||||||
django-ninja = "^1.1.0"
|
|
||||||
django-debug-toolbar = "^4.3.0"
|
|
||||||
whitenoise = { extras = ["brotli"], version = "^6.6.0" }
|
|
||||||
rich = "^13.7.1"
|
|
||||||
django-htmx = "^1.17.3"
|
|
||||||
django-redis = {extras = ["hiredis"], version = "^5.4.0"}
|
|
||||||
psycopg = {extras = ["binary"], version = "^3.1.19"} # TODO: Use psycopg[c] in Dockerfile
|
|
||||||
reader = "^3.12"
|
reader = "^3.12"
|
||||||
|
fastapi = "^0.111.0"
|
||||||
|
jinja2 = "^3.1.4"
|
||||||
|
python-multipart = "^0.0.9"
|
||||||
|
humanize = "^4.9.0"
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
ruff = "^0.3.0"
|
ruff = "^0.3.0"
|
||||||
|
|
@ -30,44 +24,24 @@ build-backend = "poetry.core.masonry.api"
|
||||||
requires = ["poetry-core"]
|
requires = ["poetry-core"]
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
exclude = ["migrations"]
|
|
||||||
fix = true
|
fix = true
|
||||||
unsafe-fixes = true
|
unsafe-fixes = true
|
||||||
preview = true
|
preview = true
|
||||||
line-length = 120
|
line-length = 120
|
||||||
lint.select = ["ALL"]
|
lint.select = ["ALL"]
|
||||||
lint.ignore = [
|
lint.ignore = [
|
||||||
"ARG001", # Checks for the presence of unused arguments in function definitions.
|
"ANN201", # Checks that public functions and methods have return type annotations.
|
||||||
"ARG002", # Checks for the presence of unused arguments in instance method definitions.
|
"ARG001", # Checks for the presence of unused arguments in function definitions.
|
||||||
"COM812", # Checks for the absence of trailing commas.
|
"B008", # Checks for function calls in default function arguments.
|
||||||
"CPY001", # Missing copyright notice at top of file
|
"D100", # Checks for undocumented public module definitions.
|
||||||
"D100", # Checks for undocumented public module definitions.
|
"CPY001", # Checks for the absence of copyright notices within Python files.
|
||||||
"D101", # Checks for undocumented public class definitions.
|
"D104", # Checks for undocumented public package definitions.
|
||||||
"D102", # Checks for undocumented public method definitions.
|
"FIX002", # Checks for "TODO" comments.
|
||||||
"D104", # Missing docstring in public package.
|
|
||||||
"D105", # Missing docstring in magic method.
|
|
||||||
"D106", # Checks for undocumented public class definitions, for nested classes.
|
|
||||||
"D402", # Checks for function docstrings that include the function's signature in the summary line.
|
|
||||||
"DJ001", # Checks nullable string-based fields (like CharField and TextField) in Django models.
|
|
||||||
"ERA001", # Found commented-out code
|
|
||||||
"FIX002", # Line contains TODO
|
|
||||||
"ISC001", # Checks for implicitly concatenated strings on a single line.
|
|
||||||
"PLR6301", # Checks for the presence of unused self parameter in methods definitions.
|
|
||||||
"TD003", # Checks that a TODO comment is associated with a link to a relevant issue or ticket.
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.ruff.lint.pydocstyle]
|
[tool.ruff.lint.pydocstyle]
|
||||||
convention = "google"
|
convention = "google"
|
||||||
|
|
||||||
[tool.ruff.lint.per-file-ignores]
|
|
||||||
"**/tests.py" = [
|
|
||||||
"S101", # Allow asserts
|
|
||||||
"ARG", # Allow unused arguments
|
|
||||||
"FBT", # Don't care about booleans as positional arguments in tests, e.g. via @pytest.mark.parametrize()
|
|
||||||
"PLR2004", # Allow "assert response.status_code == 200" when testing views
|
|
||||||
"D102", # Allow missing docstrings in tests
|
|
||||||
"PLR6301", # Checks for the presence of unused self parameter in methods definitions.
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.djlint]
|
[tool.djlint]
|
||||||
|
profile = "jinja"
|
||||||
format_attribute_template_tags = true
|
format_attribute_template_tags = true
|
||||||
|
|
|
||||||
BIN
static/favicon.ico
Normal file
BIN
static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
|
|
@ -1,4 +1,3 @@
|
||||||
{% load static %}
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
|
@ -8,8 +7,7 @@
|
||||||
{% if keywords %}<meta name="keywords" content="{{ keywords }}" />{% endif %}
|
{% if keywords %}<meta name="keywords" content="{{ keywords }}" />{% endif %}
|
||||||
{% if author %}<meta name="author" content="{{ author }}" />{% endif %}
|
{% if author %}<meta name="author" content="{{ author }}" />{% endif %}
|
||||||
{% if canonical %}<link rel="canonical" href="{{ canonical }}" />{% endif %}
|
{% if canonical %}<link rel="canonical" href="{{ canonical }}" />{% endif %}
|
||||||
<title>{{ title|default:"FeedVault" }}</title>
|
<title>{{ title | default("FeedVault") }}</title>
|
||||||
<script src="{% static 'htmx.min.js' %}" defer></script>
|
|
||||||
<style>
|
<style>
|
||||||
html {
|
html {
|
||||||
max-width: 88ch;
|
max-width: 88ch;
|
||||||
|
|
@ -84,19 +82,18 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<span class="title">
|
<span class="title">
|
||||||
<h1>
|
<h1>
|
||||||
<a href="{% url 'feeds:index' %}">FeedVault</a>
|
<a href='{{ url_for("index") }}'>FeedVault</a>
|
||||||
</h1>
|
</h1>
|
||||||
</span>
|
</span>
|
||||||
<div class="leftright">
|
<div class="leftright">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<small>Archive of
|
<small>Archive of
|
||||||
<a href="https://en.wikipedia.org/wiki/Web_feed">web feeds</a>.
|
<a href="https://en.wikipedia.org/wiki/Web_feed">web feeds</a>.
|
||||||
{% if amount_of_feeds %}{{ amount_of_feeds }} feeds.{% endif %}
|
{{ stats }}
|
||||||
{% if db_size %}~{{ db_size }}.{% endif %}
|
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<form action="{% url 'feeds:search' %}" method="get">
|
<form action='{{ url_for("search") }}' method="get" class="search">
|
||||||
<input type="text" name="q" placeholder="Search" />
|
<input type="text" name="q" placeholder="Search" />
|
||||||
<button type="submit">Search</button>
|
<button type="submit">Search</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -106,15 +103,14 @@
|
||||||
<small>
|
<small>
|
||||||
<div class="leftright">
|
<div class="leftright">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<a href="{% url 'feeds:index' %}">Home</a> |
|
<a href='{{ url_for("index") }}'>Home</a> |
|
||||||
<a href="{% url 'feeds:feeds' %}">Feeds</a> |
|
<a href='{{ url_for("feeds") }}'>Feeds</a> |
|
||||||
<a href="{% url 'feeds:upload' %}">Upload</a>
|
<a href='{{ url_for("upload_files") }}'>Upload</a> |
|
||||||
|
<a href='{{ url_for("contact") }}'>Contact</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<a href="https://github.com/TheLovinator1/FeedVault">GitHub</a> |
|
<a href="https://github.com/TheLovinator1/FeedVault">GitHub</a> |
|
||||||
<a href="https://github.com/sponsors/TheLovinator1">Donate</a>
|
<a href="https://github.com/sponsors/TheLovinator1">Donate</a>
|
||||||
{% if not user.is_authenticated %}| <a href="">Login</a>{% endif %}
|
|
||||||
{% if user.is_authenticated %}| <a href="">{{ user.username }}</a>{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</small>
|
</small>
|
||||||
|
|
@ -127,9 +123,7 @@
|
||||||
<footer>
|
<footer>
|
||||||
<small>
|
<small>
|
||||||
<div class="leftright">
|
<div class="leftright">
|
||||||
<div class="left">
|
<div class="left">Web scraping is not a crime.</div>
|
||||||
<a href="">Privacy Policy</a> | <a href="">Terms of Service</a>
|
|
||||||
</div>
|
|
||||||
<div class="right">No rights reserved.</div>
|
<div class="right">No rights reserved.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="leftright">
|
<div class="leftright">
|
||||||
|
|
|
||||||
34
templates/contact.html
Normal file
34
templates/contact.html
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<h2>Contact</h2>
|
||||||
|
<p>
|
||||||
|
If you have any questions, suggestions, or feedback, feel free to contact me. I am always happy to help.
|
||||||
|
<br>
|
||||||
|
You can contact me through the following methods:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="https://github.com/TheLovinator1/FeedVault.se/issues">GitHub issues</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="mailto:tlovinator@gmail.com">tlovinator@gmail.com</a>
|
||||||
|
</li>
|
||||||
|
<li>TheLovinator#9276 on Discord</li>
|
||||||
|
<li>Use the form below to send me a message</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
<h3>Send a message</h3>
|
||||||
|
<form method="post" action='{{ url_for("contact") }}'>
|
||||||
|
<p>
|
||||||
|
<label for="message">Message</label>
|
||||||
|
<textarea id="message"
|
||||||
|
name="message"
|
||||||
|
rows="4"
|
||||||
|
cols="50"
|
||||||
|
required
|
||||||
|
placeholder="Enter your message"></textarea>
|
||||||
|
</p>
|
||||||
|
<button type="submit">Send message</button>
|
||||||
|
</form>
|
||||||
|
{% endblock content %}
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
{% for entry in entries %}
|
{% for entry in entries %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ entry.link }}">{{ entry.title }}</a>
|
<a href="{{ entry.link }}">{{ entry.title }}</a>
|
||||||
<p>{{ entry.summary|safe }}</p>
|
<p>{{ entry.summary | safe }}</p>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endblock %}
|
{% endblock content %}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
<ul>
|
<ul>
|
||||||
{% for feed in feeds %}
|
{% for feed in feeds %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'feeds:feed' feed.id %}">{{ feed.url }}</a>
|
<a href="{{ url_for('feed', feed_url=feed.url) }}">{{ feed.url }}</a>
|
||||||
<p>{{ feed.description }}</p>
|
<p>{{ feed.description }}</p>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endblock %}
|
{% endblock content %}
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,36 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Welcome, archivist!</h2>
|
<h2>Welcome, archivist!</h2>
|
||||||
|
<h3>Latest Feeds</h3>
|
||||||
|
<ul>
|
||||||
|
{% if not feeds %}<p>No feeds found.</p>{% endif %}
|
||||||
|
{% for feed in feeds %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ url_for('feed', feed_url=feed.url) }}">{{ feed.url }}</a>
|
||||||
|
<p>{{ feed.description }}</p>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
<h3>FAQ</h3>
|
||||||
|
<summary>What are web feeds?</summary>
|
||||||
<p>
|
<p>
|
||||||
Input the URLs of the feeds you wish to archive below. You can add as many as needed, and access them through the website or API. Alternatively, include links to .opml files, and the feeds within will be archived.
|
Web feeds are a way to distribute content on the web. They allow users to access updates from websites without having to visit them directly. Feeds are typically used for news websites, blogs, and other sites that frequently update content.
|
||||||
|
<br>
|
||||||
|
You can read more about web feeds on <a href="https://en.wikipedia.org/wiki/Web_feed">Wikipedia</a>.
|
||||||
</p>
|
</p>
|
||||||
<form action="{% url 'feeds:add' %}" method='post'>
|
<hr>
|
||||||
{% csrf_token %}
|
<summary>What is FeedVault?</summary>
|
||||||
<textarea id="urls" name="urls" rows="5" cols="50" required></textarea>
|
<p>
|
||||||
<button type="submit">Add feeds</button>
|
FeedVault is a service that archives web feeds. It allows users to access and search for historical content from various websites. The service is designed to preserve the history of the web and provide a reliable source for accessing content that may no longer be available on the original websites.
|
||||||
</form>
|
</p>
|
||||||
<h2>FAQ</h2>
|
<hr>
|
||||||
<details>
|
<summary>Why archive feeds?</summary>
|
||||||
<summary>What are web feeds?</summary>
|
<p>
|
||||||
<p>
|
Web feeds are a valuable source of information, and archiving them ensures that the content is preserved for future reference. By archiving feeds, we can ensure that historical content is available for research, analysis, and other purposes. Additionally, archiving feeds can help prevent the loss of valuable information due to website changes, outages, or other issues.
|
||||||
Web feeds are a way to distribute content on the web. They allow users to access updates from websites without having to visit them directly. Feeds are typically used for news websites, blogs, and other sites that frequently update content.
|
</p>
|
||||||
<br>
|
<hr>
|
||||||
You can read more about web feeds on <a href="https://en.wikipedia.org/wiki/Web_feed">Wikipedia</a>.
|
<summary>How can I access the archived feeds?</summary>
|
||||||
</p>
|
<p>
|
||||||
<hr>
|
You can access the archived feeds through the website or API. The website provides a user interface for searching and browsing the feeds, while the API allows you to access the feeds programmatically. You can also download the feeds in various formats, such as JSON, XML, or RSS.
|
||||||
</details>
|
</p>
|
||||||
<details>
|
{% endblock content %}
|
||||||
<summary>What is FeedVault?</summary>
|
|
||||||
<p>
|
|
||||||
FeedVault is a service that archives web It allows users to access and search for historical content from various websites. The service is designed to preserve the history of the web and provide a reliable source for accessing content that may no longer be available on the original websites.
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>Why archive feeds?</summary>
|
|
||||||
<p>
|
|
||||||
Web feeds are a valuable source of information, and archiving them ensures that the content is preserved for future reference. By archiving feeds, we can ensure that historical content is available for research, analysis, and other purposes. Additionally, archiving feeds can help prevent the loss of valuable information due to website changes, outages, or other issues.
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>How can I access the archived feeds?</summary>
|
|
||||||
<p>
|
|
||||||
You can access the archived feeds through the website or API. The website provides a user interface for searching and browsing the feeds, while the API allows you to access the feeds programmatically. You can also download the feeds in various formats, such as JSON, XML, or RSS.
|
|
||||||
</p>
|
|
||||||
</details>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>
|
<h2>
|
||||||
Searched for:
|
Searched for:
|
||||||
"{{ query|default:"Search" }}"
|
"{{ query }}"
|
||||||
</h2>
|
</h2>
|
||||||
{% if feeds %}
|
{% if entries %}
|
||||||
{% for feed in feeds %}
|
{% for entry in entries %}
|
||||||
<a href="{% url 'feeds:feed' feed.id %}">{{ feed.url|default:"Unknown Feed" }} →</a>
|
<a href="{{ url_for('feed', feed_url=entry.feed_url) }}">{{ entry.feed_url }} →</a>
|
||||||
<br>
|
<br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>No results found.</p>
|
<p>No entries found.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock content %}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,47 @@
|
||||||
<h2>Upload</h2>
|
{% extends "base.html" %}
|
||||||
<p>
|
{% block content %}
|
||||||
You can also upload files containing the feeds you wish to archive.
|
<h2>Upload</h2>
|
||||||
Currently supported file formats: .opml, .xml, .json.
|
|
||||||
Your file will be parsed in the future if not currently supported.
|
|
||||||
Feel free to upload databases, backups, or any other files containing feeds.
|
|
||||||
</p>
|
|
||||||
<form enctype="multipart/form-data"
|
|
||||||
method="post"
|
|
||||||
action="{% url 'feeds:upload' %}">
|
|
||||||
{% csrf_token %}
|
|
||||||
<p>
|
<p>
|
||||||
<label for="file">Choose a file to upload</label>
|
You can upload files to the archive here.
|
||||||
<br>
|
<br>
|
||||||
|
Things you can upload include:
|
||||||
|
<ul>
|
||||||
|
<li>Lists of URLs</li>
|
||||||
|
<li>Databases</li>
|
||||||
|
<li>Backups</li>
|
||||||
|
<li>Archives</li>
|
||||||
|
<li>Anything else that is relevant</li>
|
||||||
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
<input type="file" name="file" id="file" required>
|
Uploaded files will be manually reviewed and indexed. If you have any questions, feel free to <a href='{{ url_for("contact") }}''>contact me</a>.
|
||||||
<br>
|
<br>
|
||||||
<br>
|
You can also provide a description for the file you are uploading.
|
||||||
<label for="description">Description (optional)</label>
|
|
||||||
<input type="text"
|
|
||||||
name="description"
|
|
||||||
id="description"
|
|
||||||
size="80"
|
|
||||||
placeholder="Description (optional)">
|
|
||||||
</p>
|
</p>
|
||||||
<button type="submit">Upload file</button>
|
<form enctype="multipart/form-data"
|
||||||
</form>
|
method="post"
|
||||||
|
action='{{ url_for("upload_files") }}'>
|
||||||
|
<p>
|
||||||
|
<input type="file" name="files" required multiple>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<label for="description">Description (optional)</label>
|
||||||
|
<textarea id="description"
|
||||||
|
name="description"
|
||||||
|
rows="4"
|
||||||
|
cols="50"
|
||||||
|
placeholder="Enter a description for the file"></textarea>
|
||||||
|
</p>
|
||||||
|
<input type="checkbox" id="public" name="public">
|
||||||
|
<label for="public">Public</label>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<small>
|
||||||
|
Public files will be listed on FeedVault for everyone to see and download.
|
||||||
|
<br>
|
||||||
|
Private files will only be used for indexing feeds.
|
||||||
|
</small>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<button type="submit">Upload file</button>
|
||||||
|
</form>
|
||||||
|
{% endblock content %}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue