Add empty Go project
This commit is contained in:
parent
b4c66ecf3c
commit
3445466197
30 changed files with 19 additions and 4183 deletions
14
.github/workflows/ruff.yml
vendored
14
.github/workflows/ruff.yml
vendored
|
|
@ -1,14 +0,0 @@
|
||||||
name: Ruff
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 0 * * *" # Run every day
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ruff:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: chartboost/ruff-action@v1
|
|
||||||
167
.gitignore
vendored
167
.gitignore
vendored
|
|
@ -1,159 +1,22 @@
|
||||||
# Byte-compiled / optimized / DLL files
|
# Binaries for programs and plugins
|
||||||
__pycache__/
|
*.exe
|
||||||
*.py[cod]
|
*.exe~
|
||||||
*$py.class
|
*.dll
|
||||||
|
|
||||||
# C extensions
|
|
||||||
*.so
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
# Distribution / packaging
|
# Test binary, built with `go test -c`
|
||||||
.Python
|
*.test
|
||||||
build/
|
|
||||||
develop-eggs/
|
|
||||||
dist/
|
|
||||||
downloads/
|
|
||||||
eggs/
|
|
||||||
.eggs/
|
|
||||||
lib/
|
|
||||||
lib64/
|
|
||||||
parts/
|
|
||||||
sdist/
|
|
||||||
var/
|
|
||||||
wheels/
|
|
||||||
share/python-wheels/
|
|
||||||
*.egg-info/
|
|
||||||
.installed.cfg
|
|
||||||
*.egg
|
|
||||||
MANIFEST
|
|
||||||
|
|
||||||
# PyInstaller
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
# Usually these files are written by a python script from a template
|
*.out
|
||||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
||||||
*.manifest
|
|
||||||
*.spec
|
|
||||||
|
|
||||||
# Installer logs
|
# Dependency directories
|
||||||
pip-log.txt
|
vendor/
|
||||||
pip-delete-this-directory.txt
|
|
||||||
|
|
||||||
# Unit test / coverage reports
|
# Go workspace file
|
||||||
htmlcov/
|
go.work
|
||||||
.tox/
|
tmp/
|
||||||
.nox/
|
|
||||||
.coverage
|
|
||||||
.coverage.*
|
|
||||||
.cache
|
|
||||||
nosetests.xml
|
|
||||||
coverage.xml
|
|
||||||
*.cover
|
|
||||||
*.py,cover
|
|
||||||
.hypothesis/
|
|
||||||
.pytest_cache/
|
|
||||||
cover/
|
|
||||||
|
|
||||||
# Translations
|
# Environment variables file
|
||||||
*.mo
|
|
||||||
*.pot
|
|
||||||
|
|
||||||
# Django stuff:
|
|
||||||
*.log
|
|
||||||
local_settings.py
|
|
||||||
db.sqlite3
|
|
||||||
db.sqlite3-journal
|
|
||||||
|
|
||||||
# Flask stuff:
|
|
||||||
instance/
|
|
||||||
.webassets-cache
|
|
||||||
|
|
||||||
# Scrapy stuff:
|
|
||||||
.scrapy
|
|
||||||
|
|
||||||
# Sphinx documentation
|
|
||||||
docs/_build/
|
|
||||||
|
|
||||||
# PyBuilder
|
|
||||||
.pybuilder/
|
|
||||||
target/
|
|
||||||
|
|
||||||
# Jupyter Notebook
|
|
||||||
.ipynb_checkpoints
|
|
||||||
|
|
||||||
# IPython
|
|
||||||
profile_default/
|
|
||||||
ipython_config.py
|
|
||||||
|
|
||||||
# pyenv
|
|
||||||
# For a library or package, you might want to ignore these files since the code is
|
|
||||||
# intended to run in multiple environments; otherwise, check them in:
|
|
||||||
# .python-version
|
|
||||||
|
|
||||||
# pipenv
|
|
||||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
||||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
||||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
||||||
# install all needed dependencies.
|
|
||||||
#Pipfile.lock
|
|
||||||
|
|
||||||
# poetry
|
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
||||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
||||||
# commonly ignored for libraries.
|
|
||||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
||||||
#poetry.lock
|
|
||||||
|
|
||||||
# pdm
|
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
||||||
#pdm.lock
|
|
||||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
||||||
# in version control.
|
|
||||||
# https://pdm.fming.dev/#use-with-ide
|
|
||||||
.pdm.toml
|
|
||||||
|
|
||||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
||||||
__pypackages__/
|
|
||||||
|
|
||||||
# Celery stuff
|
|
||||||
celerybeat-schedule
|
|
||||||
celerybeat.pid
|
|
||||||
|
|
||||||
# SageMath parsed files
|
|
||||||
*.sage.py
|
|
||||||
|
|
||||||
# Environments
|
|
||||||
.env
|
.env
|
||||||
.venv
|
|
||||||
env/
|
|
||||||
venv/
|
|
||||||
ENV/
|
|
||||||
env.bak/
|
|
||||||
venv.bak/
|
|
||||||
|
|
||||||
# Spyder project settings
|
|
||||||
.spyderproject
|
|
||||||
.spyproject
|
|
||||||
|
|
||||||
# Rope project settings
|
|
||||||
.ropeproject
|
|
||||||
|
|
||||||
# mkdocs documentation
|
|
||||||
/site
|
|
||||||
|
|
||||||
# mypy
|
|
||||||
.mypy_cache/
|
|
||||||
.dmypy.json
|
|
||||||
dmypy.json
|
|
||||||
|
|
||||||
# Pyre type checker
|
|
||||||
.pyre/
|
|
||||||
|
|
||||||
# pytype static type analyzer
|
|
||||||
.pytype/
|
|
||||||
|
|
||||||
# Cython debug symbols
|
|
||||||
cython_debug/
|
|
||||||
|
|
||||||
# PyCharm
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
# Static files
|
|
||||||
staticfiles/
|
|
||||||
|
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
default_language_version:
|
|
||||||
python: python3.12
|
|
||||||
repos:
|
|
||||||
# Apply a consistent format to pyproject.toml files.
|
|
||||||
# https://pyproject-fmt.readthedocs.io/en/latest/
|
|
||||||
- repo: https://github.com/tox-dev/pyproject-fmt
|
|
||||||
rev: "1.6.0"
|
|
||||||
hooks:
|
|
||||||
- id: pyproject-fmt
|
|
||||||
|
|
||||||
# Automatically add trailing commas to calls and literals.
|
|
||||||
- repo: https://github.com/asottile/add-trailing-comma
|
|
||||||
rev: v3.1.0
|
|
||||||
hooks:
|
|
||||||
- id: add-trailing-comma
|
|
||||||
|
|
||||||
# Some out-of-the-box hooks for pre-commit.
|
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
||||||
rev: v4.5.0
|
|
||||||
hooks:
|
|
||||||
- id: check-ast
|
|
||||||
- id: check-builtin-literals
|
|
||||||
- id: check-docstring-first
|
|
||||||
- id: check-executables-have-shebangs
|
|
||||||
- id: check-merge-conflict
|
|
||||||
- id: check-toml
|
|
||||||
- id: check-vcs-permalinks
|
|
||||||
- id: end-of-file-fixer
|
|
||||||
- id: mixed-line-ending
|
|
||||||
- id: name-tests-test
|
|
||||||
args: [--pytest-test-first]
|
|
||||||
- id: trailing-whitespace
|
|
||||||
args: [--markdown-linebreak-ext=md]
|
|
||||||
exclude_types:
|
|
||||||
- "html"
|
|
||||||
|
|
||||||
# Automatically upgrade your Django project code
|
|
||||||
- repo: https://github.com/adamchainz/django-upgrade
|
|
||||||
rev: "1.15.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.
|
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
|
||||||
rev: v3.15.0
|
|
||||||
hooks:
|
|
||||||
- id: pyupgrade
|
|
||||||
args: ["--py312-plus"]
|
|
||||||
|
|
||||||
# An extremely fast Python linter and formatter.
|
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
||||||
rev: v0.1.13
|
|
||||||
hooks:
|
|
||||||
- id: ruff-format
|
|
||||||
- id: ruff
|
|
||||||
args: ["--fix", "--exit-non-zero-on-fix"]
|
|
||||||
|
|
||||||
# Static checker for GitHub Actions workflow files.
|
|
||||||
- repo: https://github.com/rhysd/actionlint
|
|
||||||
rev: v1.6.26
|
|
||||||
hooks:
|
|
||||||
- id: actionlint
|
|
||||||
|
|
||||||
# Optimize .png files.
|
|
||||||
- repo: https://github.com/shssoichiro/oxipng
|
|
||||||
rev: v9.0.0
|
|
||||||
hooks:
|
|
||||||
- id: oxipng
|
|
||||||
64
Dockerfile
64
Dockerfile
|
|
@ -1,64 +0,0 @@
|
||||||
# Stage 1: Build the requirements.txt using Poetry
|
|
||||||
FROM python:3.12-slim AS builder
|
|
||||||
|
|
||||||
# Set environment variables for Python
|
|
||||||
ENV PYTHONDONTWRITEBYTECODE 1
|
|
||||||
ENV PYTHONUNBUFFERED 1
|
|
||||||
ENV PATH="${PATH}:/root/.local/bin"
|
|
||||||
|
|
||||||
# Install system dependencies
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y --no-install-recommends \
|
|
||||||
curl \
|
|
||||||
git \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Install Poetry
|
|
||||||
RUN curl -sSL https://install.python-poetry.org | python3 -
|
|
||||||
|
|
||||||
# Copy only the poetry.lock/pyproject.toml to leverage Docker cache
|
|
||||||
WORKDIR /app
|
|
||||||
COPY pyproject.toml poetry.lock /app/
|
|
||||||
|
|
||||||
# Install dependencies and create requirements.txt
|
|
||||||
RUN poetry self add poetry-plugin-export && poetry export --format=requirements.txt --output=requirements.txt --only=main --without-hashes
|
|
||||||
|
|
||||||
# Stage 2: Install dependencies and run the Django application
|
|
||||||
FROM python:3.12-slim AS runner
|
|
||||||
|
|
||||||
# Set environment variables for Python
|
|
||||||
ENV PYTHONDONTWRITEBYTECODE 1
|
|
||||||
ENV PYTHONUNBUFFERED 1
|
|
||||||
|
|
||||||
# Create a non-root user
|
|
||||||
RUN useradd -ms /bin/bash appuser
|
|
||||||
|
|
||||||
# Install system dependencies
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y --no-install-recommends \
|
|
||||||
libpq-dev \
|
|
||||||
git \
|
|
||||||
netcat-openbsd \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Copy the generated requirements.txt from the builder stage
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=builder /app/requirements.txt /app/
|
|
||||||
|
|
||||||
# Install application dependencies
|
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
|
||||||
|
|
||||||
# Copy the rest of the application code
|
|
||||||
COPY . /app/
|
|
||||||
|
|
||||||
# Change ownership of the application directory to the non-root user
|
|
||||||
RUN chown -R appuser:appuser /app
|
|
||||||
|
|
||||||
# Switch to the non-root user
|
|
||||||
USER appuser
|
|
||||||
|
|
||||||
# The port the application will listen on
|
|
||||||
EXPOSE 8000
|
|
||||||
|
|
||||||
# Run startup script
|
|
||||||
CMD ["./docker-entrypoint.sh"]
|
|
||||||
51
README.md
51
README.md
|
|
@ -2,9 +2,7 @@
|
||||||
|
|
||||||
_A seed vault for your feeds._
|
_A seed vault for your feeds._
|
||||||
|
|
||||||
FeedVault is an open-source web application written in Python that allows users to easily archive RSS, Atom, and JSON feeds.
|
FeedVault is an open-source web application written in Golang that allows users to archive and search their favorite RSS, Atom, and JSON feeds. With FeedVault, users can effortlessly add their favorite feeds, ensuring they have a centralized location for accessing and preserving valuable content.
|
||||||
|
|
||||||
With FeedVault, users can effortlessly add their favorite feeds, ensuring they have a centralized location for accessing and preserving valuable content.
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|
@ -18,53 +16,6 @@ _Note: Some features are currently in development._
|
||||||
- **User-Friendly Design**: FeedVault is designed to be simple, intuitive, and responsive, working seamlessly on both desktop and mobile devices.
|
- **User-Friendly Design**: FeedVault is designed to be simple, intuitive, and responsive, working seamlessly on both desktop and mobile devices.
|
||||||
- **Privacy-Focused**: FeedVault respects user privacy by not tracking or collecting any personal data. It is an ad-free platform that prioritizes user security.
|
- **Privacy-Focused**: FeedVault respects user privacy by not tracking or collecting any personal data. It is an ad-free platform that prioritizes user security.
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
|
|
||||||
#### Development
|
|
||||||
|
|
||||||
Ensure you have the following installed on your machine if you plan to run FeedVault locally for development purposes:
|
|
||||||
|
|
||||||
- [Python 3.12](https://www.python.org/downloads/)
|
|
||||||
- [Poetry](https://python-poetry.org/docs/master/#installation)
|
|
||||||
- [PostgreSQL](https://www.postgresql.org/download/)
|
|
||||||
|
|
||||||
#### Production
|
|
||||||
|
|
||||||
Ensure you have the following installed on your machine if you plan to run FeedVault locally for production purposes:
|
|
||||||
|
|
||||||
- [Docker](https://docs.docker.com/get-docker/)
|
|
||||||
- [PostgreSQL](https://www.postgresql.org/download/)
|
|
||||||
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
Clone the repository:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/TheLovinator1/FeedVault.git
|
|
||||||
```
|
|
||||||
|
|
||||||
Navigate to the project directory:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd FeedVault
|
|
||||||
```
|
|
||||||
|
|
||||||
Install the project dependencies:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
poetry install
|
|
||||||
```
|
|
||||||
|
|
||||||
Run the project:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
poetry run site
|
|
||||||
```
|
|
||||||
|
|
||||||
Access FeedVault in your browser at http://localhost:8080.
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
- Visit the FeedVault website.
|
- Visit the FeedVault website.
|
||||||
|
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
services:
|
|
||||||
# Postgres - Database
|
|
||||||
feedvault_postgres:
|
|
||||||
container_name: feedvault_postgres
|
|
||||||
image: postgres:16
|
|
||||||
user: "1000:1000"
|
|
||||||
ports:
|
|
||||||
- 5434:5432 # Host:Container
|
|
||||||
restart: always
|
|
||||||
environment:
|
|
||||||
- POSTGRES_USER=${PGUSER}
|
|
||||||
- POSTGRES_PASSWORD=${PGPASSWORD}
|
|
||||||
- POSTGRES_DB=${PGDATABASE}
|
|
||||||
volumes:
|
|
||||||
- /mnt/Fourteen/Docker/FeedVault/Postgres:/var/lib/postgresql/data
|
|
||||||
networks:
|
|
||||||
- db
|
|
||||||
redis:
|
|
||||||
container_name: feedvault_redis
|
|
||||||
image: redis:7
|
|
||||||
restart: always
|
|
||||||
user: "1000:1000"
|
|
||||||
ports:
|
|
||||||
- 6380:6379 # Host:Container
|
|
||||||
environment:
|
|
||||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
|
||||||
command: /bin/sh -c 'redis-server --requirepass ${REDIS_PASSWORD} --appendonly yes --maxmemory 4gb --maxmemory-policy allkeys-lru'
|
|
||||||
networks:
|
|
||||||
- redis
|
|
||||||
volumes:
|
|
||||||
- /mnt/Fourteen/Docker/FeedVault/Redis:/data
|
|
||||||
|
|
||||||
networks:
|
|
||||||
db:
|
|
||||||
driver: bridge
|
|
||||||
redis:
|
|
||||||
driver: bridge
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Exit on error
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Print commands and their arguments as they are executed.
|
|
||||||
set -x
|
|
||||||
|
|
||||||
# Wait for database
|
|
||||||
echo "Waiting for database"
|
|
||||||
while ! nc -z "$PGHOST" "$PGPORT"; do
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
echo "Database started"
|
|
||||||
|
|
||||||
# Django entrypoint script
|
|
||||||
# 1. Collect static files
|
|
||||||
echo "Collect static files"
|
|
||||||
python manage.py collectstatic --noinput
|
|
||||||
echo "Collect static files done"
|
|
||||||
|
|
||||||
# 2. Apply database migrations
|
|
||||||
echo "Apply database migrations"
|
|
||||||
python manage.py migrate
|
|
||||||
echo "Apply database migrations done"
|
|
||||||
|
|
||||||
# https://docs.gunicorn.org/en/stable/design.html#how-many-workers
|
|
||||||
num_cores=$(nproc --all)
|
|
||||||
workers=$((2 * num_cores + 1))
|
|
||||||
|
|
||||||
# 3. Start server
|
|
||||||
echo "Starting server with $workers workers"
|
|
||||||
gunicorn --workers=$workers --bind=0.0.0.0:8000 feedvault.wsgi:application --log-level=info --access-logfile=- --error-logfile=- --forwarded-allow-ips="172.*,192.*" --proxy-allow-from="172.*,192.*"
|
|
||||||
echo "Bye, love you"
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
"""This package contains the main Django app.
|
|
||||||
|
|
||||||
https://docs.djangoproject.com/en/5.0/ref/applications/
|
|
||||||
"""
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
"""Admin interface for feeds app.
|
|
||||||
|
|
||||||
https://docs.djangoproject.com/en/5.0/ref/contrib/admin/
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, ClassVar
|
|
||||||
|
|
||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
from feeds.models import (
|
|
||||||
Author,
|
|
||||||
Blocklist,
|
|
||||||
Cloud,
|
|
||||||
Contributor,
|
|
||||||
Feed,
|
|
||||||
Generator,
|
|
||||||
Image,
|
|
||||||
Info,
|
|
||||||
Link,
|
|
||||||
Publisher,
|
|
||||||
Rights,
|
|
||||||
Subtitle,
|
|
||||||
Tags,
|
|
||||||
TextInput,
|
|
||||||
Title,
|
|
||||||
)
|
|
||||||
from feeds.validator import update_blocklist
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.models.query import QuerySet
|
|
||||||
from django.http import HttpRequest
|
|
||||||
|
|
||||||
admin.site.register(Author)
|
|
||||||
admin.site.register(Cloud)
|
|
||||||
admin.site.register(Contributor)
|
|
||||||
admin.site.register(Feed)
|
|
||||||
admin.site.register(Generator)
|
|
||||||
admin.site.register(Image)
|
|
||||||
admin.site.register(Info)
|
|
||||||
admin.site.register(Link)
|
|
||||||
admin.site.register(Publisher)
|
|
||||||
admin.site.register(Rights)
|
|
||||||
admin.site.register(Subtitle)
|
|
||||||
admin.site.register(Tags)
|
|
||||||
admin.site.register(TextInput)
|
|
||||||
admin.site.register(Title)
|
|
||||||
|
|
||||||
|
|
||||||
# Add button to update blocklist on the admin page
|
|
||||||
@admin.register(Blocklist)
|
|
||||||
class BlocklistAdmin(admin.ModelAdmin):
|
|
||||||
"""Admin interface for blocklist."""
|
|
||||||
|
|
||||||
actions: ClassVar[list[str]] = ["_update_blocklist", "delete_all_blocklist"]
|
|
||||||
list_display: ClassVar[list[str]] = ["url", "active"]
|
|
||||||
|
|
||||||
@admin.action(description="Update blocklist")
|
|
||||||
def _update_blocklist(self: admin.ModelAdmin, request: HttpRequest, queryset: QuerySet) -> None: # noqa: ARG002
|
|
||||||
"""Update blocklist."""
|
|
||||||
msg: str = update_blocklist()
|
|
||||||
self.message_user(request=request, message=msg)
|
|
||||||
|
|
||||||
@admin.action(description="Delete all blocklists")
|
|
||||||
def delete_all_blocklist(self: admin.ModelAdmin, request: HttpRequest, queryset: QuerySet) -> None: # noqa: ARG002
|
|
||||||
"""Delete all blocklist from database."""
|
|
||||||
Blocklist.objects.all().delete()
|
|
||||||
self.message_user(request=request, message="Deleted all blocklists")
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
"""Django application configuration for the main feeds app."""
|
|
||||||
|
|
||||||
from typing import Literal
|
|
||||||
|
|
||||||
from django.apps import AppConfig
|
|
||||||
|
|
||||||
|
|
||||||
class FeedsConfig(AppConfig):
|
|
||||||
"""Configuration object for the main feeds app.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
AppConfig: The base configuration object for Django applications.
|
|
||||||
"""
|
|
||||||
|
|
||||||
default_auto_field: Literal["django.db.models.BigAutoField"] = "django.db.models.BigAutoField"
|
|
||||||
name: Literal["feeds"] = "feeds"
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
"""https://docs.djangoproject.com/en/5.0/topics/forms/."""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from django import forms
|
|
||||||
|
|
||||||
|
|
||||||
class UploadOPMLForm(forms.Form):
|
|
||||||
"""Upload OPML.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
forms: A collection of Fields, plus their associated data.
|
|
||||||
"""
|
|
||||||
|
|
||||||
file = forms.FileField(
|
|
||||||
label="Select an OPML file",
|
|
||||||
help_text="max. 100 megabytes",
|
|
||||||
widget=forms.FileInput(attrs={"accept": ".opml"}),
|
|
||||||
)
|
|
||||||
|
|
@ -1,279 +0,0 @@
|
||||||
# Generated by Django 5.0.1 on 2024-01-30 01:03
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Author',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_at', models.DateTimeField(auto_now=True)),
|
|
||||||
('name', models.TextField(blank=True, help_text='The name of the feed author.')),
|
|
||||||
('email', models.EmailField(blank=True, help_text='The email address of the feed author.', max_length=254)),
|
|
||||||
('href', models.URLField(blank=True, help_text="The URL of the feed author. This can be the author's home page, or a contact page with a webmail form.")),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed author',
|
|
||||||
'verbose_name_plural': 'Feed authors',
|
|
||||||
'db_table_comment': 'Details about the author of a feed.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Cloud',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_at', models.DateTimeField(auto_now=True)),
|
|
||||||
('domain', models.CharField(blank=True, help_text='The domain of the cloud. Should be just the domain name, not including the http:// protocol. All clouds are presumed to operate over HTTP. The cloud specification does not support secure clouds over HTTPS, nor can clouds operate over other protocols.', max_length=255)),
|
|
||||||
('port', models.CharField(blank=True, help_text='The port of the cloud. Should be an integer, but Universal Feed Parser currently returns it as a string.', max_length=255)),
|
|
||||||
('path', models.CharField(blank=True, help_text='The URL path of the cloud.', max_length=255)),
|
|
||||||
('register_procedure', models.CharField(blank=True, help_text='The name of the procedure to call on the cloud.', max_length=255)),
|
|
||||||
('protocol', models.CharField(blank=True, help_text='The protocol of the cloud. Documentation differs on what the acceptable values are. Acceptable values definitely include xml-rpc and soap, although only in lowercase, despite both being acronyms. There is no way for a publisher to specify the version number of the protocol to use. soap refers to SOAP 1.1; the cloud interface does not support SOAP 1.0 or 1.2. post or http-post might also be acceptable values; nobody really knows for sure.', max_length=255)),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed cloud',
|
|
||||||
'verbose_name_plural': 'Feed clouds',
|
|
||||||
'db_table_comment': 'No one really knows what a cloud is.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Contributor',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_at', models.DateTimeField(auto_now=True)),
|
|
||||||
('name', models.TextField(blank=True, help_text='The name of this contributor.')),
|
|
||||||
('email', models.EmailField(blank=True, help_text='The email address of this contributor.', max_length=254)),
|
|
||||||
('href', models.URLField(blank=True, help_text="The URL of this contributor. This can be the contributor's home page, or a contact page with a webmail form.")),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed contributor',
|
|
||||||
'verbose_name_plural': 'Feed contributors',
|
|
||||||
'db_table_comment': 'Details about the contributor to a feed.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Generator',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_at', models.DateTimeField(auto_now=True)),
|
|
||||||
('name', models.TextField(blank=True, help_text='Human-readable name of the application used to generate the feed.')),
|
|
||||||
('href', models.URLField(blank=True, help_text='The URL of the application used to generate the feed.')),
|
|
||||||
('version', models.CharField(blank=True, help_text='The version number of the application used to generate the feed. There is no required format for this, but most applications use a MAJOR.MINOR version number.', max_length=255)),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed generator',
|
|
||||||
'verbose_name_plural': 'Feed generators',
|
|
||||||
'db_table_comment': 'Details about the software used to generate the feed.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Image',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_at', models.DateTimeField(auto_now=True)),
|
|
||||||
('title', models.TextField(blank=True, help_text='The alternate text of the feed image, which would go in the alt attribute if you rendered the feed image as an HTML img element.')),
|
|
||||||
('href', models.URLField(blank=True, help_text='The URL of the feed image itself, which would go in the src attribute if you rendered the feed image as an HTML img element.')),
|
|
||||||
('link', models.URLField(blank=True, help_text='The URL which the feed image would point to. If you rendered the feed image as an HTML img element, you would wrap it in an a element and put this in the href attribute.')),
|
|
||||||
('width', models.IntegerField(default=0, help_text='The width of the feed image, which would go in the width attribute if you rendered the feed image as an HTML img element.')),
|
|
||||||
('height', models.IntegerField(default=0, help_text='The height of the feed image, which would go in the height attribute if you rendered the feed image as an HTML img element.')),
|
|
||||||
('description', models.TextField(blank=True, help_text='A short description of the feed image, which would go in the title attribute if you rendered the feed image as an HTML img element. This element is rare; it was available in Netscape RSS 0.91 but was dropped from Userland RSS 0.91.')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed image',
|
|
||||||
'verbose_name_plural': 'Feed images',
|
|
||||||
'db_table_comment': 'A feed image can be a logo, banner, or a picture of the author.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Info',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_at', models.DateTimeField(auto_now=True)),
|
|
||||||
('value', models.TextField(blank=True, help_text='Free-form human-readable description of the feed format itself. Intended for people who view the feed in a browser, to explain what they just clicked on.')),
|
|
||||||
('info_type', models.CharField(blank=True, help_text='The content type of the feed info. Most likely text/plain, text/html, or application/xhtml+xml.', max_length=255)),
|
|
||||||
('language', models.CharField(blank=True, help_text='The language of the feed info.', max_length=255)),
|
|
||||||
('base', models.URLField(blank=True, help_text='The original base URI for links within the feed copyright.')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed information',
|
|
||||||
'verbose_name_plural': 'Feed information',
|
|
||||||
'db_table_comment': 'Details about the feed.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Link',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('rel', models.CharField(blank=True, help_text='The relationship of this feed link.', max_length=255)),
|
|
||||||
('link_type', models.CharField(blank=True, help_text='The content type of the page that this feed link points to.', max_length=255)),
|
|
||||||
('href', models.URLField(blank=True, help_text='The URL of the page that this feed link points to.')),
|
|
||||||
('title', models.TextField(blank=True, help_text='The title of this feed link.')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed link',
|
|
||||||
'verbose_name_plural': 'Feed links',
|
|
||||||
'db_table_comment': 'A list of dictionaries with details on the links associated with the feed.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Publisher',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_at', models.DateTimeField(auto_now=True)),
|
|
||||||
('name', models.TextField(blank=True, help_text="The name of this feed's publisher.")),
|
|
||||||
('email', models.EmailField(blank=True, help_text="The email address of this feed's publisher.", max_length=254)),
|
|
||||||
('href', models.URLField(blank=True, help_text="The URL of this feed's publisher. This can be the publisher's home page, or a contact page with a webmail form.")),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed publisher',
|
|
||||||
'verbose_name_plural': 'Feed publishers',
|
|
||||||
'db_table_comment': 'Details about the publisher of a feed.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Rights',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_at', models.DateTimeField(auto_now=True)),
|
|
||||||
('value', models.TextField(blank=True, help_text='A human-readable copyright statement for the feed.')),
|
|
||||||
('rights_type', models.CharField(blank=True, help_text='The content type of the feed copyright. Most likely text/plain, text/html, or application/xhtml+xml.', max_length=255)),
|
|
||||||
('language', models.CharField(blank=True, help_text='The language of the feed rights.', max_length=255)),
|
|
||||||
('base', models.URLField(blank=True, help_text='The original base URI for links within the feed copyright.')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed rights',
|
|
||||||
'verbose_name_plural': 'Feed rights',
|
|
||||||
'db_table_comment': 'Details about the rights of a feed.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Subtitle',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('value', models.TextField(blank=True, help_text='A subtitle, tagline, slogan, or other short description of the feed.')),
|
|
||||||
('subtitle_type', models.CharField(blank=True, help_text='The content type of the feed subtitle. Most likely text/plain, text/html, or application/xhtml+xml.', max_length=255)),
|
|
||||||
('language', models.CharField(blank=True, help_text='The language of the feed subtitle.', max_length=255)),
|
|
||||||
('base', models.URLField(blank=True, help_text='The original base URI for links within the feed subtitle.')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed subtitle',
|
|
||||||
'verbose_name_plural': 'Feed subtitles',
|
|
||||||
'db_table_comment': 'A subtitle, tagline, slogan, or other short description of the feed.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Tags',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('term', models.TextField(blank=True, help_text='The category term (keyword).')),
|
|
||||||
('scheme', models.CharField(blank=True, help_text='The category scheme (domain).', max_length=255)),
|
|
||||||
('label', models.TextField(blank=True, help_text='A human-readable label for the category.')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed tag',
|
|
||||||
'verbose_name_plural': 'Feed tags',
|
|
||||||
'db_table_comment': 'A list of tags associated with the feed.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='TextInput',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('title', models.TextField(blank=True, help_text="The title of the text input form, which would go in the value attribute of the form's submit button.")),
|
|
||||||
('link', models.URLField(blank=True, help_text='The link of the script which processes the text input form, which would go in the action attribute of the form.')),
|
|
||||||
('name', models.TextField(blank=True, help_text="The name of the text input box in the form, which would go in the name attribute of the form's input box.")),
|
|
||||||
('description', models.TextField(blank=True, help_text='A short description of the text input form, which would go in the label element of the form.')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed text input',
|
|
||||||
'verbose_name_plural': 'Feed text inputs',
|
|
||||||
'db_table_comment': 'A text input form. No one actually uses this. Why are you?',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Title',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('value', models.TextField(blank=True, help_text='The title of the feed.')),
|
|
||||||
('title_type', models.CharField(blank=True, help_text='The content type of the feed title. Most likely text/plain, text/html, or application/xhtml+xml.', max_length=255)),
|
|
||||||
('language', models.CharField(blank=True, help_text='The language of the feed title.', max_length=255)),
|
|
||||||
('base', models.URLField(blank=True, help_text='The original base URI for links within the feed title.')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed title',
|
|
||||||
'verbose_name_plural': 'Feed titles',
|
|
||||||
'db_table_comment': 'Details about the title of a feed.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
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 feed URL.', unique=True)),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_at', models.DateTimeField(auto_now=True)),
|
|
||||||
('error', models.BooleanField(default=False)),
|
|
||||||
('error_message', models.TextField(default='')),
|
|
||||||
('error_at', models.DateTimeField(null=True)),
|
|
||||||
('bozo', models.BooleanField(default=False, help_text='Is the feed well-formed XML?')),
|
|
||||||
('bozo_exception', models.TextField(default='', help_text='The exception raised when attempting to parse a non-well-formed feed.')),
|
|
||||||
('encoding', models.CharField(default='', help_text='The character encoding that was used to parse the feed.', max_length=255)),
|
|
||||||
('etag', models.CharField(default='', help_text='The ETag of the feed, as specified in the HTTP headers.', max_length=255)),
|
|
||||||
('headers', models.TextField(default='', help_text='HTTP headers received from the web server when retrieving the feed.')),
|
|
||||||
('href', models.URLField(default='', help_text='The final URL of the feed that was parsed. If the feed was redirected from the original requested address, href will contain the final (redirected) address.')),
|
|
||||||
('last_modified', models.DateTimeField(help_text='The last-modified date of the feed, as specified in the HTTP headers.', null=True)),
|
|
||||||
('namespaces', models.TextField(default='', help_text='A dictionary of all XML namespaces defined in the feed, as {prefix: namespaceURI}.')),
|
|
||||||
('http_status_code', models.IntegerField(default=0, help_text='The HTTP status code that was returned by the web server when the feed was fetched.')),
|
|
||||||
('version', models.CharField(choices=[('atom', 'Atom (unknown or unrecognized version)'), ('atom01', 'Atom 0.1'), ('atom02', 'Atom 0.2'), ('atom03', 'Atom 0.3'), ('atom10', 'Atom 1.0'), ('cdf', 'CDF'), ('rss', 'RSS (unknown or unrecognized version)'), ('rss090', 'RSS 0.90'), ('rss091n', 'Netscape RSS 0.91'), ('rss091u', 'Userland RSS 0.91'), ('rss092', 'RSS 0.92'), ('rss093', 'RSS 0.93'), ('rss094', 'RSS 0.94 (no accurate specification is known to exist)'), ('rss10', 'RSS 1.0'), ('rss20', 'RSS 2.0')], default='', help_text='The version of the feed, as determined by Universal Feed Parser.', max_length=255)),
|
|
||||||
('feed_data', models.TextField(default='', help_text='A dictionary of data about the feed.')),
|
|
||||||
('docs', models.URLField(blank=True, help_text='A URL pointing to the specification which this feed conforms to.')),
|
|
||||||
('error_reports_to', models.EmailField(blank=True, help_text='An email address for reporting errors in the feed itself.', max_length=254)),
|
|
||||||
('feed_id', models.CharField(blank=True, help_text='A globally unique identifier for this feed.', max_length=255)),
|
|
||||||
('language', models.CharField(blank=True, help_text='The primary language of the feed.', max_length=255)),
|
|
||||||
('license', models.URLField(blank=True, help_text='A URL pointing to the license of the feed.')),
|
|
||||||
('logo', models.URLField(blank=True, help_text='A URL to a graphic representing a logo for the feed.')),
|
|
||||||
('published', models.CharField(blank=True, help_text='The date the feed was published, as a string in the same format as it was published in the original feed.', max_length=255)),
|
|
||||||
('published_parsed', models.DateTimeField(help_text='The date the feed was published.', null=True)),
|
|
||||||
('ttl', models.CharField(blank=True, help_text='According to the RSS specification, “None"', max_length=255)),
|
|
||||||
('updated', models.CharField(blank=True, help_text='The date the feed was last updated, as a string in the same format as it was published in the original feed.', max_length=255)),
|
|
||||||
('updated_parsed', models.DateTimeField(help_text='The date the feed was last updated.', null=True)),
|
|
||||||
('author', models.ForeignKey(help_text='The author of the feed.', null=True, on_delete=django.db.models.deletion.CASCADE, to='feeds.author')),
|
|
||||||
('cloud', models.ForeignKey(help_text='Cloud enables realtime push notifications or distributed publish/subscribe communication for feeds.', null=True, on_delete=django.db.models.deletion.CASCADE, to='feeds.cloud')),
|
|
||||||
('contributors', models.ManyToManyField(help_text='A list of contributors (secondary authors) to this feed.', to='feeds.contributor')),
|
|
||||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
|
|
||||||
('generator', models.ForeignKey(help_text='Details about the software used to generate the feed.', null=True, on_delete=django.db.models.deletion.CASCADE, to='feeds.generator')),
|
|
||||||
('image', models.ForeignKey(help_text='A feed image can be a logo, banner, or a picture of the author.', null=True, on_delete=django.db.models.deletion.CASCADE, to='feeds.image')),
|
|
||||||
('info', models.ForeignKey(help_text='Details about the feed.', null=True, on_delete=django.db.models.deletion.CASCADE, to='feeds.info')),
|
|
||||||
('link', models.ForeignKey(help_text='A list of dictionaries with details on the links associated with the feed.', null=True, on_delete=django.db.models.deletion.CASCADE, to='feeds.link')),
|
|
||||||
('publisher', models.ForeignKey(help_text='The publisher of the feed.', null=True, on_delete=django.db.models.deletion.CASCADE, to='feeds.publisher')),
|
|
||||||
('rights', models.ForeignKey(help_text='Details about the rights of a feed.', null=True, on_delete=django.db.models.deletion.CASCADE, to='feeds.rights')),
|
|
||||||
('subtitle', models.ForeignKey(help_text='A subtitle, tagline, slogan, or other short description of the feed.', null=True, on_delete=django.db.models.deletion.CASCADE, to='feeds.subtitle')),
|
|
||||||
('tags', models.ManyToManyField(help_text='A list of tags associated with the feed.', to='feeds.tags')),
|
|
||||||
('text_input', models.ForeignKey(help_text='A text input form. No one actually uses this. Why are you?', null=True, on_delete=django.db.models.deletion.CASCADE, to='feeds.textinput')),
|
|
||||||
('title', models.ForeignKey(help_text='Details about the title of a feed.', null=True, on_delete=django.db.models.deletion.CASCADE, to='feeds.title')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Feed',
|
|
||||||
'verbose_name_plural': 'Feeds',
|
|
||||||
'db_table_comment': 'A feed. This is the main model of the app.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
# Generated by Django 5.0.1 on 2024-01-30 16:41
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('feeds', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Blocklist',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('url', models.URLField(help_text='The URL to block.', unique=True)),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Blocklist',
|
|
||||||
'verbose_name_plural': 'Blocklists',
|
|
||||||
'db_table_comment': 'A list of URLs to block.',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 5.0.1 on 2024-01-30 16:45
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('feeds', '0002_blocklist'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='blocklist',
|
|
||||||
name='active',
|
|
||||||
field=models.BooleanField(default=True, help_text='Is this URL still blocked?'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 5.0.1 on 2024-01-30 18:22
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('feeds', '0003_blocklist_active'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='blocklist',
|
|
||||||
name='url',
|
|
||||||
field=models.CharField(help_text='The URL to block.', max_length=2000, unique=True),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
983
feeds/models.py
983
feeds/models.py
|
|
@ -1,983 +0,0 @@
|
||||||
"""Django models for the feeds app."""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import typing
|
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
FEED_VERSION_CHOICES: tuple = (
|
|
||||||
("atom", "Atom (unknown or unrecognized version)"),
|
|
||||||
("atom01", "Atom 0.1"),
|
|
||||||
("atom02", "Atom 0.2"),
|
|
||||||
("atom03", "Atom 0.3"),
|
|
||||||
("atom10", "Atom 1.0"),
|
|
||||||
("cdf", "CDF"),
|
|
||||||
("rss", "RSS (unknown or unrecognized version)"),
|
|
||||||
("rss090", "RSS 0.90"),
|
|
||||||
("rss091n", "Netscape RSS 0.91"),
|
|
||||||
("rss091u", "Userland RSS 0.91"),
|
|
||||||
("rss092", "RSS 0.92"),
|
|
||||||
("rss093", "RSS 0.93"),
|
|
||||||
("rss094", "RSS 0.94 (no accurate specification is known to exist)"),
|
|
||||||
("rss10", "RSS 1.0"),
|
|
||||||
("rss20", "RSS 2.0"),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Author(models.Model):
|
|
||||||
"""Details about the author of a feed.
|
|
||||||
|
|
||||||
Comes from the following elements:
|
|
||||||
- /atom03:feed/atom03:author
|
|
||||||
- /atom10:feed/atom10:author
|
|
||||||
- /rdf:RDF/rdf:channel/dc:author
|
|
||||||
- /rdf:RDF/rdf:channel/dc:creator
|
|
||||||
- /rss/channel/dc:author
|
|
||||||
- /rss/channel/dc:creator
|
|
||||||
- /rss/channel/itunes:author
|
|
||||||
- /rss/channel/managingEditor
|
|
||||||
"""
|
|
||||||
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
|
||||||
|
|
||||||
name = models.TextField(blank=True, help_text="The name of the feed author.")
|
|
||||||
email = models.EmailField(blank=True, help_text="The email address of the feed author.")
|
|
||||||
|
|
||||||
# If this is a relative URI, it is resolved according to a set of rules:
|
|
||||||
# https://feedparser.readthedocs.io/en/latest/resolving-relative-links.html#advanced-base
|
|
||||||
href = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The URL of the feed author. This can be the author's home page, or a contact page with a webmail form.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Author meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed author"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feed authors"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "Details about the author of a feed."
|
|
||||||
|
|
||||||
def __str__(self: Author) -> str:
|
|
||||||
"""Author."""
|
|
||||||
return f"{self.name} {self.email} {self.href}"
|
|
||||||
|
|
||||||
|
|
||||||
class Contributor(models.Model):
|
|
||||||
"""Details about the contributor to a feed.
|
|
||||||
|
|
||||||
Comes from the following elements:
|
|
||||||
- /atom03:feed/atom03:contributor
|
|
||||||
- /atom10:feed/atom10:contributor
|
|
||||||
- /rss/channel/dc:contributor
|
|
||||||
"""
|
|
||||||
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
|
||||||
|
|
||||||
name = models.TextField(blank=True, help_text="The name of this contributor.")
|
|
||||||
email = models.EmailField(blank=True, help_text="The email address of this contributor.")
|
|
||||||
|
|
||||||
# If this is a relative URI, it is resolved according to a set of rules:
|
|
||||||
# https://feedparser.readthedocs.io/en/latest/resolving-relative-links.html#advanced-base
|
|
||||||
href = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The URL of this contributor. This can be the contributor's home page, or a contact page with a webmail form.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Contributor meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed contributor"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feed contributors"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "Details about the contributor to a feed."
|
|
||||||
|
|
||||||
def __str__(self: Contributor) -> str:
|
|
||||||
"""Contributor."""
|
|
||||||
return f"{self.name} {self.email} {self.href}"
|
|
||||||
|
|
||||||
|
|
||||||
class Cloud(models.Model):
|
|
||||||
"""No one really knows what a cloud is.
|
|
||||||
|
|
||||||
Comes from the following elements:
|
|
||||||
- /rss/channel/cloud
|
|
||||||
"""
|
|
||||||
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
|
||||||
|
|
||||||
domain = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The domain of the cloud. Should be just the domain name, not including the http:// protocol. All clouds are presumed to operate over HTTP. The cloud specification does not support secure clouds over HTTPS, nor can clouds operate over other protocols.", # noqa: E501
|
|
||||||
)
|
|
||||||
port = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The port of the cloud. Should be an integer, but Universal Feed Parser currently returns it as a string.", # noqa: E501
|
|
||||||
)
|
|
||||||
path = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The URL path of the cloud.",
|
|
||||||
)
|
|
||||||
register_procedure = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The name of the procedure to call on the cloud.",
|
|
||||||
)
|
|
||||||
protocol = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The protocol of the cloud. Documentation differs on what the acceptable values are. Acceptable values definitely include xml-rpc and soap, although only in lowercase, despite both being acronyms. There is no way for a publisher to specify the version number of the protocol to use. soap refers to SOAP 1.1; the cloud interface does not support SOAP 1.0 or 1.2. post or http-post might also be acceptable values; nobody really knows for sure.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Cloud meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed cloud"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feed clouds"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "No one really knows what a cloud is."
|
|
||||||
|
|
||||||
def __str__(self: Cloud) -> str:
|
|
||||||
"""Cloud domain."""
|
|
||||||
return f"{self.register_procedure} {self.protocol}://{self.domain}{self.path}:{self.port}"
|
|
||||||
|
|
||||||
|
|
||||||
class Generator(models.Model):
|
|
||||||
"""Details about the software used to generate the feed.
|
|
||||||
|
|
||||||
Comes from the following elements:
|
|
||||||
- /atom03:feed/atom03:generator
|
|
||||||
- /atom10:feed/atom10:generator
|
|
||||||
- /rdf:RDF/rdf:channel/admin:generatorAgent/@rdf:resource
|
|
||||||
- /rss/channel/generator
|
|
||||||
"""
|
|
||||||
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
|
||||||
|
|
||||||
name = models.TextField(blank=True, help_text="Human-readable name of the application used to generate the feed.")
|
|
||||||
|
|
||||||
# If this is a relative URI, it is resolved according to a set of rules:
|
|
||||||
# https://feedparser.readthedocs.io/en/latest/resolving-relative-links.html#advanced-base
|
|
||||||
href = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The URL of the application used to generate the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
version = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The version number of the application used to generate the feed. There is no required format for this, but most applications use a MAJOR.MINOR version number.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Generator meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed generator"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feed generators"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "Details about the software used to generate the feed."
|
|
||||||
|
|
||||||
def __str__(self: Generator) -> str:
|
|
||||||
"""Generator name."""
|
|
||||||
return f"{self.name} {self.version} {self.href}"
|
|
||||||
|
|
||||||
|
|
||||||
class Image(models.Model):
|
|
||||||
"""A feed image can be a logo, banner, or a picture of the author.
|
|
||||||
|
|
||||||
Comes from the following elements:
|
|
||||||
- /rdf:RDF/rdf:image
|
|
||||||
- /rss/channel/image
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```xml
|
|
||||||
<image>
|
|
||||||
<title>Feed logo</title>
|
|
||||||
<url>http://example.org/logo.png</url>
|
|
||||||
<link>http://example.org/</link>
|
|
||||||
<width>80</width>
|
|
||||||
<height>15</height>
|
|
||||||
<description>Visit my home page</description>
|
|
||||||
</image>
|
|
||||||
```
|
|
||||||
|
|
||||||
This feed image could be rendered in HTML as this:
|
|
||||||
```html
|
|
||||||
<a href="http://example.org/">
|
|
||||||
<img src="http://example.org/logo.png"
|
|
||||||
width="80"
|
|
||||||
height="15"
|
|
||||||
alt="Feed logo"
|
|
||||||
title="Visit my home page">
|
|
||||||
</a>
|
|
||||||
```
|
|
||||||
"""
|
|
||||||
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
|
||||||
|
|
||||||
title = models.TextField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The alternate text of the feed image, which would go in the alt attribute if you rendered the feed image as an HTML img element.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
# If this is a relative URI, it is resolved according to a set of rules:
|
|
||||||
# https://feedparser.readthedocs.io/en/latest/resolving-relative-links.html#advanced-base
|
|
||||||
href = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The URL of the feed image itself, which would go in the src attribute if you rendered the feed image as an HTML img element.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
# If this is a relative URI, it is resolved according to a set of rules:
|
|
||||||
# https://feedparser.readthedocs.io/en/latest/resolving-relative-links.html#advanced-base
|
|
||||||
link = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The URL which the feed image would point to. If you rendered the feed image as an HTML img element, you would wrap it in an a element and put this in the href attribute.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
width = models.IntegerField(
|
|
||||||
default=0,
|
|
||||||
help_text="The width of the feed image, which would go in the width attribute if you rendered the feed image as an HTML img element.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
height = models.IntegerField(
|
|
||||||
default=0,
|
|
||||||
help_text="The height of the feed image, which would go in the height attribute if you rendered the feed image as an HTML img element.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
description = models.TextField(
|
|
||||||
blank=True,
|
|
||||||
help_text="A short description of the feed image, which would go in the title attribute if you rendered the feed image as an HTML img element. This element is rare; it was available in Netscape RSS 0.91 but was dropped from Userland RSS 0.91.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Image meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed image"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feed images"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "A feed image can be a logo, banner, or a picture of the author."
|
|
||||||
|
|
||||||
def __str__(self: Image) -> str:
|
|
||||||
"""Image title."""
|
|
||||||
return f"{self.title} {self.href} {self.link} {self.width}x{self.height} {self.description}"
|
|
||||||
|
|
||||||
|
|
||||||
class Info(models.Model):
|
|
||||||
"""Details about the feed.
|
|
||||||
|
|
||||||
Comes from the following elements:
|
|
||||||
- /atom03:feed/atom03:info
|
|
||||||
- /rss/channel/feedburner:browserFriendly
|
|
||||||
"""
|
|
||||||
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
|
||||||
|
|
||||||
# This element is generally ignored by feed readers.
|
|
||||||
# If this contains HTML or XHTML, it is sanitized by default.
|
|
||||||
# If this contains HTML or XHTML, certain (X)HTML elements within this value may
|
|
||||||
# contain relative URI (Uniform Resource Identifier)'s. These relative URI's are
|
|
||||||
# resolved according to a set of rules: https://feedparser.readthedocs.io/en/latest/resolving-relative-links.html#advanced-base
|
|
||||||
value = models.TextField(
|
|
||||||
blank=True,
|
|
||||||
help_text="Free-form human-readable description of the feed format itself. Intended for people who view the feed in a browser, to explain what they just clicked on.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
# For Atom feeds, the content type is taken from the type attribute, which defaults to text/plain if not specified.
|
|
||||||
# For RSS feeds, the content type is auto-determined by inspecting the content, and defaults to text/html.
|
|
||||||
# Note that this may cause silent data loss if the value contains plain text with angle brackets.
|
|
||||||
# Future enhancement: some versions of RSS clearly specify that certain values default to text/plain,
|
|
||||||
# and Universal Feed Parser should respect this, but it doesn't yet.
|
|
||||||
info_type = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The content type of the feed info. Most likely text/plain, text/html, or application/xhtml+xml.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Supposed to be a language code, but publishers have been known to publish random values like “English” or “German”. # noqa: E501
|
|
||||||
# May come from the element's xml:lang attribute, or it may inherit from a parent element's xml:lang, or the Content-Language HTTP header # noqa: E501
|
|
||||||
language = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The language of the feed info.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# is only useful in rare situations and can usually be ignored. It is the original base URI for this value, as
|
|
||||||
# specified by the element's xml:base attribute, or a parent element's xml:base, or the appropriate HTTP header,
|
|
||||||
# or the URI of the feed. By the time you see it, Universal Feed Parser has already resolved relative links in all
|
|
||||||
# values where it makes sense to do so. Clients should never need to manually resolve relative links.
|
|
||||||
base = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The original base URI for links within the feed copyright.",
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Info meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed information"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feed information"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "Details about the feed."
|
|
||||||
|
|
||||||
def __str__(self: Info) -> str:
|
|
||||||
"""Info value."""
|
|
||||||
return f"{self.value} {self.info_type} {self.language} {self.base}"
|
|
||||||
|
|
||||||
|
|
||||||
class Link(models.Model):
|
|
||||||
"""A list of dictionaries with details on the links associated with the feed.
|
|
||||||
|
|
||||||
Each link has a rel (relationship), type (content type), and href (the URL that the link points to).
|
|
||||||
Some links may also have a title.
|
|
||||||
|
|
||||||
Comes from
|
|
||||||
/atom03:feed/atom03:link
|
|
||||||
/atom10:feed/atom10:link
|
|
||||||
/rdf:RDF/rdf:channel/rdf:link
|
|
||||||
/rss/channel/link
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Atom 1.0 defines five standard link relationships and describes the process for registering others.
|
|
||||||
# Here are the five standard rel values:
|
|
||||||
# alternate
|
|
||||||
# enclosure
|
|
||||||
# related
|
|
||||||
# self
|
|
||||||
# via
|
|
||||||
rel = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The relationship of this feed link.",
|
|
||||||
)
|
|
||||||
|
|
||||||
link_type = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The content type of the page that this feed link points to.",
|
|
||||||
)
|
|
||||||
|
|
||||||
href = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The URL of the page that this feed link points to.",
|
|
||||||
)
|
|
||||||
|
|
||||||
title = models.TextField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The title of this feed link.",
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Link meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed link"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feed links"
|
|
||||||
db_table_comment: typing.ClassVar[str] = (
|
|
||||||
"A list of dictionaries with details on the links associated with the feed."
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self: Link) -> str:
|
|
||||||
"""Link href."""
|
|
||||||
return f"{self.href}"
|
|
||||||
|
|
||||||
|
|
||||||
class Publisher(models.Model):
|
|
||||||
"""The publisher of the feed.
|
|
||||||
|
|
||||||
Comes from the following elements:
|
|
||||||
/rdf:RDF/rdf:channel/dc:publisher
|
|
||||||
/rss/channel/dc:publisher
|
|
||||||
/rss/channel/itunes:owner
|
|
||||||
/rss/channel/webMaster
|
|
||||||
"""
|
|
||||||
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
|
||||||
|
|
||||||
name = models.TextField(blank=True, help_text="The name of this feed's publisher.")
|
|
||||||
email = models.EmailField(blank=True, help_text="The email address of this feed's publisher.")
|
|
||||||
|
|
||||||
# If this is a relative URI, it is resolved according to a set of rules:
|
|
||||||
# https://feedparser.readthedocs.io/en/latest/resolving-relative-links.html#advanced-base
|
|
||||||
href = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The URL of this feed's publisher. This can be the publisher's home page, or a contact page with a webmail form.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Publisher meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed publisher"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feed publishers"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "Details about the publisher of a feed."
|
|
||||||
|
|
||||||
def __str__(self: Publisher) -> str:
|
|
||||||
"""Publisher."""
|
|
||||||
return f"{self.name} {self.email} {self.href}"
|
|
||||||
|
|
||||||
|
|
||||||
class Rights(models.Model):
|
|
||||||
"""Details about the rights of a feed.
|
|
||||||
|
|
||||||
For machine-readable copyright information, see feed.license.
|
|
||||||
|
|
||||||
Comes from the following elements:
|
|
||||||
/atom03:feed/atom03:copyright
|
|
||||||
/atom10:feed/atom10:rights
|
|
||||||
/rdf:RDF/rdf:channel/dc:rights
|
|
||||||
/rss/channel/copyright
|
|
||||||
/rss/channel/dc:rights
|
|
||||||
"""
|
|
||||||
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
|
||||||
|
|
||||||
# If this contains HTML or XHTML, it is sanitized by default.
|
|
||||||
# If this contains HTML or XHTML, certain (X)HTML elements within this value may
|
|
||||||
# contain relative URI (Uniform Resource Identifier)'s. These relative URI's are
|
|
||||||
# resolved according to a set of rules: https://feedparser.readthedocs.io/en/latest/resolving-relative-links.html#advanced-base
|
|
||||||
value = models.TextField(
|
|
||||||
blank=True,
|
|
||||||
help_text="A human-readable copyright statement for the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# For Atom feeds, the content type is taken from the type attribute, which defaults to text/plain if not specified.
|
|
||||||
# For RSS feeds, the content type is auto-determined by inspecting the content, and defaults to text/html.
|
|
||||||
# Note that this may cause silent data loss if the value contains plain text with angle brackets.
|
|
||||||
# Future enhancement: some versions of RSS clearly specify that certain values default to text/plain,
|
|
||||||
# and Universal Feed Parser should respect this, but it doesn't yet.
|
|
||||||
rights_type = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The content type of the feed copyright. Most likely text/plain, text/html, or application/xhtml+xml.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
# Supposed to be a language code, but publishers have been known to publish random values like “English” or “German”. # noqa: E501
|
|
||||||
# May come from the element's xml:lang attribute, or it may inherit from a parent element's xml:lang, or the Content-Language HTTP header # noqa: E501
|
|
||||||
language = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The language of the feed rights.",
|
|
||||||
)
|
|
||||||
|
|
||||||
base = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The original base URI for links within the feed copyright.",
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Rights meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed rights"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feed rights"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "Details about the rights of a feed."
|
|
||||||
|
|
||||||
def __str__(self: Rights) -> str:
|
|
||||||
"""Rights value."""
|
|
||||||
return f"{self.value} {self.rights_type} {self.language} {self.base}"
|
|
||||||
|
|
||||||
|
|
||||||
class Subtitle(models.Model):
|
|
||||||
"""A subtitle, tagline, slogan, or other short description of the feed.
|
|
||||||
|
|
||||||
Comes from
|
|
||||||
/atom03:feed/atom03:tagline
|
|
||||||
/atom10:feed/atom10:subtitle
|
|
||||||
/rdf:RDF/rdf:channel/dc:description
|
|
||||||
/rdf:RDF/rdf:channel/rdf:description
|
|
||||||
/rss/channel/dc:description
|
|
||||||
/rss/channel/description
|
|
||||||
/rss/channel/itunes:subtitle
|
|
||||||
"""
|
|
||||||
|
|
||||||
value = models.TextField(
|
|
||||||
blank=True,
|
|
||||||
help_text="A subtitle, tagline, slogan, or other short description of the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
subtitle_type = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The content type of the feed subtitle. Most likely text/plain, text/html, or application/xhtml+xml.",
|
|
||||||
)
|
|
||||||
|
|
||||||
language = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The language of the feed subtitle.",
|
|
||||||
)
|
|
||||||
|
|
||||||
base = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The original base URI for links within the feed subtitle.",
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Subtitle meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed subtitle"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feed subtitles"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "A subtitle, tagline, slogan, or other short description of the feed."
|
|
||||||
|
|
||||||
def __str__(self: Subtitle) -> str:
|
|
||||||
"""Subtitle value."""
|
|
||||||
return f"{self.value} {self.subtitle_type} {self.language} {self.base}"
|
|
||||||
|
|
||||||
|
|
||||||
class Tags(models.Model):
|
|
||||||
"""A list of tags associated with the feed.
|
|
||||||
|
|
||||||
Comes from
|
|
||||||
/atom03:feed/dc:subject
|
|
||||||
/atom10:feed/category
|
|
||||||
/rdf:RDF/rdf:channel/dc:subject
|
|
||||||
/rss/channel/category
|
|
||||||
/rss/channel/dc:subject
|
|
||||||
/rss/channel/itunes:category
|
|
||||||
/rss/channel/itunes:keywords
|
|
||||||
"""
|
|
||||||
|
|
||||||
term = models.TextField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The category term (keyword).",
|
|
||||||
)
|
|
||||||
|
|
||||||
scheme = models.CharField(
|
|
||||||
blank=True,
|
|
||||||
max_length=255,
|
|
||||||
help_text="The category scheme (domain).",
|
|
||||||
)
|
|
||||||
|
|
||||||
label = models.TextField(
|
|
||||||
blank=True,
|
|
||||||
help_text="A human-readable label for the category.",
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Tags meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed tag"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feed tags"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "A list of tags associated with the feed."
|
|
||||||
|
|
||||||
def __str__(self: Tags) -> str:
|
|
||||||
"""Tag term."""
|
|
||||||
return f"{self.term} {self.scheme} {self.label}"
|
|
||||||
|
|
||||||
|
|
||||||
class TextInput(models.Model):
|
|
||||||
"""A text input form. No one actually uses this. Why are you?
|
|
||||||
|
|
||||||
Comes from the following elements:
|
|
||||||
/rdf:RDF/rdf:textinput
|
|
||||||
/rss/channel/textInput
|
|
||||||
/rss/channel/textinput
|
|
||||||
|
|
||||||
Example:
|
|
||||||
This is a text input in a feed:
|
|
||||||
```xml
|
|
||||||
<textInput>
|
|
||||||
<title>Go!</title>
|
|
||||||
<link>http://example.org/search</link>
|
|
||||||
<name>keyword</name>
|
|
||||||
<description>Search this site:</description>
|
|
||||||
</textInput>
|
|
||||||
```
|
|
||||||
|
|
||||||
This is how it could be rendered in HTML:
|
|
||||||
```html
|
|
||||||
<form method="get" action="http://example.org/search">
|
|
||||||
<label for="keyword">Search this site:</label>
|
|
||||||
<input type="text" id="keyword" name="keyword" value="">
|
|
||||||
<input type="submit" value="Go!">
|
|
||||||
</form>
|
|
||||||
```
|
|
||||||
"""
|
|
||||||
|
|
||||||
title = models.TextField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The title of the text input form, which would go in the value attribute of the form's submit button.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
link = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The link of the script which processes the text input form, which would go in the action attribute of the form.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
name = models.TextField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The name of the text input box in the form, which would go in the name attribute of the form's input box.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
description = models.TextField(
|
|
||||||
blank=True,
|
|
||||||
help_text="A short description of the text input form, which would go in the label element of the form.",
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""TextInput meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed text input"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feed text inputs"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "A text input form. No one actually uses this. Why are you?"
|
|
||||||
|
|
||||||
def __str__(self: TextInput) -> str:
|
|
||||||
"""TextInput title."""
|
|
||||||
return f"{self.title} {self.link} {self.name} {self.description}"
|
|
||||||
|
|
||||||
|
|
||||||
class Title(models.Model):
|
|
||||||
"""Details about the title of a feed.
|
|
||||||
|
|
||||||
Comes from the following elements:
|
|
||||||
/atom03:feed/atom03:title
|
|
||||||
/atom10:feed/atom10:title
|
|
||||||
/rdf:RDF/rdf:channel/dc:title
|
|
||||||
/rdf:RDF/rdf:channel/rdf:title
|
|
||||||
/rss/channel/dc:title
|
|
||||||
/rss/channel/title
|
|
||||||
"""
|
|
||||||
|
|
||||||
value = models.TextField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The title of the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
title_type = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The content type of the feed title. Most likely text/plain, text/html, or application/xhtml+xml.",
|
|
||||||
)
|
|
||||||
|
|
||||||
language = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The language of the feed title.",
|
|
||||||
)
|
|
||||||
|
|
||||||
base = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="The original base URI for links within the feed title.",
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Title meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed title"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feed titles"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "Details about the title of a feed."
|
|
||||||
|
|
||||||
def __str__(self: Title) -> str:
|
|
||||||
"""Title value."""
|
|
||||||
return f"{self.value} {self.title_type} {self.language} {self.base}"
|
|
||||||
|
|
||||||
|
|
||||||
class Feed(models.Model):
|
|
||||||
"""A feed."""
|
|
||||||
|
|
||||||
url = models.URLField(
|
|
||||||
unique=True,
|
|
||||||
help_text="The feed URL.",
|
|
||||||
)
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
|
||||||
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
|
|
||||||
|
|
||||||
# Error tracking
|
|
||||||
error = models.BooleanField(default=False)
|
|
||||||
error_message = models.TextField(default="")
|
|
||||||
error_at = models.DateTimeField(null=True)
|
|
||||||
|
|
||||||
# bozo may not be present. Some platforms, such as Mac OS X 10.2 and some versions of FreeBSD, do not include an XML
|
|
||||||
# parser in their Python distributions. Universal Feed Parser will still work on these platforms, but it will not be
|
|
||||||
# able to detect whether a feed is well-formed. However, it can detect whether a feed's character encoding is
|
|
||||||
# incorrectly declared. (This is done in Python, not by the XML parser.)
|
|
||||||
# See: https://feedparser.readthedocs.io/en/latest/bozo.html#advanced-bozo
|
|
||||||
bozo = models.BooleanField(default=False, help_text="Is the feed well-formed XML?")
|
|
||||||
# bozo_exception will only be present if bozo is True.
|
|
||||||
bozo_exception = models.TextField(
|
|
||||||
default="",
|
|
||||||
help_text="The exception raised when attempting to parse a non-well-formed feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# The process by which Universal Feed Parser determines the character encoding of the feed is explained can be found here: # noqa: E501
|
|
||||||
# https://feedparser.readthedocs.io/en/latest/character-encoding.html#advanced-encoding
|
|
||||||
# This element always exists, although it may be an empty string if the character encoding cannot be determined.
|
|
||||||
encoding = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
default="",
|
|
||||||
help_text="The character encoding that was used to parse the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# The purpose of etag is explained here: https://feedparser.readthedocs.io/en/latest/http-etag.html#http-etag
|
|
||||||
etag = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
default="",
|
|
||||||
help_text="The ETag of the feed, as specified in the HTTP headers.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Headers will only be present if the feed was retrieved from a web server. If the feed was parsed from a local file
|
|
||||||
# or from a string in memory, headers will not be present.
|
|
||||||
headers = models.TextField(
|
|
||||||
default="",
|
|
||||||
help_text="HTTP headers received from the web server when retrieving the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# href will only be present if the feed was retrieved from a web server. If the feed was parsed from a local file or
|
|
||||||
# from a string in memory, href will not be present.
|
|
||||||
href = models.URLField(
|
|
||||||
default="",
|
|
||||||
help_text="The final URL of the feed that was parsed. If the feed was redirected from the original requested address, href will contain the final (redirected) address.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
# last_modified will only be present if the feed was retrieved from a web server, and only if the web server
|
|
||||||
# provided a Last-Modified HTTP header for the feed. If the feed was parsed from a local file or from a string
|
|
||||||
# in memory, last_modified will not be present.
|
|
||||||
last_modified = models.DateTimeField(
|
|
||||||
null=True,
|
|
||||||
help_text="The last-modified date of the feed, as specified in the HTTP headers.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# The prefixes listed in the namespaces dictionary may not match the prefixes defined in the original feed.
|
|
||||||
# See: https://feedparser.readthedocs.io/en/latest/namespace-handling.html#advanced-namespaces
|
|
||||||
# This element always exists, although it may be an empty dictionary if the feed does not define any namespaces (such as an RSS 2.0 feed with no extensions). # noqa: E501
|
|
||||||
namespaces = models.TextField(
|
|
||||||
default="",
|
|
||||||
help_text="A dictionary of all XML namespaces defined in the feed, as {prefix: namespaceURI}.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# If the feed was redirected from its original URL, status will contain the redirect status code, not the
|
|
||||||
# final status code.
|
|
||||||
# If status is 301, the feed was permanently redirected to a new URL. Clients should update
|
|
||||||
# their address book to request the new URL from now on.
|
|
||||||
# If status is 410, the feed is gone. Clients should stop polling the feed.
|
|
||||||
# status will only be present if the feed was retrieved from a web server. If the feed was parsed from a local file
|
|
||||||
# or from a string in memory, status will not be present.
|
|
||||||
# TODO(TheLovinator): #1 We should change feed URL if we get a HTTP 301.
|
|
||||||
# https://github.com/TheLovinator1/FeedVault/issues/1
|
|
||||||
# TODO(TheLovinator): #2 We should stop polling a feed if we get a HTTP 410.
|
|
||||||
# https://github.com/TheLovinator1/FeedVault/issues/2
|
|
||||||
http_status_code = models.IntegerField(
|
|
||||||
default=0,
|
|
||||||
help_text="The HTTP status code that was returned by the web server when the feed was fetched.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# The format and version of the feed. the feed type is completely unknown, version will be an empty string.
|
|
||||||
version = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
choices=FEED_VERSION_CHOICES,
|
|
||||||
default="",
|
|
||||||
help_text="The version of the feed, as determined by Universal Feed Parser.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# /atom03:feed, /atom10:feed, /rdf:RDF/rdf:channel, /rss/channel
|
|
||||||
feed_data = models.TextField(
|
|
||||||
default="",
|
|
||||||
help_text="A dictionary of data about the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
author = models.ForeignKey(
|
|
||||||
Author,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
null=True,
|
|
||||||
help_text="The author of the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
cloud = models.ForeignKey(
|
|
||||||
Cloud,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
null=True,
|
|
||||||
help_text="Cloud enables realtime push notifications or distributed publish/subscribe communication for feeds.",
|
|
||||||
)
|
|
||||||
|
|
||||||
contributors = models.ManyToManyField(
|
|
||||||
Contributor,
|
|
||||||
help_text="A list of contributors (secondary authors) to this feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# This element is rare. The reasoning was that in 25 years, someone will stumble on
|
|
||||||
# an RSS feed and not know what it is, so we should waste everyone's bandwidth with
|
|
||||||
# useless links until then. Most publishers skip it, and all clients ignore it. If
|
|
||||||
# this is a relative URI, it is resolved according to a set of rules.
|
|
||||||
# Comes from /rss/channel/docs
|
|
||||||
docs = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="A URL pointing to the specification which this feed conforms to.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Comes from /rdf:RDF/admin:errorReportsTo/@rdf:resource
|
|
||||||
error_reports_to = models.EmailField(
|
|
||||||
blank=True,
|
|
||||||
help_text="An email address for reporting errors in the feed itself.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Comes from /atom10:feed/atom10:icon
|
|
||||||
generator = models.ForeignKey(
|
|
||||||
Generator,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
null=True,
|
|
||||||
help_text="Details about the software used to generate the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# If this is a relative URI, it is resolved according to a set of rules.
|
|
||||||
# Comes from/atom03:feed/atom03:id or /atom10:feed/atom10:id
|
|
||||||
feed_id = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="A globally unique identifier for this feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
image = models.ForeignKey(
|
|
||||||
Image,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
null=True,
|
|
||||||
help_text="A feed image can be a logo, banner, or a picture of the author.",
|
|
||||||
)
|
|
||||||
|
|
||||||
info = models.ForeignKey(
|
|
||||||
Info,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
null=True,
|
|
||||||
help_text="Details about the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Comes from:
|
|
||||||
# /atom03:feed/@xml:lang
|
|
||||||
# /atom10:feed/@xml:lang
|
|
||||||
# /rdf:RDF/rdf:channel/dc:language
|
|
||||||
# /rss/channel/dc:language
|
|
||||||
# /rss/channel/language
|
|
||||||
language = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The primary language of the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Comes from /atom10:feed/atom10:link[@rel=”license”]/@href, /rdf:RDF/cc:license/@rdf:resource or /rss/channel/creativeCommons:license # noqa: E501
|
|
||||||
license = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="A URL pointing to the license of the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
link = models.ForeignKey(
|
|
||||||
Link,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
null=True,
|
|
||||||
help_text="A list of dictionaries with details on the links associated with the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Comes from /atom10:feed/atom10:logo
|
|
||||||
logo = models.URLField(
|
|
||||||
blank=True,
|
|
||||||
help_text="A URL to a graphic representing a logo for the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Comes from /rss/channel/pubDate
|
|
||||||
# See feed.published_parsed for a more useful version of this value.
|
|
||||||
published = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The date the feed was published, as a string in the same format as it was published in the original feed.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
# Parsed version of feed.published. Feedparser gives us a standard Python 9-tuple.
|
|
||||||
published_parsed = models.DateTimeField(
|
|
||||||
null=True,
|
|
||||||
help_text="The date the feed was published.",
|
|
||||||
)
|
|
||||||
|
|
||||||
publisher = models.ForeignKey(
|
|
||||||
Publisher,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
null=True,
|
|
||||||
help_text="The publisher of the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
rights = models.ForeignKey(
|
|
||||||
Rights,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
null=True,
|
|
||||||
help_text="Details about the rights of a feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
subtitle = models.ForeignKey(
|
|
||||||
Subtitle,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
null=True,
|
|
||||||
help_text="A subtitle, tagline, slogan, or other short description of the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
tags = models.ManyToManyField(
|
|
||||||
Tags,
|
|
||||||
help_text="A list of tags associated with the feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
text_input = models.ForeignKey(
|
|
||||||
TextInput,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
null=True,
|
|
||||||
help_text="A text input form. No one actually uses this. Why are you?",
|
|
||||||
)
|
|
||||||
|
|
||||||
title = models.ForeignKey(
|
|
||||||
Title,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
null=True,
|
|
||||||
help_text="Details about the title of a feed.",
|
|
||||||
)
|
|
||||||
|
|
||||||
# No one is quite sure what this means, and no one publishes feeds via file-sharing networks.
|
|
||||||
# Some clients have interpreted this element to be some sort of inline caching mechanism, albeit one
|
|
||||||
# that completely ignores the underlying HTTP protocol, its robust caching mechanisms, and the huge
|
|
||||||
# amount of HTTP-savvy network infrastructure that understands them. Given the vague documentation,
|
|
||||||
# it is impossible to say that this interpretation is any more ridiculous than the element itself.
|
|
||||||
# Comes from /rss/channel/ttl
|
|
||||||
ttl = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text='According to the RSS specification, “None"',
|
|
||||||
)
|
|
||||||
|
|
||||||
# if this key doesn't exist but feed.published does, the value of feed.published will be returned.
|
|
||||||
updated = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
help_text="The date the feed was last updated, as a string in the same format as it was published in the original feed.", # noqa: E501
|
|
||||||
)
|
|
||||||
|
|
||||||
updated_parsed = models.DateTimeField(
|
|
||||||
null=True,
|
|
||||||
help_text="The date the feed was last updated.",
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Feed meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Feed"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Feeds"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "A feed. This is the main model of the app."
|
|
||||||
|
|
||||||
def __str__(self: Feed) -> str:
|
|
||||||
"""Feed URL."""
|
|
||||||
return f"{self.url}"
|
|
||||||
|
|
||||||
|
|
||||||
class Blocklist(models.Model):
|
|
||||||
"""A list of URLs to block."""
|
|
||||||
|
|
||||||
url = models.CharField(max_length=2000, unique=True, help_text="The URL to block.")
|
|
||||||
active = models.BooleanField(default=True, help_text="Is this URL still blocked?")
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Blocklist meta."""
|
|
||||||
|
|
||||||
verbose_name: typing.ClassVar[str] = "Blocklist"
|
|
||||||
verbose_name_plural: typing.ClassVar[str] = "Blocklists"
|
|
||||||
db_table_comment: typing.ClassVar[str] = "A list of URLs to block."
|
|
||||||
|
|
||||||
def __str__(self: Blocklist) -> str:
|
|
||||||
"""Blocklist URL."""
|
|
||||||
return f"{self.url}"
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
"""https://docs.djangoproject.com/en/5.0/topics/testing/."""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import random
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.test import Client, TestCase
|
|
||||||
|
|
||||||
from feeds.validator import is_ip, validate_scheme
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.http import HttpResponse
|
|
||||||
|
|
||||||
|
|
||||||
class TestHomePage(TestCase):
|
|
||||||
"""Test case for the home page view."""
|
|
||||||
|
|
||||||
def setUp(self: TestHomePage) -> None:
|
|
||||||
"""Set up the test client for the test case."""
|
|
||||||
self.client = Client()
|
|
||||||
|
|
||||||
def test_home_page(self: TestHomePage) -> None:
|
|
||||||
"""Test that a GET request to the home page returns a 200 status code."""
|
|
||||||
response: HttpResponse = self.client.get("/")
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
|
|
||||||
class TestValidator(TestCase):
|
|
||||||
"""Test case for the validator."""
|
|
||||||
|
|
||||||
def setUp(self: TestValidator) -> None:
|
|
||||||
"""Set up the test client for the test case."""
|
|
||||||
self.client = Client()
|
|
||||||
|
|
||||||
def test_is_ip(self: TestValidator) -> None:
|
|
||||||
"""Test that is_ip() returns True for a valid IP address."""
|
|
||||||
# Test random IP address
|
|
||||||
random_ip: str = ".".join(str(random.randint(0, 255)) for _ in range(4)) # noqa: S311
|
|
||||||
assert is_ip(feed_url=random_ip)
|
|
||||||
|
|
||||||
# Test domain name
|
|
||||||
assert not is_ip(feed_url="https://example.com")
|
|
||||||
|
|
||||||
def test_validate_scheme(self: TestValidator) -> None:
|
|
||||||
"""Test that validate_scheme() returns True for a valid scheme."""
|
|
||||||
assert validate_scheme(feed_url="https://example.com")
|
|
||||||
assert validate_scheme(feed_url="http://example.com")
|
|
||||||
assert not validate_scheme(feed_url="ftp://example.com")
|
|
||||||
assert not validate_scheme(feed_url="example.com")
|
|
||||||
assert not validate_scheme(feed_url="127.0.0.1")
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
"""URLs for the feeds app."""
|
|
||||||
|
|
||||||
from django.urls import path
|
|
||||||
|
|
||||||
from feeds.views import APIView, DonateView, FeedsView, IndexView, add_feeds, upload_opml
|
|
||||||
|
|
||||||
app_name = "feeds"
|
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
# /
|
|
||||||
path("", IndexView.as_view(), name="index"),
|
|
||||||
# /feeds
|
|
||||||
path("feeds", FeedsView.as_view(), name="feeds"),
|
|
||||||
# /add
|
|
||||||
path("add", add_feeds, name="add"),
|
|
||||||
# /api
|
|
||||||
path("api", APIView.as_view(), name="api"),
|
|
||||||
# /donate
|
|
||||||
path("donate", DonateView.as_view(), name="donate"),
|
|
||||||
# /upload_opml
|
|
||||||
path("upload_opml", upload_opml, name="upload_opml"),
|
|
||||||
]
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
"""Validate feeds before adding them to the database."""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import ipaddress
|
|
||||||
import logging
|
|
||||||
import socket
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from django.core.exceptions import ValidationError
|
|
||||||
from django.core.validators import URLValidator
|
|
||||||
|
|
||||||
from feeds.models import Blocklist
|
|
||||||
|
|
||||||
BLOCKLISTS: list[str] = [
|
|
||||||
"https://malware-filter.gitlab.io/malware-filter/urlhaus-filter-dnscrypt-blocked-names.txt",
|
|
||||||
"https://malware-filter.gitlab.io/malware-filter/phishing-filter-dnscrypt-blocked-names.txt",
|
|
||||||
]
|
|
||||||
|
|
||||||
logger: logging.Logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def validate_scheme(feed_url: str) -> bool:
|
|
||||||
"""Validate the scheme of a URL. Only allow http and https.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
feed_url: The URL to validate.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
True if the URL is valid, False otherwise.
|
|
||||||
"""
|
|
||||||
validator = URLValidator(schemes=["http", "https"])
|
|
||||||
# TODO(TheLovinator): Should we allow other schemes? # noqa: TD003
|
|
||||||
try:
|
|
||||||
validator(feed_url)
|
|
||||||
except ValidationError:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def is_ip(feed_url: str) -> bool:
|
|
||||||
"""Check if feed is an IP address."""
|
|
||||||
try:
|
|
||||||
ipaddress.ip_address(feed_url)
|
|
||||||
except ValueError:
|
|
||||||
logger.info(f"{feed_url} passed isn't either a v4 or a v6 address") # noqa: G004
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
logger.info(f"{feed_url} is an IP address") # noqa: G004
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def update_blocklist() -> str:
|
|
||||||
"""Download the blocklist and add to database."""
|
|
||||||
# URLs found in the blocklist
|
|
||||||
found_urls = set()
|
|
||||||
|
|
||||||
for _blocklist in BLOCKLISTS:
|
|
||||||
with requests.get(url=_blocklist, timeout=10) as r:
|
|
||||||
r.raise_for_status()
|
|
||||||
|
|
||||||
logger.debug(f"Downloaded {_blocklist}") # noqa: G004
|
|
||||||
|
|
||||||
# Split the blocklist into a list of URLs
|
|
||||||
blocked_urls = set(r.text.splitlines())
|
|
||||||
|
|
||||||
# Remove comments and whitespace
|
|
||||||
blocked_urls = {url for url in blocked_urls if not url.startswith("#")}
|
|
||||||
blocked_urls = {url.strip() for url in blocked_urls}
|
|
||||||
|
|
||||||
logger.debug(f"Found {len(blocked_urls)} URLs in {_blocklist}") # noqa: G004
|
|
||||||
|
|
||||||
# Add URLs to the found URLs set
|
|
||||||
found_urls.update(blocked_urls)
|
|
||||||
|
|
||||||
logger.debug(f"Found {len(found_urls)} URLs in total") # noqa: G004
|
|
||||||
|
|
||||||
# Mark all URLs as inactive
|
|
||||||
Blocklist.objects.all().update(active=False)
|
|
||||||
|
|
||||||
logger.debug("Marked all URLs as inactive")
|
|
||||||
|
|
||||||
# Bulk create the blocklist
|
|
||||||
Blocklist.objects.bulk_create(
|
|
||||||
[Blocklist(url=url, active=True) for url in found_urls],
|
|
||||||
update_conflicts=True,
|
|
||||||
unique_fields=["url"],
|
|
||||||
update_fields=["active"],
|
|
||||||
batch_size=1000,
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.debug(f"Added {len(found_urls)} URLs to the blocklist") # noqa: G004
|
|
||||||
return f"Added {len(found_urls)} URLs to the blocklist"
|
|
||||||
|
|
||||||
|
|
||||||
def is_local(feed_url: str) -> bool:
|
|
||||||
"""Check if feed is a local address."""
|
|
||||||
network_location: str = urlparse(url=feed_url).netloc
|
|
||||||
|
|
||||||
# Check if network location is an IP address
|
|
||||||
if is_ip(feed_url=network_location):
|
|
||||||
try:
|
|
||||||
ip: ipaddress.IPv4Address | ipaddress.IPv6Address = ipaddress.ip_address(address=network_location)
|
|
||||||
except ValueError:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return ip.is_private
|
|
||||||
|
|
||||||
try:
|
|
||||||
ip_address: str = socket.gethostbyname(network_location)
|
|
||||||
is_private: bool = ipaddress.ip_address(address=ip_address).is_private
|
|
||||||
except socket.gaierror as e:
|
|
||||||
logger.info(f"{feed_url} failed to resolve: {e}") # noqa: G004
|
|
||||||
return True
|
|
||||||
except ValueError as e:
|
|
||||||
logger.info(f"{feed_url} failed to resolve: {e}") # noqa: G004
|
|
||||||
return True
|
|
||||||
|
|
||||||
msg: str = f"{feed_url} is a local URL" if is_private else f"{feed_url} is not a local URL"
|
|
||||||
logger.info(msg)
|
|
||||||
|
|
||||||
return is_private
|
|
||||||
283
feeds/views.py
283
feeds/views.py
|
|
@ -1,283 +0,0 @@
|
||||||
"""Views for the feeds app.
|
|
||||||
|
|
||||||
IndexView - /
|
|
||||||
FeedsView - /feeds
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import typing
|
|
||||||
from urllib import parse
|
|
||||||
|
|
||||||
import listparser
|
|
||||||
from django.contrib import messages
|
|
||||||
from django.core.exceptions import ValidationError
|
|
||||||
from django.db import connection
|
|
||||||
from django.shortcuts import redirect
|
|
||||||
from django.views.generic.base import TemplateView
|
|
||||||
from django.views.generic.list import ListView
|
|
||||||
|
|
||||||
from feeds.forms import UploadOPMLForm
|
|
||||||
from feeds.models import Blocklist, Feed
|
|
||||||
from feeds.validator import is_ip, is_local, validate_scheme
|
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
|
||||||
from django.http import HttpRequest, HttpResponse
|
|
||||||
from listparser.common import SuperDict
|
|
||||||
|
|
||||||
logger: logging.Logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def get_database_size() -> int:
|
|
||||||
"""Get the size of a database.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The size of the database in megabytes.
|
|
||||||
"""
|
|
||||||
with connection.cursor() as cursor:
|
|
||||||
# Query to get the size of the database
|
|
||||||
query = "SELECT pg_database_size('feedvault')"
|
|
||||||
cursor.execute(sql=query)
|
|
||||||
|
|
||||||
if not cursor:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
size_in_bytes = cursor.fetchone()[0] # type: ignore # noqa: PGH003
|
|
||||||
|
|
||||||
if not size_in_bytes:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
return int(size_in_bytes / (1024 * 1024))
|
|
||||||
|
|
||||||
|
|
||||||
class IndexView(TemplateView):
|
|
||||||
"""Index page."""
|
|
||||||
|
|
||||||
template_name = "index.html"
|
|
||||||
|
|
||||||
def get_context_data(self: IndexView, **kwargs: dict) -> dict:
|
|
||||||
"""Add feed count and database size to context data."""
|
|
||||||
context: dict = super().get_context_data(**kwargs)
|
|
||||||
context["feed_count"] = Feed.objects.count()
|
|
||||||
context["database_size"] = get_database_size()
|
|
||||||
|
|
||||||
logger.info(f"Found {context['feed_count']} feeds in the database") # noqa: G004
|
|
||||||
logger.info(f"Database size is {context['database_size']} MB") # noqa: G004
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
class FeedsView(ListView):
|
|
||||||
"""Feeds page."""
|
|
||||||
|
|
||||||
model = Feed
|
|
||||||
template_name = "feeds.html"
|
|
||||||
context_object_name = "feeds"
|
|
||||||
paginate_by = 100
|
|
||||||
ordering: typing.ClassVar[list[str]] = ["-created_at"]
|
|
||||||
|
|
||||||
def get_context_data(self: FeedsView, **kwargs: dict) -> dict:
|
|
||||||
"""Add feed count and database size to context data."""
|
|
||||||
context: dict = super().get_context_data(**kwargs)
|
|
||||||
context["feed_count"] = Feed.objects.count()
|
|
||||||
context["database_size"] = get_database_size()
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
def add_feeds(request: HttpRequest) -> HttpResponse:
|
|
||||||
"""Add feeds to the database.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request: The request object.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A redirect to the index page if there are errors, otherwise a redirect to the feeds page.
|
|
||||||
"""
|
|
||||||
if request.method == "POST":
|
|
||||||
urls: str | None = request.POST.get("urls")
|
|
||||||
if not urls:
|
|
||||||
messages.error(request, "No URLs provided")
|
|
||||||
return redirect("feeds:index")
|
|
||||||
|
|
||||||
if urls == "Test":
|
|
||||||
messages.error(request, "Test test hello")
|
|
||||||
return redirect("feeds:index")
|
|
||||||
|
|
||||||
for url in urls.splitlines():
|
|
||||||
check_feeds(feed_urls=[url], request=request)
|
|
||||||
|
|
||||||
return redirect("feeds:index")
|
|
||||||
|
|
||||||
msg: str = f"You must use a POST request. You used a {request.method} request. You can find out how to use this endpoint here: <a href=''>http://127.0.0.1:8000/</a>. If you think this is a mistake, please contact the administrator." # noqa: E501
|
|
||||||
messages.error(request, msg)
|
|
||||||
return redirect("feeds:index")
|
|
||||||
|
|
||||||
|
|
||||||
def handle_opml(opml_url: str, request: HttpRequest) -> None:
|
|
||||||
"""Add feeds from an OPML file.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
opml_url: The URL of the OPML file.
|
|
||||||
request: The request object.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Errors
|
|
||||||
"""
|
|
||||||
if not opml_url:
|
|
||||||
msg: str = "No URL provided when parsing OPML file."
|
|
||||||
messages.error(request, msg)
|
|
||||||
logger.error(msg)
|
|
||||||
return
|
|
||||||
|
|
||||||
url_html: str = f"<a href='{opml_url}'>{opml_url}</a>"
|
|
||||||
result: SuperDict = listparser.parse(opml_url)
|
|
||||||
if result.bozo:
|
|
||||||
msg: str = f"Error when parsing {url_html}: '{result.bozo_exception}'"
|
|
||||||
messages.error(request, msg)
|
|
||||||
logger.error(msg)
|
|
||||||
return
|
|
||||||
|
|
||||||
for feed in result.feeds:
|
|
||||||
logger.debug(f"Found {feed.url} in OPML file '{opml_url}' for '{feed.title}'") # noqa: G004
|
|
||||||
check_feeds(feed_urls=feed.url, request=request)
|
|
||||||
|
|
||||||
|
|
||||||
def validate_and_add(url: str, request: HttpRequest) -> None:
|
|
||||||
"""Check if a feed is valid.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
url: The URL of the feed.
|
|
||||||
request: The request object.
|
|
||||||
"""
|
|
||||||
# TODO(TheLovinator): #4 Rewrite this so we check the content instead of the URL
|
|
||||||
# https://github.com/TheLovinator1/FeedVault/issues/4
|
|
||||||
list_of_opml_urls: list[str] = [".opml", ".ttl", ".trig", ".rdf"]
|
|
||||||
if url.endswith(tuple(list_of_opml_urls)):
|
|
||||||
handle_opml(opml_url=url, request=request)
|
|
||||||
return
|
|
||||||
|
|
||||||
url_html: str = f"<a href='{url}'>{url}</a>"
|
|
||||||
if Feed.objects.filter(url=url).exists():
|
|
||||||
msg: str = f"{url_html} is already in the database."
|
|
||||||
messages.error(request, msg)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Only allow HTTP and HTTPS URLs
|
|
||||||
if not validate_scheme(feed_url=url):
|
|
||||||
msg = f"{url_html} is not a HTTP or HTTPS URL."
|
|
||||||
messages.error(request, msg)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Don't allow IP addresses
|
|
||||||
if is_ip(feed_url=url):
|
|
||||||
msg = f"{url_html} is an IP address. IP addresses are not allowed."
|
|
||||||
messages.error(request, msg)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Check if in blocklist
|
|
||||||
domain: str = parse.urlparse(url).netloc
|
|
||||||
if Blocklist.objects.filter(url=domain).exists():
|
|
||||||
msg = f"{url_html} is in the blocklist."
|
|
||||||
messages.error(request, msg)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Check if local URL
|
|
||||||
if is_local(feed_url=url):
|
|
||||||
msg = f"{url_html} is not accessible from the internet."
|
|
||||||
messages.error(request, msg)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Create feed
|
|
||||||
try:
|
|
||||||
Feed.objects.create(url=url)
|
|
||||||
msg = f"{url_html} was added to the database."
|
|
||||||
messages.success(request, msg)
|
|
||||||
except ValidationError:
|
|
||||||
msg = f"{url_html} is not a valid URL."
|
|
||||||
messages.error(request, msg)
|
|
||||||
|
|
||||||
|
|
||||||
def check_feeds(feed_urls: list[str], request: HttpRequest) -> HttpResponse:
|
|
||||||
"""Check feeds before adding them to the database.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
feed_urls: The feed URLs to check.
|
|
||||||
request: The request object.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A redirect to the index page if there are errors, otherwise a redirect to the feeds page.
|
|
||||||
"""
|
|
||||||
for url in feed_urls:
|
|
||||||
validate_and_add(url=url, request=request)
|
|
||||||
|
|
||||||
# Return to feeds page if no errors
|
|
||||||
# TODO(TheLovinator): Return to search page with our new feeds # noqa: TD003
|
|
||||||
logger.info(f"Added {len(feed_urls)} feeds to the database") # noqa: G004
|
|
||||||
return redirect("feeds:feeds")
|
|
||||||
|
|
||||||
|
|
||||||
class APIView(TemplateView):
|
|
||||||
"""API page."""
|
|
||||||
|
|
||||||
template_name = "api.html"
|
|
||||||
|
|
||||||
def get_context_data(self: APIView, **kwargs: dict) -> dict:
|
|
||||||
"""Add feed count and database size to context data."""
|
|
||||||
context: dict = super().get_context_data(**kwargs)
|
|
||||||
context["feed_count"] = Feed.objects.count()
|
|
||||||
context["database_size"] = get_database_size()
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
class DonateView(TemplateView):
|
|
||||||
"""Donate page."""
|
|
||||||
|
|
||||||
template_name = "donate.html"
|
|
||||||
|
|
||||||
def get_context_data(self: DonateView, **kwargs: dict) -> dict:
|
|
||||||
"""Add feed count and database size to context data."""
|
|
||||||
context: dict = super().get_context_data(**kwargs)
|
|
||||||
context["feed_count"] = Feed.objects.count()
|
|
||||||
context["database_size"] = get_database_size()
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
def upload_opml(request: HttpRequest) -> HttpResponse:
|
|
||||||
"""Upload an OPML file.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request: The request object.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A redirect to the index page if there are errors, otherwise a redirect to the feeds page.
|
|
||||||
"""
|
|
||||||
if request.method == "POST":
|
|
||||||
form = UploadOPMLForm(request.POST, request.FILES)
|
|
||||||
if form.is_valid():
|
|
||||||
opml_file = request.FILES["file"]
|
|
||||||
|
|
||||||
# Read file
|
|
||||||
with opml_file.open() as file:
|
|
||||||
opml_file = file.read().decode("utf-8")
|
|
||||||
|
|
||||||
result: SuperDict = listparser.parse(opml_file)
|
|
||||||
if result.bozo:
|
|
||||||
msg: str = f"Error when parsing OPML file: '{result.bozo_exception}'"
|
|
||||||
messages.error(request, msg)
|
|
||||||
logger.error(msg)
|
|
||||||
return redirect("feeds:index")
|
|
||||||
|
|
||||||
for feed in result.feeds:
|
|
||||||
logger.debug(f"Found {feed.url} in OPML file for '{feed.title}'") # noqa: G004
|
|
||||||
validate_and_add(url=feed.url, request=request)
|
|
||||||
|
|
||||||
for _list in result.lists:
|
|
||||||
logger.debug(f"Found {_list.url} in OPML file for '{_list.title}'") # noqa: G004
|
|
||||||
validate_and_add(url=_list.url, request=request)
|
|
||||||
|
|
||||||
return redirect("feeds:index")
|
|
||||||
|
|
||||||
msg: str = "Invalid form"
|
|
||||||
messages.error(request, msg)
|
|
||||||
logger.error(msg)
|
|
||||||
return redirect("feeds:index")
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
"""This package contains the Django project for FeedVault."""
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
"""ASGI config for FeedVault project.
|
|
||||||
|
|
||||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from django.core.asgi import get_asgi_application
|
|
||||||
from django.core.handlers.asgi import ASGIHandler
|
|
||||||
|
|
||||||
os.environ.setdefault(key="DJANGO_SETTINGS_MODULE", value="feedvault.settings")
|
|
||||||
|
|
||||||
application: ASGIHandler = get_asgi_application()
|
|
||||||
|
|
@ -1,209 +0,0 @@
|
||||||
"""Django settings for FeedVault project.
|
|
||||||
|
|
||||||
Generated by 'django-admin startproject' using Django 5.0.1.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/5.0/topics/settings/
|
|
||||||
|
|
||||||
For the full list of settings and their values, see
|
|
||||||
https://docs.djangoproject.com/en/5.0/ref/settings/
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from dotenv import find_dotenv, load_dotenv
|
|
||||||
|
|
||||||
load_dotenv(dotenv_path=find_dotenv(), verbose=True)
|
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
|
||||||
BASE_DIR: Path = Path(__file__).resolve().parent.parent
|
|
||||||
|
|
||||||
# The secret key is used for cryptographic signing, and should be set to a unique, unpredictable value.
|
|
||||||
SECRET_KEY: str = os.getenv("SECRET_KEY", default="")
|
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
|
||||||
DEBUG: bool = os.getenv(key="DEBUG", default="True").lower() == "true"
|
|
||||||
|
|
||||||
# A list of all the people who get code error notifications. When DEBUG=False and a view raises an exception
|
|
||||||
# Django will email these people with the full exception information.
|
|
||||||
ADMINS: list[tuple[str, str]] = [("Joakim Hellsén", "django@feedvault.se")]
|
|
||||||
|
|
||||||
# A list of strings representing the host/domain names that this Django site can serve.
|
|
||||||
# .feedvault.se will match *.feedvault.se and feedvault.se
|
|
||||||
ALLOWED_HOSTS: list[str] = [".feedvault.se", ".localhost", "127.0.0.1"]
|
|
||||||
|
|
||||||
# The time zone that Django will use to display datetimes in templates and to interpret datetimes entered in forms
|
|
||||||
TIME_ZONE: str = os.getenv(key="TZ", default="Europe/Stockholm")
|
|
||||||
|
|
||||||
# If datetimes will be timezone-aware by default. If True, Django will use timezone-aware datetimes internally.
|
|
||||||
USE_TZ = True
|
|
||||||
|
|
||||||
# Turn off Django's translation system
|
|
||||||
USE_I18N = False
|
|
||||||
|
|
||||||
# Decides which translation is served to all users.
|
|
||||||
LANGUAGE_CODE = "en-us"
|
|
||||||
|
|
||||||
# Default decimal separator used when formatting decimal numbers.
|
|
||||||
DECIMAL_SEPARATOR = ","
|
|
||||||
|
|
||||||
# Use a space as the thousand separator instead of a comma
|
|
||||||
THOUSAND_SEPARATOR = " "
|
|
||||||
|
|
||||||
# Use gmail for sending emails
|
|
||||||
EMAIL_HOST = "smtp.gmail.com"
|
|
||||||
EMAIL_PORT = 587
|
|
||||||
EMAIL_USE_TLS = True
|
|
||||||
EMAIL_HOST_USER: str = os.getenv(key="EMAIL_HOST_USER", default="webmaster@localhost")
|
|
||||||
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")
|
|
||||||
|
|
||||||
# Use the X-Forwarded-Host header
|
|
||||||
USE_X_FORWARDED_HOST = True
|
|
||||||
|
|
||||||
# Set the Referrer Policy HTTP header on all responses that do not already have one.
|
|
||||||
SECURE_REFERRER_POLICY = "strict-origin-when-cross-origin"
|
|
||||||
|
|
||||||
# Full Python import path to our main URL configuration.
|
|
||||||
ROOT_URLCONF = "feedvault.urls"
|
|
||||||
|
|
||||||
# URL to use when referring to static files located in STATIC_ROOT.
|
|
||||||
# https://feedvault.se/static/...
|
|
||||||
STATIC_URL = "static/"
|
|
||||||
|
|
||||||
# Use a 64-bit integer as a primary key for models that don't have a field with primary_key=True.
|
|
||||||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
|
||||||
|
|
||||||
# A string representing the full Python import path to our WSGI application object
|
|
||||||
WSGI_APPLICATION = "feedvault.wsgi.application"
|
|
||||||
|
|
||||||
# Internal IPs that are allowed to see debug views
|
|
||||||
INTERNAL_IPS: list[str] = ["127.0.0.1", "localhost"]
|
|
||||||
|
|
||||||
# Applications include some combination of models, views, templates, template tags, static files, URLs, middleware, etc
|
|
||||||
INSTALLED_APPS: list[str] = [
|
|
||||||
# First-party apps
|
|
||||||
"feeds.apps.FeedsConfig",
|
|
||||||
# Third-party apps
|
|
||||||
"whitenoise.runserver_nostatic", # https://whitenoise.readthedocs.io/en/latest/index.html
|
|
||||||
"debug_toolbar", # https://github.com/jazzband/django-debug-toolbar/
|
|
||||||
# Django apps
|
|
||||||
"django.contrib.sites",
|
|
||||||
"django.contrib.admin",
|
|
||||||
"django.contrib.sitemaps",
|
|
||||||
"django.contrib.auth",
|
|
||||||
"django.contrib.contenttypes",
|
|
||||||
"django.contrib.sessions",
|
|
||||||
"django.contrib.messages",
|
|
||||||
"django.contrib.staticfiles",
|
|
||||||
]
|
|
||||||
|
|
||||||
# Middleware is a framework of hooks into Django's request/response processing.
|
|
||||||
MIDDLEWARE: list[str] = [
|
|
||||||
"django.middleware.security.SecurityMiddleware",
|
|
||||||
"whitenoise.middleware.WhiteNoiseMiddleware",
|
|
||||||
"debug_toolbar.middleware.DebugToolbarMiddleware",
|
|
||||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
||||||
"django.middleware.cache.UpdateCacheMiddleware",
|
|
||||||
"django.middleware.common.CommonMiddleware",
|
|
||||||
"django.middleware.cache.FetchFromCacheMiddleware",
|
|
||||||
"django.middleware.csrf.CsrfViewMiddleware",
|
|
||||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
||||||
"django.contrib.messages.middleware.MessageMiddleware",
|
|
||||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
||||||
]
|
|
||||||
|
|
||||||
# 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",
|
|
||||||
],
|
|
||||||
"loaders": [
|
|
||||||
(
|
|
||||||
"django.template.loaders.cached.Loader",
|
|
||||||
[
|
|
||||||
"django.template.loaders.filesystem.Loader",
|
|
||||||
"django.template.loaders.app_directories.Loader",
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
# A dictionary containing the settings for how we should connect to our PostgreSQL database.
|
|
||||||
DATABASES: dict[str, dict[str, str]] = {
|
|
||||||
"default": {
|
|
||||||
"ENGINE": "django.db.backends.postgresql",
|
|
||||||
"NAME": "feedvault",
|
|
||||||
"USER": os.getenv(key="PGUSER", default=""),
|
|
||||||
"PASSWORD": os.getenv(key="PGPASSWORD", default=""),
|
|
||||||
"HOST": os.getenv(key="PGHOST", default=""),
|
|
||||||
"PORT": os.getenv(key="PGPORT", default="5432"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
# The absolute path to the directory where 'python manage.py collectstatic' will copy static files for deployment
|
|
||||||
STATIC_ROOT: Path = BASE_DIR / "staticfiles"
|
|
||||||
STATICFILES_DIRS: list[Path] = [BASE_DIR / "static"]
|
|
||||||
|
|
||||||
# Use WhiteNoise to serve static files. https://whitenoise.readthedocs.io/en/latest/django.html
|
|
||||||
STORAGES: dict[str, dict[str, str]] = {
|
|
||||||
"staticfiles": {"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage"},
|
|
||||||
}
|
|
||||||
|
|
||||||
# Our site ID
|
|
||||||
SITE_ID = 1
|
|
||||||
|
|
||||||
if not DEBUG:
|
|
||||||
CACHES: dict[str, dict[str, str]] = {
|
|
||||||
"default": {
|
|
||||||
"BACKEND": "django.core.cache.backends.db.DatabaseCache",
|
|
||||||
"LOCATION": "feedvault_cache", # The cache table will be created in the default database
|
|
||||||
},
|
|
||||||
}
|
|
||||||
CACHE_MIDDLEWARE_ALIAS = "default"
|
|
||||||
CACHE_MIDDLEWARE_SECONDS = 600 # 10 minutes
|
|
||||||
CACHE_MIDDLEWARE_KEY_PREFIX = "feedvault"
|
|
||||||
else:
|
|
||||||
CACHES: dict[str, dict[str, str]] = {
|
|
||||||
"default": {
|
|
||||||
"BACKEND": "django.core.cache.backends.dummy.DummyCache",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LOGGING = {
|
|
||||||
"version": 1,
|
|
||||||
"disable_existing_loggers": False,
|
|
||||||
"handlers": {
|
|
||||||
"console": {
|
|
||||||
"class": "logging.StreamHandler",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"handlers": ["console"],
|
|
||||||
"level": "DEBUG",
|
|
||||||
},
|
|
||||||
"loggers": {
|
|
||||||
"django": {
|
|
||||||
"handlers": ["console"],
|
|
||||||
"level": os.getenv("DJANGO_LOG_LEVEL", "INFO"),
|
|
||||||
"propagate": False,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
"""URL configuration for feedvault project.
|
|
||||||
|
|
||||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
|
||||||
https://docs.djangoproject.com/en/5.0/topics/http/urls/
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from django.contrib import admin
|
|
||||||
from django.urls import URLResolver, include, path
|
|
||||||
|
|
||||||
urlpatterns: list[URLResolver] = [
|
|
||||||
path(route="admin/", view=admin.site.urls),
|
|
||||||
path(route="__debug__/", view=include(arg="debug_toolbar.urls")),
|
|
||||||
path(route="", view=include(arg="feeds.urls")),
|
|
||||||
]
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
"""WSGI config for FeedVault project.
|
|
||||||
|
|
||||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
|
|
||||||
"""
|
|
||||||
|
|
||||||
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()
|
|
||||||
3
go.mod
Normal file
3
go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
module github.com/TheLovinator1/FeedVault
|
||||||
|
|
||||||
|
go 1.21.6
|
||||||
20
manage.py
20
manage.py
|
|
@ -1,20 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
"""Django's command-line utility for administrative tasks."""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
"""Run administrative tasks."""
|
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "feedvault.settings")
|
|
||||||
try:
|
|
||||||
from django.core.management import execute_from_command_line # noqa: PLC0415
|
|
||||||
except ImportError as exc:
|
|
||||||
msg = "Couldn't import Django. Have you run `poetry install` or `poetry shell`?"
|
|
||||||
raise ImportError(msg) from exc
|
|
||||||
execute_from_command_line(sys.argv)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
1518
poetry.lock
generated
1518
poetry.lock
generated
|
|
@ -1,1518 +0,0 @@
|
||||||
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "annotated-types"
|
|
||||||
version = "0.6.0"
|
|
||||||
description = "Reusable constraint types to use with typing.Annotated"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"},
|
|
||||||
{file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "asgiref"
|
|
||||||
version = "3.7.2"
|
|
||||||
description = "ASGI specs, helper code, and adapters"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"},
|
|
||||||
{file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
|
|
||||||
|
|
||||||
[[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]]
|
|
||||||
name = "certifi"
|
|
||||||
version = "2024.2.2"
|
|
||||||
description = "Python package for providing Mozilla's CA Bundle."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"},
|
|
||||||
{file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cffi"
|
|
||||||
version = "1.16.0"
|
|
||||||
description = "Foreign Function Interface for Python calling C code."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"},
|
|
||||||
{file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"},
|
|
||||||
{file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"},
|
|
||||||
{file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"},
|
|
||||||
{file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"},
|
|
||||||
{file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"},
|
|
||||||
{file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"},
|
|
||||||
{file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"},
|
|
||||||
{file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"},
|
|
||||||
{file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"},
|
|
||||||
{file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"},
|
|
||||||
{file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"},
|
|
||||||
{file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"},
|
|
||||||
{file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"},
|
|
||||||
{file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"},
|
|
||||||
{file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"},
|
|
||||||
{file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"},
|
|
||||||
{file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"},
|
|
||||||
{file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"},
|
|
||||||
{file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"},
|
|
||||||
{file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"},
|
|
||||||
{file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"},
|
|
||||||
{file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"},
|
|
||||||
{file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"},
|
|
||||||
{file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"},
|
|
||||||
{file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"},
|
|
||||||
{file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"},
|
|
||||||
{file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"},
|
|
||||||
{file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"},
|
|
||||||
{file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"},
|
|
||||||
{file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"},
|
|
||||||
{file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"},
|
|
||||||
{file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"},
|
|
||||||
{file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"},
|
|
||||||
{file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"},
|
|
||||||
{file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"},
|
|
||||||
{file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"},
|
|
||||||
{file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"},
|
|
||||||
{file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"},
|
|
||||||
{file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"},
|
|
||||||
{file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"},
|
|
||||||
{file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"},
|
|
||||||
{file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"},
|
|
||||||
{file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"},
|
|
||||||
{file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"},
|
|
||||||
{file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"},
|
|
||||||
{file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"},
|
|
||||||
{file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"},
|
|
||||||
{file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"},
|
|
||||||
{file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"},
|
|
||||||
{file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"},
|
|
||||||
{file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
pycparser = "*"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfgv"
|
|
||||||
version = "3.4.0"
|
|
||||||
description = "Validate configuration and produce human readable error messages."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
|
|
||||||
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "charset-normalizer"
|
|
||||||
version = "3.3.2"
|
|
||||||
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7.0"
|
|
||||||
files = [
|
|
||||||
{file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
|
|
||||||
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "click"
|
|
||||||
version = "8.1.7"
|
|
||||||
description = "Composable command line interface toolkit"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
|
|
||||||
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "colorama"
|
|
||||||
version = "0.4.6"
|
|
||||||
description = "Cross-platform colored terminal text."
|
|
||||||
optional = false
|
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
|
||||||
files = [
|
|
||||||
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
|
||||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cryptography"
|
|
||||||
version = "42.0.2"
|
|
||||||
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "cryptography-42.0.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:701171f825dcab90969596ce2af253143b93b08f1a716d4b2a9d2db5084ef7be"},
|
|
||||||
{file = "cryptography-42.0.2-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:61321672b3ac7aade25c40449ccedbc6db72c7f5f0fdf34def5e2f8b51ca530d"},
|
|
||||||
{file = "cryptography-42.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea2c3ffb662fec8bbbfce5602e2c159ff097a4631d96235fcf0fb00e59e3ece4"},
|
|
||||||
{file = "cryptography-42.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b15c678f27d66d247132cbf13df2f75255627bcc9b6a570f7d2fd08e8c081d2"},
|
|
||||||
{file = "cryptography-42.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8e88bb9eafbf6a4014d55fb222e7360eef53e613215085e65a13290577394529"},
|
|
||||||
{file = "cryptography-42.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a047682d324ba56e61b7ea7c7299d51e61fd3bca7dad2ccc39b72bd0118d60a1"},
|
|
||||||
{file = "cryptography-42.0.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:36d4b7c4be6411f58f60d9ce555a73df8406d484ba12a63549c88bd64f7967f1"},
|
|
||||||
{file = "cryptography-42.0.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a00aee5d1b6c20620161984f8ab2ab69134466c51f58c052c11b076715e72929"},
|
|
||||||
{file = "cryptography-42.0.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b97fe7d7991c25e6a31e5d5e795986b18fbbb3107b873d5f3ae6dc9a103278e9"},
|
|
||||||
{file = "cryptography-42.0.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5fa82a26f92871eca593b53359c12ad7949772462f887c35edaf36f87953c0e2"},
|
|
||||||
{file = "cryptography-42.0.2-cp37-abi3-win32.whl", hash = "sha256:4b063d3413f853e056161eb0c7724822a9740ad3caa24b8424d776cebf98e7ee"},
|
|
||||||
{file = "cryptography-42.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:841ec8af7a8491ac76ec5a9522226e287187a3107e12b7d686ad354bb78facee"},
|
|
||||||
{file = "cryptography-42.0.2-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:55d1580e2d7e17f45d19d3b12098e352f3a37fe86d380bf45846ef257054b242"},
|
|
||||||
{file = "cryptography-42.0.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28cb2c41f131a5758d6ba6a0504150d644054fd9f3203a1e8e8d7ac3aea7f73a"},
|
|
||||||
{file = "cryptography-42.0.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9097a208875fc7bbeb1286d0125d90bdfed961f61f214d3f5be62cd4ed8a446"},
|
|
||||||
{file = "cryptography-42.0.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:44c95c0e96b3cb628e8452ec060413a49002a247b2b9938989e23a2c8291fc90"},
|
|
||||||
{file = "cryptography-42.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2f9f14185962e6a04ab32d1abe34eae8a9001569ee4edb64d2304bf0d65c53f3"},
|
|
||||||
{file = "cryptography-42.0.2-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:09a77e5b2e8ca732a19a90c5bca2d124621a1edb5438c5daa2d2738bfeb02589"},
|
|
||||||
{file = "cryptography-42.0.2-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad28cff53f60d99a928dfcf1e861e0b2ceb2bc1f08a074fdd601b314e1cc9e0a"},
|
|
||||||
{file = "cryptography-42.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:130c0f77022b2b9c99d8cebcdd834d81705f61c68e91ddd614ce74c657f8b3ea"},
|
|
||||||
{file = "cryptography-42.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:fa3dec4ba8fb6e662770b74f62f1a0c7d4e37e25b58b2bf2c1be4c95372b4a33"},
|
|
||||||
{file = "cryptography-42.0.2-cp39-abi3-win32.whl", hash = "sha256:3dbd37e14ce795b4af61b89b037d4bc157f2cb23e676fa16932185a04dfbf635"},
|
|
||||||
{file = "cryptography-42.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:8a06641fb07d4e8f6c7dda4fc3f8871d327803ab6542e33831c7ccfdcb4d0ad6"},
|
|
||||||
{file = "cryptography-42.0.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:087887e55e0b9c8724cf05361357875adb5c20dec27e5816b653492980d20380"},
|
|
||||||
{file = "cryptography-42.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a7ef8dd0bf2e1d0a27042b231a3baac6883cdd5557036f5e8df7139255feaac6"},
|
|
||||||
{file = "cryptography-42.0.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4383b47f45b14459cab66048d384614019965ba6c1a1a141f11b5a551cace1b2"},
|
|
||||||
{file = "cryptography-42.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:fbeb725c9dc799a574518109336acccaf1303c30d45c075c665c0793c2f79a7f"},
|
|
||||||
{file = "cryptography-42.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:320948ab49883557a256eab46149df79435a22d2fefd6a66fe6946f1b9d9d008"},
|
|
||||||
{file = "cryptography-42.0.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5ef9bc3d046ce83c4bbf4c25e1e0547b9c441c01d30922d812e887dc5f125c12"},
|
|
||||||
{file = "cryptography-42.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:52ed9ebf8ac602385126c9a2fe951db36f2cb0c2538d22971487f89d0de4065a"},
|
|
||||||
{file = "cryptography-42.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:141e2aa5ba100d3788c0ad7919b288f89d1fe015878b9659b307c9ef867d3a65"},
|
|
||||||
{file = "cryptography-42.0.2.tar.gz", hash = "sha256:e0ec52ba3c7f1b7d813cd52649a5b3ef1fc0d433219dc8c93827c57eab6cf888"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"]
|
|
||||||
docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"]
|
|
||||||
nox = ["nox"]
|
|
||||||
pep8test = ["check-sdist", "click", "mypy", "ruff"]
|
|
||||||
sdist = ["build"]
|
|
||||||
ssh = ["bcrypt (>=3.1.5)"]
|
|
||||||
test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]
|
|
||||||
test-randomorder = ["pytest-randomly"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cssbeautifier"
|
|
||||||
version = "1.14.11"
|
|
||||||
description = "CSS unobfuscator and beautifier."
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "cssbeautifier-1.14.11.tar.gz", hash = "sha256:40544c2b62bbcb64caa5e7f37a02df95654e5ce1bcacadac4ca1f3dc89c31513"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
editorconfig = ">=0.12.2"
|
|
||||||
jsbeautifier = "*"
|
|
||||||
six = ">=1.13.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "defusedxml"
|
|
||||||
version = "0.7.1"
|
|
||||||
description = "XML bomb protection for Python stdlib modules"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
|
||||||
files = [
|
|
||||||
{file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"},
|
|
||||||
{file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "distlib"
|
|
||||||
version = "0.3.8"
|
|
||||||
description = "Distribution utilities"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"},
|
|
||||||
{file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "django"
|
|
||||||
version = "5.0.1"
|
|
||||||
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.1-py3-none-any.whl", hash = "sha256:f47a37a90b9bbe2c8ec360235192c7fddfdc832206fcf618bb849b39256affc1"},
|
|
||||||
{file = "Django-5.0.1.tar.gz", hash = "sha256:8c8659665bc6e3a44fefe1ab0a291e5a3fb3979f9a8230be29de975e57e8f854"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[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-allauth"
|
|
||||||
version = "0.60.1"
|
|
||||||
description = "Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "django-allauth-0.60.1.tar.gz", hash = "sha256:97b0f9a1807ca812d84204328cd55c273ce4ec1835f822d8fd1a28178708f192"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
Django = ">=3.2"
|
|
||||||
pyjwt = {version = ">=1.7", extras = ["crypto"]}
|
|
||||||
python3-openid = ">=3.0.8"
|
|
||||||
requests = ">=2.0.0"
|
|
||||||
requests-oauthlib = ">=0.3.0"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
mfa = ["qrcode (>=7.0.0)"]
|
|
||||||
saml = ["python3-saml (>=1.15.0,<2.0.0)"]
|
|
||||||
|
|
||||||
[[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-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 = "djlint"
|
|
||||||
version = "1.34.1"
|
|
||||||
description = "HTML Template Linter and Formatter"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8.0,<4.0.0"
|
|
||||||
files = [
|
|
||||||
{file = "djlint-1.34.1-py3-none-any.whl", hash = "sha256:96ff1c464fb6f061130ebc88663a2ea524d7ec51f4b56221a2b3f0320a3cfce8"},
|
|
||||||
{file = "djlint-1.34.1.tar.gz", hash = "sha256:db93fa008d19eaadb0454edf1704931d14469d48508daba2df9941111f408346"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
click = ">=8.0.1,<9.0.0"
|
|
||||||
colorama = ">=0.4.4,<0.5.0"
|
|
||||||
cssbeautifier = ">=1.14.4,<2.0.0"
|
|
||||||
html-tag-names = ">=0.1.2,<0.2.0"
|
|
||||||
html-void-elements = ">=0.1.0,<0.2.0"
|
|
||||||
jsbeautifier = ">=1.14.4,<2.0.0"
|
|
||||||
json5 = ">=0.9.11,<0.10.0"
|
|
||||||
pathspec = ">=0.12.0,<0.13.0"
|
|
||||||
PyYAML = ">=6.0,<7.0"
|
|
||||||
regex = ">=2023.0.0,<2024.0.0"
|
|
||||||
tqdm = ">=4.62.2,<5.0.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "editorconfig"
|
|
||||||
version = "0.12.3"
|
|
||||||
description = "EditorConfig File Locator and Interpreter for Python"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "EditorConfig-0.12.3-py3-none-any.whl", hash = "sha256:6b0851425aa875b08b16789ee0eeadbd4ab59666e9ebe728e526314c4a2e52c1"},
|
|
||||||
{file = "EditorConfig-0.12.3.tar.gz", hash = "sha256:57f8ce78afcba15c8b18d46b5170848c88d56fd38f05c2ec60dbbfcb8996e89e"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "feedparser"
|
|
||||||
version = "6.0.11"
|
|
||||||
description = "Universal feed parser, handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "feedparser-6.0.11-py3-none-any.whl", hash = "sha256:0be7ee7b395572b19ebeb1d6aafb0028dee11169f1c934e0ed67d54992f4ad45"},
|
|
||||||
{file = "feedparser-6.0.11.tar.gz", hash = "sha256:c9d0407b64c6f2a065d0ebb292c2b35c01050cc0dc33757461aaabdc4c4184d5"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
sgmllib3k = "*"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "filelock"
|
|
||||||
version = "3.13.1"
|
|
||||||
description = "A platform independent file lock."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"},
|
|
||||||
{file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"]
|
|
||||||
testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"]
|
|
||||||
typing = ["typing-extensions (>=4.8)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gunicorn"
|
|
||||||
version = "21.2.0"
|
|
||||||
description = "WSGI HTTP Server for UNIX"
|
|
||||||
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 = "html-tag-names"
|
|
||||||
version = "0.1.2"
|
|
||||||
description = "List of known HTML tag names"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7,<4.0"
|
|
||||||
files = [
|
|
||||||
{file = "html-tag-names-0.1.2.tar.gz", hash = "sha256:04924aca48770f36b5a41c27e4d917062507be05118acb0ba869c97389084297"},
|
|
||||||
{file = "html_tag_names-0.1.2-py3-none-any.whl", hash = "sha256:eeb69ef21078486b615241f0393a72b41352c5219ee648e7c61f5632d26f0420"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "html-void-elements"
|
|
||||||
version = "0.1.0"
|
|
||||||
description = "List of HTML void tag names."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7,<4.0"
|
|
||||||
files = [
|
|
||||||
{file = "html-void-elements-0.1.0.tar.gz", hash = "sha256:931b88f84cd606fee0b582c28fcd00e41d7149421fb673e1e1abd2f0c4f231f0"},
|
|
||||||
{file = "html_void_elements-0.1.0-py3-none-any.whl", hash = "sha256:784cf39db03cdeb017320d9301009f8f3480f9d7b254d0974272e80e0cb5e0d2"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "identify"
|
|
||||||
version = "2.5.33"
|
|
||||||
description = "File identification library for Python"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"},
|
|
||||||
{file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
license = ["ukkonen"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "idna"
|
|
||||||
version = "3.6"
|
|
||||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.5"
|
|
||||||
files = [
|
|
||||||
{file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"},
|
|
||||||
{file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "jsbeautifier"
|
|
||||||
version = "1.14.11"
|
|
||||||
description = "JavaScript unobfuscator and beautifier."
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "jsbeautifier-1.14.11.tar.gz", hash = "sha256:6b632581ea60dd1c133cd25a48ad187b4b91f526623c4b0fb5443ef805250505"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
editorconfig = ">=0.12.2"
|
|
||||||
six = ">=1.13.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "json5"
|
|
||||||
version = "0.9.14"
|
|
||||||
description = "A Python implementation of the JSON5 data format."
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "json5-0.9.14-py2.py3-none-any.whl", hash = "sha256:740c7f1b9e584a468dbb2939d8d458db3427f2c93ae2139d05f47e453eae964f"},
|
|
||||||
{file = "json5-0.9.14.tar.gz", hash = "sha256:9ed66c3a6ca3510a976a9ef9b8c0787de24802724ab1860bc0153c7fdd589b02"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
dev = ["hypothesis"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "listparser"
|
|
||||||
version = "0.19"
|
|
||||||
description = "Parse OPML subscription lists"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7,<4.0"
|
|
||||||
files = [
|
|
||||||
{file = "listparser-0.19-py3-none-any.whl", hash = "sha256:c3857a9e5e5342207a556ba72e5c030782971fbe587e7afc2a75b2d7c0fa5a5c"},
|
|
||||||
{file = "listparser-0.19.tar.gz", hash = "sha256:5aa23ae017a22e36c50ca5259a690328dd524527977d8c094ae0857887002805"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
lxml = {version = ">=4.6.2,<5.0.0", optional = true, markers = "extra == \"lxml\""}
|
|
||||||
requests = {version = ">=2.25.1,<3.0.0", optional = true, markers = "extra == \"http\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
http = ["requests (>=2.25.1,<3.0.0)"]
|
|
||||||
lxml = ["lxml (>=4.6.2,<5.0.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lxml"
|
|
||||||
version = "4.9.4"
|
|
||||||
description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*"
|
|
||||||
files = [
|
|
||||||
{file = "lxml-4.9.4-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e214025e23db238805a600f1f37bf9f9a15413c7bf5f9d6ae194f84980c78722"},
|
|
||||||
{file = "lxml-4.9.4-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ec53a09aee61d45e7dbe7e91252ff0491b6b5fee3d85b2d45b173d8ab453efc1"},
|
|
||||||
{file = "lxml-4.9.4-cp27-cp27m-win32.whl", hash = "sha256:7d1d6c9e74c70ddf524e3c09d9dc0522aba9370708c2cb58680ea40174800013"},
|
|
||||||
{file = "lxml-4.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:cb53669442895763e61df5c995f0e8361b61662f26c1b04ee82899c2789c8f69"},
|
|
||||||
{file = "lxml-4.9.4-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:647bfe88b1997d7ae8d45dabc7c868d8cb0c8412a6e730a7651050b8c7289cf2"},
|
|
||||||
{file = "lxml-4.9.4-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4d973729ce04784906a19108054e1fd476bc85279a403ea1a72fdb051c76fa48"},
|
|
||||||
{file = "lxml-4.9.4-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:056a17eaaf3da87a05523472ae84246f87ac2f29a53306466c22e60282e54ff8"},
|
|
||||||
{file = "lxml-4.9.4-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:aaa5c173a26960fe67daa69aa93d6d6a1cd714a6eb13802d4e4bd1d24a530644"},
|
|
||||||
{file = "lxml-4.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:647459b23594f370c1c01768edaa0ba0959afc39caeeb793b43158bb9bb6a663"},
|
|
||||||
{file = "lxml-4.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:bdd9abccd0927673cffe601d2c6cdad1c9321bf3437a2f507d6b037ef91ea307"},
|
|
||||||
{file = "lxml-4.9.4-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:00e91573183ad273e242db5585b52670eddf92bacad095ce25c1e682da14ed91"},
|
|
||||||
{file = "lxml-4.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a602ed9bd2c7d85bd58592c28e101bd9ff9c718fbde06545a70945ffd5d11868"},
|
|
||||||
{file = "lxml-4.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:de362ac8bc962408ad8fae28f3967ce1a262b5d63ab8cefb42662566737f1dc7"},
|
|
||||||
{file = "lxml-4.9.4-cp310-cp310-win32.whl", hash = "sha256:33714fcf5af4ff7e70a49731a7cc8fd9ce910b9ac194f66eaa18c3cc0a4c02be"},
|
|
||||||
{file = "lxml-4.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:d3caa09e613ece43ac292fbed513a4bce170681a447d25ffcbc1b647d45a39c5"},
|
|
||||||
{file = "lxml-4.9.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:359a8b09d712df27849e0bcb62c6a3404e780b274b0b7e4c39a88826d1926c28"},
|
|
||||||
{file = "lxml-4.9.4-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:43498ea734ccdfb92e1886dfedaebeb81178a241d39a79d5351ba2b671bff2b2"},
|
|
||||||
{file = "lxml-4.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4855161013dfb2b762e02b3f4d4a21cc7c6aec13c69e3bffbf5022b3e708dd97"},
|
|
||||||
{file = "lxml-4.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c71b5b860c5215fdbaa56f715bc218e45a98477f816b46cfde4a84d25b13274e"},
|
|
||||||
{file = "lxml-4.9.4-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9a2b5915c333e4364367140443b59f09feae42184459b913f0f41b9fed55794a"},
|
|
||||||
{file = "lxml-4.9.4-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d82411dbf4d3127b6cde7da0f9373e37ad3a43e89ef374965465928f01c2b979"},
|
|
||||||
{file = "lxml-4.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:273473d34462ae6e97c0f4e517bd1bf9588aa67a1d47d93f760a1282640e24ac"},
|
|
||||||
{file = "lxml-4.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:389d2b2e543b27962990ab529ac6720c3dded588cc6d0f6557eec153305a3622"},
|
|
||||||
{file = "lxml-4.9.4-cp311-cp311-win32.whl", hash = "sha256:8aecb5a7f6f7f8fe9cac0bcadd39efaca8bbf8d1bf242e9f175cbe4c925116c3"},
|
|
||||||
{file = "lxml-4.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:c7721a3ef41591341388bb2265395ce522aba52f969d33dacd822da8f018aff8"},
|
|
||||||
{file = "lxml-4.9.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:dbcb2dc07308453db428a95a4d03259bd8caea97d7f0776842299f2d00c72fc8"},
|
|
||||||
{file = "lxml-4.9.4-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:01bf1df1db327e748dcb152d17389cf6d0a8c5d533ef9bab781e9d5037619229"},
|
|
||||||
{file = "lxml-4.9.4-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e8f9f93a23634cfafbad6e46ad7d09e0f4a25a2400e4a64b1b7b7c0fbaa06d9d"},
|
|
||||||
{file = "lxml-4.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3f3f00a9061605725df1816f5713d10cd94636347ed651abdbc75828df302b20"},
|
|
||||||
{file = "lxml-4.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:953dd5481bd6252bd480d6ec431f61d7d87fdcbbb71b0d2bdcfc6ae00bb6fb10"},
|
|
||||||
{file = "lxml-4.9.4-cp312-cp312-win32.whl", hash = "sha256:266f655d1baff9c47b52f529b5f6bec33f66042f65f7c56adde3fcf2ed62ae8b"},
|
|
||||||
{file = "lxml-4.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:f1faee2a831fe249e1bae9cbc68d3cd8a30f7e37851deee4d7962b17c410dd56"},
|
|
||||||
{file = "lxml-4.9.4-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:23d891e5bdc12e2e506e7d225d6aa929e0a0368c9916c1fddefab88166e98b20"},
|
|
||||||
{file = "lxml-4.9.4-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e96a1788f24d03e8d61679f9881a883ecdf9c445a38f9ae3f3f193ab6c591c66"},
|
|
||||||
{file = "lxml-4.9.4-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:5557461f83bb7cc718bc9ee1f7156d50e31747e5b38d79cf40f79ab1447afd2d"},
|
|
||||||
{file = "lxml-4.9.4-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:fdb325b7fba1e2c40b9b1db407f85642e32404131c08480dd652110fc908561b"},
|
|
||||||
{file = "lxml-4.9.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d74d4a3c4b8f7a1f676cedf8e84bcc57705a6d7925e6daef7a1e54ae543a197"},
|
|
||||||
{file = "lxml-4.9.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ac7674d1638df129d9cb4503d20ffc3922bd463c865ef3cb412f2c926108e9a4"},
|
|
||||||
{file = "lxml-4.9.4-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:ddd92e18b783aeb86ad2132d84a4b795fc5ec612e3545c1b687e7747e66e2b53"},
|
|
||||||
{file = "lxml-4.9.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bd9ac6e44f2db368ef8986f3989a4cad3de4cd55dbdda536e253000c801bcc7"},
|
|
||||||
{file = "lxml-4.9.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:bc354b1393dce46026ab13075f77b30e40b61b1a53e852e99d3cc5dd1af4bc85"},
|
|
||||||
{file = "lxml-4.9.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f836f39678cb47c9541f04d8ed4545719dc31ad850bf1832d6b4171e30d65d23"},
|
|
||||||
{file = "lxml-4.9.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:9c131447768ed7bc05a02553d939e7f0e807e533441901dd504e217b76307745"},
|
|
||||||
{file = "lxml-4.9.4-cp36-cp36m-win32.whl", hash = "sha256:bafa65e3acae612a7799ada439bd202403414ebe23f52e5b17f6ffc2eb98c2be"},
|
|
||||||
{file = "lxml-4.9.4-cp36-cp36m-win_amd64.whl", hash = "sha256:6197c3f3c0b960ad033b9b7d611db11285bb461fc6b802c1dd50d04ad715c225"},
|
|
||||||
{file = "lxml-4.9.4-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:7b378847a09d6bd46047f5f3599cdc64fcb4cc5a5a2dd0a2af610361fbe77b16"},
|
|
||||||
{file = "lxml-4.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:1343df4e2e6e51182aad12162b23b0a4b3fd77f17527a78c53f0f23573663545"},
|
|
||||||
{file = "lxml-4.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6dbdacf5752fbd78ccdb434698230c4f0f95df7dd956d5f205b5ed6911a1367c"},
|
|
||||||
{file = "lxml-4.9.4-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:506becdf2ecaebaf7f7995f776394fcc8bd8a78022772de66677c84fb02dd33d"},
|
|
||||||
{file = "lxml-4.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca8e44b5ba3edb682ea4e6185b49661fc22b230cf811b9c13963c9f982d1d964"},
|
|
||||||
{file = "lxml-4.9.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9d9d5726474cbbef279fd709008f91a49c4f758bec9c062dfbba88eab00e3ff9"},
|
|
||||||
{file = "lxml-4.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:bbdd69e20fe2943b51e2841fc1e6a3c1de460d630f65bde12452d8c97209464d"},
|
|
||||||
{file = "lxml-4.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8671622256a0859f5089cbe0ce4693c2af407bc053dcc99aadff7f5310b4aa02"},
|
|
||||||
{file = "lxml-4.9.4-cp37-cp37m-win32.whl", hash = "sha256:dd4fda67f5faaef4f9ee5383435048ee3e11ad996901225ad7615bc92245bc8e"},
|
|
||||||
{file = "lxml-4.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6bee9c2e501d835f91460b2c904bc359f8433e96799f5c2ff20feebd9bb1e590"},
|
|
||||||
{file = "lxml-4.9.4-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:1f10f250430a4caf84115b1e0f23f3615566ca2369d1962f82bef40dd99cd81a"},
|
|
||||||
{file = "lxml-4.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:3b505f2bbff50d261176e67be24e8909e54b5d9d08b12d4946344066d66b3e43"},
|
|
||||||
{file = "lxml-4.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:1449f9451cd53e0fd0a7ec2ff5ede4686add13ac7a7bfa6988ff6d75cff3ebe2"},
|
|
||||||
{file = "lxml-4.9.4-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:4ece9cca4cd1c8ba889bfa67eae7f21d0d1a2e715b4d5045395113361e8c533d"},
|
|
||||||
{file = "lxml-4.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59bb5979f9941c61e907ee571732219fa4774d5a18f3fa5ff2df963f5dfaa6bc"},
|
|
||||||
{file = "lxml-4.9.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b1980dbcaad634fe78e710c8587383e6e3f61dbe146bcbfd13a9c8ab2d7b1192"},
|
|
||||||
{file = "lxml-4.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9ae6c3363261021144121427b1552b29e7b59de9d6a75bf51e03bc072efb3c37"},
|
|
||||||
{file = "lxml-4.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bcee502c649fa6351b44bb014b98c09cb00982a475a1912a9881ca28ab4f9cd9"},
|
|
||||||
{file = "lxml-4.9.4-cp38-cp38-win32.whl", hash = "sha256:a8edae5253efa75c2fc79a90068fe540b197d1c7ab5803b800fccfe240eed33c"},
|
|
||||||
{file = "lxml-4.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:701847a7aaefef121c5c0d855b2affa5f9bd45196ef00266724a80e439220e46"},
|
|
||||||
{file = "lxml-4.9.4-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:f610d980e3fccf4394ab3806de6065682982f3d27c12d4ce3ee46a8183d64a6a"},
|
|
||||||
{file = "lxml-4.9.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:aa9b5abd07f71b081a33115d9758ef6077924082055005808f68feccb27616bd"},
|
|
||||||
{file = "lxml-4.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:365005e8b0718ea6d64b374423e870648ab47c3a905356ab6e5a5ff03962b9a9"},
|
|
||||||
{file = "lxml-4.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:16b9ec51cc2feab009e800f2c6327338d6ee4e752c76e95a35c4465e80390ccd"},
|
|
||||||
{file = "lxml-4.9.4-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:a905affe76f1802edcac554e3ccf68188bea16546071d7583fb1b693f9cf756b"},
|
|
||||||
{file = "lxml-4.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fd814847901df6e8de13ce69b84c31fc9b3fb591224d6762d0b256d510cbf382"},
|
|
||||||
{file = "lxml-4.9.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:91bbf398ac8bb7d65a5a52127407c05f75a18d7015a270fdd94bbcb04e65d573"},
|
|
||||||
{file = "lxml-4.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f99768232f036b4776ce419d3244a04fe83784bce871b16d2c2e984c7fcea847"},
|
|
||||||
{file = "lxml-4.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bb5bd6212eb0edfd1e8f254585290ea1dadc3687dd8fd5e2fd9a87c31915cdab"},
|
|
||||||
{file = "lxml-4.9.4-cp39-cp39-win32.whl", hash = "sha256:88f7c383071981c74ec1998ba9b437659e4fd02a3c4a4d3efc16774eb108d0ec"},
|
|
||||||
{file = "lxml-4.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:936e8880cc00f839aa4173f94466a8406a96ddce814651075f95837316369899"},
|
|
||||||
{file = "lxml-4.9.4-pp310-pypy310_pp73-macosx_11_0_x86_64.whl", hash = "sha256:f6c35b2f87c004270fa2e703b872fcc984d714d430b305145c39d53074e1ffe0"},
|
|
||||||
{file = "lxml-4.9.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:606d445feeb0856c2b424405236a01c71af7c97e5fe42fbc778634faef2b47e4"},
|
|
||||||
{file = "lxml-4.9.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a1bdcbebd4e13446a14de4dd1825f1e778e099f17f79718b4aeaf2403624b0f7"},
|
|
||||||
{file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0a08c89b23117049ba171bf51d2f9c5f3abf507d65d016d6e0fa2f37e18c0fc5"},
|
|
||||||
{file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:232fd30903d3123be4c435fb5159938c6225ee8607b635a4d3fca847003134ba"},
|
|
||||||
{file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:231142459d32779b209aa4b4d460b175cadd604fed856f25c1571a9d78114771"},
|
|
||||||
{file = "lxml-4.9.4-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:520486f27f1d4ce9654154b4494cf9307b495527f3a2908ad4cb48e4f7ed7ef7"},
|
|
||||||
{file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:562778586949be7e0d7435fcb24aca4810913771f845d99145a6cee64d5b67ca"},
|
|
||||||
{file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a9e7c6d89c77bb2770c9491d988f26a4b161d05c8ca58f63fb1f1b6b9a74be45"},
|
|
||||||
{file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:786d6b57026e7e04d184313c1359ac3d68002c33e4b1042ca58c362f1d09ff58"},
|
|
||||||
{file = "lxml-4.9.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95ae6c5a196e2f239150aa4a479967351df7f44800c93e5a975ec726fef005e2"},
|
|
||||||
{file = "lxml-4.9.4-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:9b556596c49fa1232b0fff4b0e69b9d4083a502e60e404b44341e2f8fb7187f5"},
|
|
||||||
{file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:cc02c06e9e320869d7d1bd323df6dd4281e78ac2e7f8526835d3d48c69060683"},
|
|
||||||
{file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:857d6565f9aa3464764c2cb6a2e3c2e75e1970e877c188f4aeae45954a314e0c"},
|
|
||||||
{file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c42ae7e010d7d6bc51875d768110c10e8a59494855c3d4c348b068f5fb81fdcd"},
|
|
||||||
{file = "lxml-4.9.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f10250bb190fb0742e3e1958dd5c100524c2cc5096c67c8da51233f7448dc137"},
|
|
||||||
{file = "lxml-4.9.4.tar.gz", hash = "sha256:b1541e50b78e15fa06a2670157a1962ef06591d4c998b998047fff5e3236880e"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
cssselect = ["cssselect (>=0.7)"]
|
|
||||||
html5 = ["html5lib"]
|
|
||||||
htmlsoup = ["BeautifulSoup4"]
|
|
||||||
source = ["Cython (==0.29.37)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nodeenv"
|
|
||||||
version = "1.8.0"
|
|
||||||
description = "Node.js virtual environment builder"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
|
|
||||||
files = [
|
|
||||||
{file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"},
|
|
||||||
{file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
setuptools = "*"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "oauthlib"
|
|
||||||
version = "3.2.2"
|
|
||||||
description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"},
|
|
||||||
{file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
rsa = ["cryptography (>=3.0.0)"]
|
|
||||||
signals = ["blinker (>=1.4.0)"]
|
|
||||||
signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "packaging"
|
|
||||||
version = "23.2"
|
|
||||||
description = "Core utilities for Python packages"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
|
|
||||||
{file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pathspec"
|
|
||||||
version = "0.12.1"
|
|
||||||
description = "Utility library for gitignore style pattern matching of file paths."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
|
|
||||||
{file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "platformdirs"
|
|
||||||
version = "4.2.0"
|
|
||||||
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"},
|
|
||||||
{file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
|
|
||||||
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pre-commit"
|
|
||||||
version = "3.6.0"
|
|
||||||
description = "A framework for managing and maintaining multi-language pre-commit hooks."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.9"
|
|
||||||
files = [
|
|
||||||
{file = "pre_commit-3.6.0-py2.py3-none-any.whl", hash = "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376"},
|
|
||||||
{file = "pre_commit-3.6.0.tar.gz", hash = "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
cfgv = ">=2.0.0"
|
|
||||||
identify = ">=1.0.0"
|
|
||||||
nodeenv = ">=0.11.1"
|
|
||||||
pyyaml = ">=5.1"
|
|
||||||
virtualenv = ">=20.10.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "psycopg"
|
|
||||||
version = "3.1.17"
|
|
||||||
description = "PostgreSQL database adapter for Python"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "psycopg-3.1.17-py3-none-any.whl", hash = "sha256:96b7b13af6d5a514118b759a66b2799a8a4aa78675fa6bb0d3f7d52d67eff002"},
|
|
||||||
{file = "psycopg-3.1.17.tar.gz", hash = "sha256:437e7d7925459f21de570383e2e10542aceb3b9cb972ce957fdd3826ca47edc6"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
psycopg-binary = {version = "3.1.17", 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.17)"]
|
|
||||||
c = ["psycopg-c (==3.1.17)"]
|
|
||||||
dev = ["black (>=23.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.17"
|
|
||||||
description = "PostgreSQL database adapter for Python -- C optimisation distribution"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "psycopg_binary-3.1.17-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9ba559eabb0ba1afd4e0504fa0b10e00a212cac0c4028b8a1c3b087b5c1e5de"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2b2a689eaede08cf91a36b10b0da6568dd6e4669200f201e082639816737992b"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a16abab0c1abc58feb6ab11d78d0f8178a67c3586bd70628ec7c0218ec04c4ef"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:73e7097b81cad9ae358334e3cec625246bb3b8013ae6bb287758dd6435e12f65"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:67a5b93101bc85a95a189c0a23d02a29cf06c1080a695a0dedfdd50dd734662a"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:751b31c2faae0348f87f22b45ef58f704bdcfc2abdd680fa0c743c124071157e"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b447ea765e71bc33a82cf070bba814b1efa77967442d116b95ccef8ce5da7631"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d2e9ed88d9a6a475c67bf70fc8285e88ccece0391727c7701e5a512e0eafbb05"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a89f36bf7b612ff6ed3e789bd987cbd0787cf0d66c49386fa3bad816dd7bee87"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5ccbe8b2ec444763a51ecb1213befcbb75defc1ef36e7dd5dff501a23d7ce8cf"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp310-cp310-win_amd64.whl", hash = "sha256:adb670031b27949c9dc5cf585c4a5a6b4469d3879fd2fb9d39b6d53e5f66b9bc"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0227885686c2cc0104ceb22d6eebc732766e9ad48710408cb0123237432e5435"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9124b6db07e8d8b11f4512b8b56cbe136bf1b7d0417d1280e62291a9dcad4408"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8a46f77ba0ca7c5a5449b777170a518fa7820e1710edb40e777c9798f00d033"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f5f5bcbb772d8c243d605fc7151beec760dd27532d42145a58fb74ef9c5fbf2"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:267a82548c21476120e43dc72b961f1af52c380c0b4c951bdb34cf14cb26bd35"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b20013051f1fd7d02b8d0766cfe8d009e8078babc00a6d39bc7e2d50a7b96af"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c5c38129cc79d7e3ba553035b9962a442171e9f97bb1b8795c0885213f206f3"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d01c4faae66de60fcd3afd3720dcc8ffa03bc2087f898106da127774db12aac5"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e6ae27b0617ad3809449964b5e901b21acff8e306abacb8ba71d5ee7c8c47eeb"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:40af298b209dd77ca2f3e7eb3fbcfb87a25999fc015fcd14140bde030a164c7e"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp311-cp311-win_amd64.whl", hash = "sha256:7b4e4c2b05f3b431e9026e82590b217e87696e7a7548f512ae8059d59fa8af3b"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ea425a8dcd808a7232a5417d2633bfa543da583a2701b5228e9e29989a50deda"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a3f1196d76860e72d338fab0d2b6722e8d47e2285d693e366ae36011c4a5898a"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1e867c2a729348df218a14ba1b862e627177fd57c7b4f3db0b4c708f6d03696"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0711e46361ea3047cd049868419d030c8236a9dea7e9ed1f053cbd61a853ec9"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1c0115bdf80cf6c8c9109cb10cf6f650fd1a8d841f884925e8cb12f34eb5371"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d0d154c780cc7b28a3a0886e8a4b18689202a1dbb522b3c771eb3a1289cf7c3"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f4028443bf25c1e04ecffdc552c0a98d826903dec76a1568dfddf5ebbbb03db7"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf424d92dd7e94705b31625b02d396297a7c8fab4b6f7de8dba6388323a7b71c"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:00377f6963ee7e4bf71cab17c2c235ef0624df9483f3b615d86aa24cde889d42"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9690a535d9ccd361bbc3590bfce7fe679e847f44fa7cc97f3b885f4744ca8a2c"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp312-cp312-win_amd64.whl", hash = "sha256:6b2ae342d69684555bfe77aed5546d125b4a99012e0b83a8b3da68c8829f0935"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:86bb3656c8d744cc1e42003414cd6c765117d70aa23da6c0f4ff2b826e0fd0fd"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c10b7713e3ed31df7319c2a72d5fea5a2536476d7695a3e1d18a1f289060997c"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12eab8bc91b4ba01b2ecee3b5b80501934b198f6e1f8d4b13596f3f38ba6e762"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6a728beefd89b430ebe2729d04ba10e05036b5e9d01648da60436000d2fcd242"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61104b8e7a43babf2bbaa36c08e31a12023e2f967166e99d6b052b11a4c7db06"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:02cd2eb62ffc56f8c847d68765cbf461b3d11b438fe48951e44b6c563ec27d18"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ca1757a6e080086f7234dc45684e81a47a66a6dd492a37d6ce38c58a1a93e9ff"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:6e3543edc18553e31a3884af3cd7eea43d6c44532d8b9b16f3e743cdf6cfe6c5"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:914254849486e14aa931b0b3382cd16887f1507068ffba775cbdc5a55fe9ef19"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp37-cp37m-win_amd64.whl", hash = "sha256:92fad8f1aa80a5ab316c0493dc6d1b54c1dba21937e43eea7296ff4a0ccc071e"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6d4f2e15d33ed4f9776fdf23683512d76f4e7825c4b80677e9e3ce6c1b193ff2"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4fa26836ce074a1104249378727e1f239a01530f36bae16e77cf6c50968599b4"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d54bcf2dfc0880bf13f38512d44b194c092794e4ee9e01d804bc6cd3eed9bfb7"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e28024204dc0c61094268c682041d2becfedfea2e3b46bed5f6138239304d98"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b1ec6895cab887b92c303565617f994c9b9db53befda81fa2a31b76fe8a3ab1"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:420c1eb1626539c261cf3fbe099998da73eb990f9ce1a34da7feda414012ea5f"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:83404a353240fdff5cfe9080665fdfdcaa2d4d0c5112e15b0a2fe2e59200ed57"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a0c4ba73f9e7721dd6cc3e6953016652dbac206f654229b7a1a8ac182b16e689"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f6898bf1ca5aa01115807643138e3e20ec603b17a811026bc4a49d43055720a7"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6b40fa54a02825d3d6a8009d9a82a2b4fad80387acf2b8fd6d398fd2813cb2d9"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp38-cp38-win_amd64.whl", hash = "sha256:78ebb43dca7d5b41eee543cd005ee5a0256cecc74d84acf0fab4f025997b837e"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:02ac573f5a6e79bb6df512b3a6279f01f033bbd45c47186e8872fee45f6681d0"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:704f6393d758b12a4369887fe956b2a8c99e4aced839d9084de8e3f056015d40"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0340ef87a888fd940796c909e038426f4901046f61856598582a817162c64984"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a880e4113af3ab84d6a0991e3f85a2424924c8a182733ab8d964421df8b5190a"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93921178b9a40c60c26e47eb44970f88c49fe484aaa3bb7ec02bb8b514eab3d9"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a05400e9314fc30bc1364865ba9f6eaa2def42b5e7e67f71f9a4430f870023e"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3e2cc2bbf37ff1cf11e8b871c294e3532636a3cf7f0c82518b7537158923d77b"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a343261701a8f63f0d8268f7fd32be40ffe28d24b65d905404ca03e7281f7bb5"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:dceb3930ec426623c0cacc78e447a90882981e8c49d6fea8d1e48850e24a0170"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d613a23f8928f30acb2b6b2398cb7775ba9852e8968e15df13807ba0d3ebd565"},
|
|
||||||
{file = "psycopg_binary-3.1.17-cp39-cp39-win_amd64.whl", hash = "sha256:d90c0531e9d591bde8cea04e75107fcddcc56811b638a34853436b23c9a3cb7d"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pycparser"
|
|
||||||
version = "2.21"
|
|
||||||
description = "C parser in Python"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|
||||||
files = [
|
|
||||||
{file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
|
|
||||||
{file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pydantic"
|
|
||||||
version = "2.6.0"
|
|
||||||
description = "Data validation using Python type hints"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "pydantic-2.6.0-py3-none-any.whl", hash = "sha256:1440966574e1b5b99cf75a13bec7b20e3512e8a61b894ae252f56275e2c465ae"},
|
|
||||||
{file = "pydantic-2.6.0.tar.gz", hash = "sha256:ae887bd94eb404b09d86e4d12f93893bdca79d766e738528c6fa1c849f3c6bcf"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
annotated-types = ">=0.4.0"
|
|
||||||
pydantic-core = "2.16.1"
|
|
||||||
typing-extensions = ">=4.6.1"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
email = ["email-validator (>=2.0.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pydantic-core"
|
|
||||||
version = "2.16.1"
|
|
||||||
description = ""
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "pydantic_core-2.16.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:300616102fb71241ff477a2cbbc847321dbec49428434a2f17f37528721c4948"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5511f962dd1b9b553e9534c3b9c6a4b0c9ded3d8c2be96e61d56f933feef9e1f"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98f0edee7ee9cc7f9221af2e1b95bd02810e1c7a6d115cfd82698803d385b28f"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9795f56aa6b2296f05ac79d8a424e94056730c0b860a62b0fdcfe6340b658cc8"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c45f62e4107ebd05166717ac58f6feb44471ed450d07fecd90e5f69d9bf03c48"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:462d599299c5971f03c676e2b63aa80fec5ebc572d89ce766cd11ca8bcb56f3f"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ebaa4bf6386a3b22eec518da7d679c8363fb7fb70cf6972161e5542f470798"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:99f9a50b56713a598d33bc23a9912224fc5d7f9f292444e6664236ae471ddf17"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8ec364e280db4235389b5e1e6ee924723c693cbc98e9d28dc1767041ff9bc388"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:653a5dfd00f601a0ed6654a8b877b18d65ac32c9d9997456e0ab240807be6cf7"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp310-none-win32.whl", hash = "sha256:1661c668c1bb67b7cec96914329d9ab66755911d093bb9063c4c8914188af6d4"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp310-none-win_amd64.whl", hash = "sha256:561be4e3e952c2f9056fba5267b99be4ec2afadc27261505d4992c50b33c513c"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:102569d371fadc40d8f8598a59379c37ec60164315884467052830b28cc4e9da"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:735dceec50fa907a3c314b84ed609dec54b76a814aa14eb90da31d1d36873a5e"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e83ebbf020be727d6e0991c1b192a5c2e7113eb66e3def0cd0c62f9f266247e4"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:30a8259569fbeec49cfac7fda3ec8123486ef1b729225222f0d41d5f840b476f"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:920c4897e55e2881db6a6da151198e5001552c3777cd42b8a4c2f72eedc2ee91"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5247a3d74355f8b1d780d0f3b32a23dd9f6d3ff43ef2037c6dcd249f35ecf4c"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d5bea8012df5bb6dda1e67d0563ac50b7f64a5d5858348b5c8cb5043811c19d"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ed3025a8a7e5a59817b7494686d449ebfbe301f3e757b852c8d0d1961d6be864"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:06f0d5a1d9e1b7932477c172cc720b3b23c18762ed7a8efa8398298a59d177c7"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:150ba5c86f502c040b822777e2e519b5625b47813bd05f9273a8ed169c97d9ae"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp311-none-win32.whl", hash = "sha256:d6cbdf12ef967a6aa401cf5cdf47850559e59eedad10e781471c960583f25aa1"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp311-none-win_amd64.whl", hash = "sha256:afa01d25769af33a8dac0d905d5c7bb2d73c7c3d5161b2dd6f8b5b5eea6a3c4c"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp311-none-win_arm64.whl", hash = "sha256:1a2fe7b00a49b51047334d84aafd7e39f80b7675cad0083678c58983662da89b"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f478ec204772a5c8218e30eb813ca43e34005dff2eafa03931b3d8caef87d51"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f1936ef138bed2165dd8573aa65e3095ef7c2b6247faccd0e15186aabdda7f66"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99d3a433ef5dc3021c9534a58a3686c88363c591974c16c54a01af7efd741f13"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd88f40f2294440d3f3c6308e50d96a0d3d0973d6f1a5732875d10f569acef49"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fac641bbfa43d5a1bed99d28aa1fded1984d31c670a95aac1bf1d36ac6ce137"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72bf9308a82b75039b8c8edd2be2924c352eda5da14a920551a8b65d5ee89253"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb4363e6c9fc87365c2bc777a1f585a22f2f56642501885ffc7942138499bf54"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:20f724a023042588d0f4396bbbcf4cffd0ddd0ad3ed4f0d8e6d4ac4264bae81e"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fb4370b15111905bf8b5ba2129b926af9470f014cb0493a67d23e9d7a48348e8"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:23632132f1fd608034f1a56cc3e484be00854db845b3a4a508834be5a6435a6f"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp312-none-win32.whl", hash = "sha256:b9f3e0bffad6e238f7acc20c393c1ed8fab4371e3b3bc311020dfa6020d99212"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp312-none-win_amd64.whl", hash = "sha256:a0b4cfe408cd84c53bab7d83e4209458de676a6ec5e9c623ae914ce1cb79b96f"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp312-none-win_arm64.whl", hash = "sha256:d195add190abccefc70ad0f9a0141ad7da53e16183048380e688b466702195dd"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:502c062a18d84452858f8aea1e520e12a4d5228fc3621ea5061409d666ea1706"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d8c032ccee90b37b44e05948b449a2d6baed7e614df3d3f47fe432c952c21b60"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:920f4633bee43d7a2818e1a1a788906df5a17b7ab6fe411220ed92b42940f818"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9f5d37ff01edcbace53a402e80793640c25798fb7208f105d87a25e6fcc9ea06"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:399166f24c33a0c5759ecc4801f040dbc87d412c1a6d6292b2349b4c505effc9"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ac89ccc39cd1d556cc72d6752f252dc869dde41c7c936e86beac5eb555041b66"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73802194f10c394c2bedce7a135ba1d8ba6cff23adf4217612bfc5cf060de34c"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8fa00fa24ffd8c31fac081bf7be7eb495be6d248db127f8776575a746fa55c95"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:601d3e42452cd4f2891c13fa8c70366d71851c1593ed42f57bf37f40f7dca3c8"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07982b82d121ed3fc1c51faf6e8f57ff09b1325d2efccaa257dd8c0dd937acca"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp38-none-win32.whl", hash = "sha256:d0bf6f93a55d3fa7a079d811b29100b019784e2ee6bc06b0bb839538272a5610"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp38-none-win_amd64.whl", hash = "sha256:fbec2af0ebafa57eb82c18c304b37c86a8abddf7022955d1742b3d5471a6339e"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a497be217818c318d93f07e14502ef93d44e6a20c72b04c530611e45e54c2196"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:694a5e9f1f2c124a17ff2d0be613fd53ba0c26de588eb4bdab8bca855e550d95"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d4dfc66abea3ec6d9f83e837a8f8a7d9d3a76d25c9911735c76d6745950e62c"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8655f55fe68c4685673265a650ef71beb2d31871c049c8b80262026f23605ee3"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:21e3298486c4ea4e4d5cc6fb69e06fb02a4e22089304308817035ac006a7f506"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71b4a48a7427f14679f0015b13c712863d28bb1ab700bd11776a5368135c7d60"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10dca874e35bb60ce4f9f6665bfbfad050dd7573596608aeb9e098621ac331dc"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fa496cd45cda0165d597e9d6f01e36c33c9508f75cf03c0a650018c5048f578e"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5317c04349472e683803da262c781c42c5628a9be73f4750ac7d13040efb5d2d"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:42c29d54ed4501a30cd71015bf982fa95e4a60117b44e1a200290ce687d3e640"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp39-none-win32.whl", hash = "sha256:ba07646f35e4e49376c9831130039d1b478fbfa1215ae62ad62d2ee63cf9c18f"},
|
|
||||||
{file = "pydantic_core-2.16.1-cp39-none-win_amd64.whl", hash = "sha256:2133b0e412a47868a358713287ff9f9a328879da547dc88be67481cdac529118"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d25ef0c33f22649b7a088035fd65ac1ce6464fa2876578df1adad9472f918a76"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:99c095457eea8550c9fa9a7a992e842aeae1429dab6b6b378710f62bfb70b394"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b49c604ace7a7aa8af31196abbf8f2193be605db6739ed905ecaf62af31ccae0"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c56da23034fe66221f2208c813d8aa509eea34d97328ce2add56e219c3a9f41c"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cebf8d56fee3b08ad40d332a807ecccd4153d3f1ba8231e111d9759f02edfd05"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:1ae8048cba95f382dba56766525abca438328455e35c283bb202964f41a780b0"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:780daad9e35b18d10d7219d24bfb30148ca2afc309928e1d4d53de86822593dc"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c94b5537bf6ce66e4d7830c6993152940a188600f6ae044435287753044a8fe2"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:adf28099d061a25fbcc6531febb7a091e027605385de9fe14dd6a97319d614cf"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:644904600c15816a1f9a1bafa6aab0d21db2788abcdf4e2a77951280473f33e1"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87bce04f09f0552b66fca0c4e10da78d17cb0e71c205864bab4e9595122cb9d9"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:877045a7969ace04d59516d5d6a7dee13106822f99a5d8df5e6822941f7bedc8"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9c46e556ee266ed3fb7b7a882b53df3c76b45e872fdab8d9cf49ae5e91147fd7"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4eebbd049008eb800f519578e944b8dc8e0f7d59a5abb5924cc2d4ed3a1834ff"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:c0be58529d43d38ae849a91932391eb93275a06b93b79a8ab828b012e916a206"},
|
|
||||||
{file = "pydantic_core-2.16.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b1fc07896fc1851558f532dffc8987e526b682ec73140886c831d773cef44b76"},
|
|
||||||
{file = "pydantic_core-2.16.1.tar.gz", hash = "sha256:daff04257b49ab7f4b3f73f98283d3dbb1a65bf3500d55c7beac3c66c310fe34"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pyjwt"
|
|
||||||
version = "2.8.0"
|
|
||||||
description = "JSON Web Token implementation in Python"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"},
|
|
||||||
{file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
crypto = ["cryptography (>=3.4.0)"]
|
|
||||||
dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"]
|
|
||||||
docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"]
|
|
||||||
tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "python-dotenv"
|
|
||||||
version = "1.0.1"
|
|
||||||
description = "Read key-value pairs from a .env file and set them as environment variables"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
|
|
||||||
{file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
cli = ["click (>=5.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "python3-openid"
|
|
||||||
version = "3.2.0"
|
|
||||||
description = "OpenID support for modern servers and consumers."
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "python3-openid-3.2.0.tar.gz", hash = "sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf"},
|
|
||||||
{file = "python3_openid-3.2.0-py3-none-any.whl", hash = "sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
defusedxml = "*"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
mysql = ["mysql-connector-python"]
|
|
||||||
postgresql = ["psycopg2"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pyyaml"
|
|
||||||
version = "6.0.1"
|
|
||||||
description = "YAML parser and emitter for Python"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
|
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
|
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
|
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
|
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
|
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
|
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
|
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
|
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
|
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
|
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
|
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
|
|
||||||
{file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
|
|
||||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
|
|
||||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
|
|
||||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
|
|
||||||
{file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
|
|
||||||
{file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
|
|
||||||
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex"
|
|
||||||
version = "2023.12.25"
|
|
||||||
description = "Alternative regular expression module, to replace re."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"},
|
|
||||||
{file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"},
|
|
||||||
{file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"},
|
|
||||||
{file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"},
|
|
||||||
{file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"},
|
|
||||||
{file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"},
|
|
||||||
{file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"},
|
|
||||||
{file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "requests"
|
|
||||||
version = "2.31.0"
|
|
||||||
description = "Python HTTP for Humans."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
|
|
||||||
{file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
certifi = ">=2017.4.17"
|
|
||||||
charset-normalizer = ">=2,<4"
|
|
||||||
idna = ">=2.5,<4"
|
|
||||||
urllib3 = ">=1.21.1,<3"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
|
||||||
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "requests-oauthlib"
|
|
||||||
version = "1.3.1"
|
|
||||||
description = "OAuthlib authentication support for Requests."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|
||||||
files = [
|
|
||||||
{file = "requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a"},
|
|
||||||
{file = "requests_oauthlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
oauthlib = ">=3.0.0"
|
|
||||||
requests = ">=2.0.0"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
rsa = ["oauthlib[signedtoken] (>=3.0.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ruff"
|
|
||||||
version = "0.2.0"
|
|
||||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "ruff-0.2.0-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:638ea3294f800d18bae84a492cb5a245c8d29c90d19a91d8e338937a4c27fca0"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3ff35433fcf4dff6d610738712152df6b7d92351a1bde8e00bd405b08b3d5759"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf9faafbdcf4f53917019f2c230766da437d4fd5caecd12ddb68bb6a17d74399"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8153a3e4128ed770871c47545f1ae7b055023e0c222ff72a759f5a341ee06483"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8a75a98ae989a27090e9c51f763990ad5bbc92d20626d54e9701c7fe597f399"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:87057dd2fdde297130ff99553be8549ca38a2965871462a97394c22ed2dfc19d"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d232f99d3ab00094ebaf88e0fb7a8ccacaa54cc7fa3b8993d9627a11e6aed7a"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d3c641f95f435fc6754b05591774a17df41648f0daf3de0d75ad3d9f099ab92"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3826fb34c144ef1e171b323ed6ae9146ab76d109960addca730756dc19dc7b22"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:eceab7d85d09321b4de18b62d38710cf296cb49e98979960a59c6b9307c18cfe"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:30ad74687e1f4a9ff8e513b20b82ccadb6bd796fe5697f1e417189c5cde6be3e"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a7e3818698f8460bd0f8d4322bbe99db8327e9bc2c93c789d3159f5b335f47da"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:edf23041242c48b0d8295214783ef543847ef29e8226d9f69bf96592dba82a83"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-win32.whl", hash = "sha256:e155147199c2714ff52385b760fe242bb99ea64b240a9ffbd6a5918eb1268843"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-win_amd64.whl", hash = "sha256:ba918e01cdd21e81b07555564f40d307b0caafa9a7a65742e98ff244f5035c59"},
|
|
||||||
{file = "ruff-0.2.0-py3-none-win_arm64.whl", hash = "sha256:3fbaff1ba9564a2c5943f8f38bc221f04bac687cc7485e45237579fee7ccda79"},
|
|
||||||
{file = "ruff-0.2.0.tar.gz", hash = "sha256:63856b91837606c673537d2889989733d7dffde553828d3b0f0bacfa6def54be"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "setuptools"
|
|
||||||
version = "69.0.3"
|
|
||||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"},
|
|
||||||
{file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
|
||||||
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
|
||||||
testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sgmllib3k"
|
|
||||||
version = "1.0.0"
|
|
||||||
description = "Py3k port of sgmllib."
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "six"
|
|
||||||
version = "1.16.0"
|
|
||||||
description = "Python 2 and 3 compatibility utilities"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
|
||||||
files = [
|
|
||||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
|
||||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sqlparse"
|
|
||||||
version = "0.4.4"
|
|
||||||
description = "A non-validating SQL parser."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.5"
|
|
||||||
files = [
|
|
||||||
{file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"},
|
|
||||||
{file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
dev = ["build", "flake8"]
|
|
||||||
doc = ["sphinx"]
|
|
||||||
test = ["pytest", "pytest-cov"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tqdm"
|
|
||||||
version = "4.66.1"
|
|
||||||
description = "Fast, Extensible Progress Meter"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"},
|
|
||||||
{file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"]
|
|
||||||
notebook = ["ipywidgets (>=6)"]
|
|
||||||
slack = ["slack-sdk"]
|
|
||||||
telegram = ["requests"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typing-extensions"
|
|
||||||
version = "4.9.0"
|
|
||||||
description = "Backported and Experimental Type Hints for Python 3.8+"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"},
|
|
||||||
{file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tzdata"
|
|
||||||
version = "2023.4"
|
|
||||||
description = "Provider of IANA time zone data"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2"
|
|
||||||
files = [
|
|
||||||
{file = "tzdata-2023.4-py2.py3-none-any.whl", hash = "sha256:aa3ace4329eeacda5b7beb7ea08ece826c28d761cda36e747cfbf97996d39bf3"},
|
|
||||||
{file = "tzdata-2023.4.tar.gz", hash = "sha256:dd54c94f294765522c77399649b4fefd95522479a664a0cec87f41bebc6148c9"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "urllib3"
|
|
||||||
version = "2.2.0"
|
|
||||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"},
|
|
||||||
{file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
|
|
||||||
h2 = ["h2 (>=4,<5)"]
|
|
||||||
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
|
||||||
zstd = ["zstandard (>=0.18.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "virtualenv"
|
|
||||||
version = "20.25.0"
|
|
||||||
description = "Virtual Python Environment builder"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"},
|
|
||||||
{file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
distlib = ">=0.3.7,<1"
|
|
||||||
filelock = ">=3.12.2,<4"
|
|
||||||
platformdirs = ">=3.9.1,<5"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "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)"]
|
|
||||||
|
|
||||||
[[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]
|
|
||||||
lock-version = "2.0"
|
|
||||||
python-versions = "^3.12"
|
|
||||||
content-hash = "0ae3f0c46114a57572a27d25b1bc11570170311b369f2c1f2c720e6a3013fa29"
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
[tool.poetry]
|
|
||||||
name = "feedvault"
|
|
||||||
version = "0.1.0"
|
|
||||||
description = "A small archive of RSS feeds"
|
|
||||||
authors = ["Joakim Hellsén <tlovinator@gmail.com>"]
|
|
||||||
readme = "README.md"
|
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
|
||||||
python = "^3.12"
|
|
||||||
django = "^5.0.1"
|
|
||||||
django-allauth = "^0.60.1"
|
|
||||||
django-debug-toolbar = "^4.2.0"
|
|
||||||
django-ninja = "^1.1.0"
|
|
||||||
feedparser = "^6.0.11"
|
|
||||||
gunicorn = "^21.2.0"
|
|
||||||
psycopg = { extras = ["binary"], version = "^3.1.17" }
|
|
||||||
python-dotenv = "^1.0.1"
|
|
||||||
whitenoise = { extras = ["brotli"], version = "^6.6.0" }
|
|
||||||
listparser = { extras = ["http", "lxml"], version = "^0.19" }
|
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
|
||||||
pre-commit = "^3.6.0"
|
|
||||||
djlint = "^1.34.1"
|
|
||||||
ruff = "^0.2.0"
|
|
||||||
|
|
||||||
[build-system]
|
|
||||||
build-backend = "poetry.core.masonry.api"
|
|
||||||
requires = [
|
|
||||||
"poetry-core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.ruff]
|
|
||||||
exclude = ["migrations"]
|
|
||||||
fix = true
|
|
||||||
unsafe-fixes = true
|
|
||||||
preview = true
|
|
||||||
select = ["ALL"]
|
|
||||||
ignore = [
|
|
||||||
"CPY001", # Missing copyright notice at top of file
|
|
||||||
"ERA001", # Found commented-out code
|
|
||||||
"FIX002", # Line contains TODO
|
|
||||||
]
|
|
||||||
line-length = 120
|
|
||||||
|
|
||||||
[tool.ruff.pydocstyle]
|
|
||||||
convention = "google"
|
|
||||||
|
|
||||||
[tool.ruff.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.
|
|
||||||
]
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue