mirror of
https://github.com/Cian-H/iform-invenio.git
synced 2026-08-16 16:32:50 +01:00
Significant overhaul of tooling
This commit is contained in:
+225
@@ -22,6 +22,229 @@ package-lock.json
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[codz]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py.cover
|
||||
*.lcov
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.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
|
||||
|
||||
# UV
|
||||
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# uv.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
|
||||
# poetry.toml
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
||||
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
||||
# pdm.lock
|
||||
# pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
|
||||
# pixi
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
||||
# pixi.lock
|
||||
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
||||
# in the .venv directory. It is recommended not to include this directory in version control.
|
||||
.pixi/*
|
||||
!.pixi/config.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
|
||||
|
||||
# Redis
|
||||
*.rdb
|
||||
*.aof
|
||||
*.pid
|
||||
|
||||
# RabbitMQ
|
||||
mnesia/
|
||||
rabbitmq/
|
||||
rabbitmq-data/
|
||||
|
||||
# ActiveMQ
|
||||
activemq-data/
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.envrc
|
||||
.bw_session
|
||||
.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
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
# .idea/
|
||||
|
||||
# Abstra
|
||||
# Abstra is an AI-powered process automation framework.
|
||||
# Ignore directories containing user credentials, local state, and settings.
|
||||
# Learn more at https://abstra.io/docs
|
||||
.abstra/
|
||||
|
||||
# Visual Studio Code
|
||||
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
||||
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
||||
# you could uncomment the following to ignore the entire vscode folder
|
||||
# .vscode/
|
||||
# Temporary file for partial code execution
|
||||
tempCodeRunnerFile.py
|
||||
|
||||
# Ruff stuff:
|
||||
.ruff_cache/
|
||||
|
||||
# PyPI configuration file
|
||||
.pypirc
|
||||
|
||||
# Marimo
|
||||
marimo/_static/
|
||||
marimo/_lsp/
|
||||
__marimo__/
|
||||
|
||||
# Streamlit
|
||||
.streamlit/secrets.toml
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
@@ -34,6 +257,7 @@ package-lock.json
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# work-in-progress assets
|
||||
/assets
|
||||
|
||||
@@ -48,3 +272,4 @@ versions
|
||||
secrets.env
|
||||
.env
|
||||
agents
|
||||
.aws
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import typer
|
||||
from loguru import logger
|
||||
from plumbum import FG, local
|
||||
from plumbum.cmd import docker as docker_cmd
|
||||
|
||||
from cli.bitwarden import app as bw_app
|
||||
from cli.bootstrap import app as bootstrap_app
|
||||
from cli.config import config
|
||||
from cli.deploy import app as deploy_app
|
||||
from cli.dev import app as dev_app
|
||||
from cli.env import app as env_app
|
||||
from cli.s3 import app as s3_app
|
||||
from cli.utils import docker_compose, get_repo_dir
|
||||
|
||||
app = typer.Typer(help="Unified Repository Automation CLI")
|
||||
|
||||
app.add_typer(dev_app, name="dev")
|
||||
app.add_typer(bw_app, name="bw")
|
||||
app.add_typer(s3_app, name="s3")
|
||||
app.add_typer(deploy_app, name="deploy")
|
||||
|
||||
app.add_typer(env_app, name="env")
|
||||
app.add_typer(bootstrap_app, name="bootstrap")
|
||||
|
||||
|
||||
@app.command(
|
||||
context_settings={"allow_extra_args": True, "ignore_unknown_options": True}
|
||||
)
|
||||
def compose(ctx: typer.Context):
|
||||
"""Passthrough to docker-compose inside the repository directory."""
|
||||
with local.cwd(get_repo_dir()):
|
||||
docker_compose(*ctx.args) & FG
|
||||
|
||||
|
||||
@app.command(
|
||||
context_settings={"allow_extra_args": True, "ignore_unknown_options": True}
|
||||
)
|
||||
def invenio(ctx: typer.Context):
|
||||
"""Passthrough to invenio inside the running worker container."""
|
||||
with local.cwd(get_repo_dir()):
|
||||
docker_compose("exec", "worker", "invenio", *ctx.args) & FG
|
||||
|
||||
|
||||
@app.command(
|
||||
context_settings={"allow_extra_args": True, "ignore_unknown_options": True}
|
||||
)
|
||||
def docker(ctx: typer.Context):
|
||||
"""Passthrough to docker inside the repository directory."""
|
||||
with local.cwd(get_repo_dir()):
|
||||
docker_cmd[*ctx.args] & FG
|
||||
|
||||
|
||||
@app.command(
|
||||
name="invenio-cli",
|
||||
context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
|
||||
)
|
||||
def invenio_cli_cmd(ctx: typer.Context):
|
||||
"""Passthrough to invenio-cli inside the repository directory."""
|
||||
from plumbum.cmd import invenio_cli
|
||||
|
||||
with local.cwd(get_repo_dir()):
|
||||
invenio_cli[*ctx.args] & FG
|
||||
|
||||
|
||||
@app.command(
|
||||
context_settings={"allow_extra_args": True, "ignore_unknown_options": True}
|
||||
)
|
||||
def aws(ctx: typer.Context):
|
||||
"""Passthrough to aws-cli with configured endpoint-url and credentials."""
|
||||
try:
|
||||
from plumbum.cmd import aws as aws_cmd
|
||||
except ImportError:
|
||||
logger.error("AWS CLI not found in PATH.")
|
||||
raise typer.Exit(1)
|
||||
|
||||
aws_cmd["--endpoint-url", str(config.s3_endpoint_url), *ctx.args] & FG
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app()
|
||||
@@ -0,0 +1,134 @@
|
||||
import json
|
||||
|
||||
import typer
|
||||
from loguru import logger
|
||||
from plumbum import FG, ProcessExecutionError, local
|
||||
|
||||
from cli.config import config
|
||||
from cli.utils import get_project_root
|
||||
|
||||
app = typer.Typer(help="Bitwarden integration workflows.")
|
||||
|
||||
BW_SESSION_FILE = get_project_root() / ".bw_session"
|
||||
ENV_FILE = get_project_root() / ".env"
|
||||
|
||||
|
||||
def _get_bw():
|
||||
try:
|
||||
from plumbum.cmd import bw
|
||||
|
||||
return bw
|
||||
except ImportError:
|
||||
logger.error(
|
||||
"Bitwarden CLI ('bw') not found. Please ensure it is installed or "
|
||||
"run 'direnv allow' if you just updated devenv.nix."
|
||||
)
|
||||
raise typer.Exit(1)
|
||||
|
||||
|
||||
@app.command()
|
||||
def login() -> bool:
|
||||
"""Log in to Bitwarden and cache the session token. Returns True if a new session was created."""
|
||||
bw = _get_bw()
|
||||
|
||||
if config.bitwarden_server_url:
|
||||
logger.info(f"Configuring Bitwarden server: {config.bitwarden_server_url}")
|
||||
bw("config", "server", config.bitwarden_server_url)
|
||||
|
||||
logger.info("Checking login status...")
|
||||
try:
|
||||
status_json = bw("status")
|
||||
status = json.loads(status_json)
|
||||
if status.get("status") == "unlocked":
|
||||
logger.info("Vault is already unlocked. Using existing session.")
|
||||
return False
|
||||
|
||||
if status.get("status") == "unauthenticated":
|
||||
logger.info("Not logged in. Initiating login...")
|
||||
bw["login"] & FG
|
||||
elif status.get("status") == "locked":
|
||||
logger.info("Vault is locked. Initiating unlock...")
|
||||
except ProcessExecutionError:
|
||||
logger.warning("Failed to check status. Initiating login...")
|
||||
bw["login"] & FG
|
||||
|
||||
logger.info("Unlocking vault and saving session...")
|
||||
try:
|
||||
# Prompt for master password and output just the raw session key
|
||||
session_key = bw("unlock", "--raw").strip()
|
||||
BW_SESSION_FILE.write_text(session_key)
|
||||
BW_SESSION_FILE.chmod(0o600)
|
||||
logger.success("Session unlocked and cached securely in .bw_session")
|
||||
return True
|
||||
except ProcessExecutionError as e:
|
||||
logger.error(f"Failed to unlock vault: {e}")
|
||||
raise typer.Exit(1)
|
||||
|
||||
|
||||
@app.command()
|
||||
def pull():
|
||||
"""Pull secrets from Bitwarden Secure Note and inject into .env"""
|
||||
bw = _get_bw()
|
||||
|
||||
if not BW_SESSION_FILE.exists():
|
||||
logger.error(
|
||||
"No active Bitwarden session found. Please run `uv run cli bw login` first."
|
||||
)
|
||||
raise typer.Exit(1)
|
||||
|
||||
session_key = BW_SESSION_FILE.read_text().strip()
|
||||
with local.env(BW_SESSION=session_key):
|
||||
logger.info("Syncing vault...")
|
||||
try:
|
||||
bw("sync")
|
||||
except ProcessExecutionError as e:
|
||||
logger.warning(f"Failed to sync vault (continuing anyway): {e}")
|
||||
|
||||
logger.info(f"Fetching item: {config.bitwarden_item_name}...")
|
||||
try:
|
||||
item_json = bw("get", "item", config.bitwarden_item_name)
|
||||
item = json.loads(item_json)
|
||||
except ProcessExecutionError as e:
|
||||
logger.error(
|
||||
f"Failed to fetch item '{config.bitwarden_item_name}'. Make sure the name is exact."
|
||||
)
|
||||
logger.debug(f"Details: {e}")
|
||||
raise typer.Exit(1)
|
||||
|
||||
notes = item.get("notes")
|
||||
if not notes:
|
||||
logger.error(
|
||||
f"The item '{config.bitwarden_item_name}' does not contain any notes."
|
||||
)
|
||||
raise typer.Exit(1)
|
||||
|
||||
try:
|
||||
secrets = json.loads(notes)
|
||||
except json.JSONDecodeError:
|
||||
logger.error(
|
||||
f"The notes in '{config.bitwarden_item_name}' are not valid JSON."
|
||||
)
|
||||
raise typer.Exit(1)
|
||||
|
||||
logger.info(f"Successfully fetched {len(secrets)} secrets from secure note.")
|
||||
return secrets
|
||||
|
||||
|
||||
@app.command()
|
||||
def lock():
|
||||
"""Lock the Bitwarden vault and remove the local session token."""
|
||||
bw = _get_bw()
|
||||
|
||||
if BW_SESSION_FILE.exists():
|
||||
session_key = BW_SESSION_FILE.read_text().strip()
|
||||
with local.env(BW_SESSION=session_key):
|
||||
try:
|
||||
bw("lock")
|
||||
logger.success("Bitwarden vault locked successfully.")
|
||||
except ProcessExecutionError as e:
|
||||
logger.warning(f"Failed to lock vault cleanly: {e}")
|
||||
|
||||
BW_SESSION_FILE.unlink()
|
||||
logger.success("Local session token removed.")
|
||||
else:
|
||||
logger.info("No local session token found.")
|
||||
@@ -0,0 +1,35 @@
|
||||
import typer
|
||||
from loguru import logger
|
||||
from plumbum.cmd import docker
|
||||
|
||||
app = typer.Typer(help="Server Bootstrap Tool")
|
||||
|
||||
|
||||
@app.command()
|
||||
def server():
|
||||
"""Bootstrap a fresh production server environment."""
|
||||
logger.info("Starting fresh server bootstrap process...")
|
||||
|
||||
try:
|
||||
docker_version = docker["--version"]().strip()
|
||||
logger.success(f"Found {docker_version}")
|
||||
except Exception:
|
||||
logger.error("Docker is not installed or not in PATH!")
|
||||
raise typer.Exit(1)
|
||||
|
||||
try:
|
||||
docker("compose", "version")
|
||||
logger.success("Found docker compose plugin")
|
||||
except Exception:
|
||||
logger.error("Docker Compose plugin is not installed!")
|
||||
raise typer.Exit(1)
|
||||
|
||||
from cli.env import template as env_template
|
||||
|
||||
logger.info("Generating .env template for configuration...")
|
||||
env_template()
|
||||
|
||||
logger.success("Bootstrap successful!")
|
||||
logger.warning(
|
||||
"Please fill out the generated .env.template and rename it to .env before running `uv run cli deploy prod-deploy`."
|
||||
)
|
||||
@@ -0,0 +1,67 @@
|
||||
from pydantic import AliasChoices, Field, SecretStr
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
from cli.utils import get_project_root
|
||||
|
||||
|
||||
class Config(BaseSettings):
|
||||
"""Centralized configuration values for the scripts."""
|
||||
|
||||
model_config = SettingsConfigDict(
|
||||
env_file=get_project_root() / ".env", env_file_encoding="utf-8", extra="ignore"
|
||||
)
|
||||
|
||||
s3_endpoint_url: str = Field(
|
||||
default="https://eu-west-1.storage.impossibleapi.net",
|
||||
validation_alias=AliasChoices(
|
||||
"invenio_s3_endpoint_url", "s3_endpoint_url", "aws_endpoint_url"
|
||||
),
|
||||
)
|
||||
s3_access_key_id: str | None = Field(
|
||||
default=None,
|
||||
validation_alias=AliasChoices(
|
||||
"invenio_s3_access_key_id", "s3_access_key_id", "aws_access_key_id"
|
||||
),
|
||||
)
|
||||
s3_secret_access_key: SecretStr | None = Field(
|
||||
default=None,
|
||||
validation_alias=AliasChoices(
|
||||
"invenio_s3_secret_access_key",
|
||||
"s3_secret_access_key",
|
||||
"aws_secret_access_key",
|
||||
),
|
||||
)
|
||||
s3_region: str = Field(
|
||||
default="eu-west-1",
|
||||
validation_alias=AliasChoices(
|
||||
"invenio_s3_region_name",
|
||||
"invenio_s3_region",
|
||||
"s3_region",
|
||||
"aws_default_region",
|
||||
),
|
||||
)
|
||||
s3_bucket_name: str = Field(
|
||||
default="iform-invenio",
|
||||
validation_alias=AliasChoices(
|
||||
"invenio_s3_bucket_name", "s3_bucket_name", "aws_s3_bucket"
|
||||
),
|
||||
)
|
||||
|
||||
# Project Settings
|
||||
repo_dir_name: str = Field(default="i-form-data-repository")
|
||||
docker_compose_file: str = Field(default="docker-compose.full.yml")
|
||||
docker_image_name: str = Field(default="i-form-data-repository:latest")
|
||||
|
||||
# Dev Settings
|
||||
theme_dir_name: str = Field(default="invenio-theme-iform")
|
||||
config_dir_name: str = Field(default="invenio-config-iform")
|
||||
local_wheels_dir: str = Field(default="local_wheels")
|
||||
ssl_cert_name: str = Field(default="nginx.crt")
|
||||
ssl_key_name: str = Field(default="nginx.key")
|
||||
|
||||
# Bitwarden Settings
|
||||
bitwarden_item_name: str = Field(default="I-Form Invenio S3 Keys")
|
||||
bitwarden_server_url: str | None = Field(default=None)
|
||||
|
||||
|
||||
config = Config()
|
||||
@@ -1,3 +1,8 @@
|
||||
# Invenio-S3 Storage Backend Credentials
|
||||
INVENIO_S3_ENDPOINT_URL=https://eu-west-1.storage.impossibleapi.net
|
||||
INVENIO_S3_REGION_NAME=eu-west-1
|
||||
INVENIO_S3_BUCKET_NAME=iform-invenio
|
||||
|
||||
# Invenio-Theme
|
||||
INVENIO_THEME_LOGO=custom_assets/I-Form_logo.webp
|
||||
INVENIO_THEME_FRONTPAGE_TITLE="I-Form Invenio Data Repository"
|
||||
@@ -58,11 +63,6 @@ INVENIO_OAISERVER_ID_PREFIX=invenio-rdm
|
||||
# Invenio-Files-REST
|
||||
INVENIO_FILES_REST_STORAGE_FACTORY=invenio_s3.s3fs_storage_factory
|
||||
|
||||
# Invenio-S3
|
||||
INVENIO_S3_ENDPOINT_URL=https://s3.eu-west-1.amazonaws.com
|
||||
INVENIO_S3_REGION_NAME=eu-west-1
|
||||
INVENIO_S3_BUCKET_NAME=i-form-invenio
|
||||
|
||||
# Invenio-Search
|
||||
INVENIO_SEARCH_HOSTS=search:9200
|
||||
INVENIO_SEARCH_INDEX_PREFIX=invenio-rdm-
|
||||
@@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"AllowedHeaders": [],
|
||||
"AllowedMethods": ["GET"],
|
||||
"AllowedOrigins": ["*"],
|
||||
"ExposeHeaders": []
|
||||
}
|
||||
]
|
||||
+261
@@ -0,0 +1,261 @@
|
||||
import typer
|
||||
from loguru import logger
|
||||
from plumbum import local
|
||||
from plumbum.cmd import docker, git, uv
|
||||
|
||||
from cli.utils import docker_compose, get_project_root, get_repo_dir
|
||||
|
||||
app = typer.Typer(help="Deployment Management Tool")
|
||||
|
||||
ROOT_DIR = get_project_root()
|
||||
REPO_DIR = get_repo_dir()
|
||||
VERSIONS_DIR = ROOT_DIR / "versions"
|
||||
|
||||
|
||||
import time
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
def healthcheck():
|
||||
"""Poll the localhost health endpoint to verify the stack is up."""
|
||||
logger.info("Running healthcheck...")
|
||||
for _ in range(3):
|
||||
try:
|
||||
response = requests.get("http://localhost/health", timeout=5)
|
||||
if response.status_code == 200:
|
||||
logger.success("Healthcheck passed.")
|
||||
return
|
||||
except requests.RequestException:
|
||||
pass
|
||||
logger.info("Waiting 5 seconds before retrying...")
|
||||
time.sleep(5)
|
||||
|
||||
logger.error("Healthcheck failed.")
|
||||
raise typer.Exit(1)
|
||||
|
||||
|
||||
@app.command()
|
||||
def tag_version():
|
||||
"""Tag current version using bumpver and save docker images state."""
|
||||
VERSIONS_DIR.mkdir(exist_ok=True)
|
||||
|
||||
logger.info("Bumping version with bumpver...")
|
||||
try:
|
||||
uv("run", "bumpver", "update")
|
||||
except Exception as e:
|
||||
logger.error(f"Bumpver failed: {e}")
|
||||
|
||||
current_tag = git("describe", "--tags", "--abbrev=0").strip()
|
||||
logger.info(f"Current tag is {current_tag}")
|
||||
|
||||
with local.cwd(REPO_DIR):
|
||||
images_output = docker_compose("images")
|
||||
|
||||
version_file = VERSIONS_DIR / f"{current_tag}.txt"
|
||||
|
||||
with open(version_file, "w") as f:
|
||||
for line in images_output.splitlines():
|
||||
if "REPOSITORY" not in line:
|
||||
f.write(line + "\n")
|
||||
|
||||
logger.success(f"Saved image states to {version_file}")
|
||||
|
||||
|
||||
@app.command()
|
||||
def rollback(version: str = typer.Option(None, help="Specific tag to rollback to")):
|
||||
"""Rollback to a specific version or latest."""
|
||||
current_branch = git("branch", "--show-current").strip()
|
||||
|
||||
if not version:
|
||||
tags = git("tag", "--sort=-v:refname").splitlines()
|
||||
if not tags:
|
||||
logger.error("No tags found.")
|
||||
raise typer.Exit(1)
|
||||
version = tags[0]
|
||||
|
||||
version_file = VERSIONS_DIR / f"{version}.txt"
|
||||
|
||||
if not version_file.exists():
|
||||
logger.error(f"No version file found for {version} at {version_file}")
|
||||
raise typer.Exit(1)
|
||||
|
||||
logger.info(f"Pulling old images for {version}...")
|
||||
with open(version_file, "r") as f:
|
||||
for line in f:
|
||||
parts = line.split()
|
||||
if len(parts) >= 2:
|
||||
repo, tag = parts[0], parts[1]
|
||||
logger.info(f"Pulling {repo}:{tag}")
|
||||
docker("pull", f"{repo}:{tag}")
|
||||
|
||||
logger.info(f"Rolling back to {version}...")
|
||||
git("checkout", version)
|
||||
|
||||
try:
|
||||
with local.cwd(REPO_DIR):
|
||||
docker_compose("down")
|
||||
docker_compose("build", "--no-cache")
|
||||
docker_compose("up", "-d")
|
||||
finally:
|
||||
if current_branch:
|
||||
git("switch", current_branch)
|
||||
logger.success(
|
||||
f"Rollback to {version} complete. Returned git to {current_branch}."
|
||||
)
|
||||
else:
|
||||
logger.success(
|
||||
f"Rollback to {version} complete. Remained in detached HEAD."
|
||||
)
|
||||
|
||||
|
||||
@app.command()
|
||||
def cleanup_versions():
|
||||
"""Keep only the latest 5 version tags and delete older ones."""
|
||||
tags = git("tag", "--sort=-v:refname").splitlines()
|
||||
tags_to_delete = tags[5:]
|
||||
|
||||
for tag in tags_to_delete:
|
||||
if not tag:
|
||||
continue
|
||||
git("tag", "-d", tag)
|
||||
version_file = VERSIONS_DIR / f"{tag}.txt"
|
||||
if version_file.exists():
|
||||
version_file.unlink()
|
||||
logger.info(f"Cleaned up {tag}")
|
||||
|
||||
|
||||
@app.command()
|
||||
def prod_deploy():
|
||||
"""First-time deployment to production."""
|
||||
|
||||
logger.info("Deploying to production (first-time)...")
|
||||
git("switch", "prod")
|
||||
git("pull", "origin", "prod")
|
||||
|
||||
with local.cwd(REPO_DIR):
|
||||
docker(
|
||||
"build",
|
||||
"-t",
|
||||
"i-form-data-repository:latest",
|
||||
"--no-cache",
|
||||
"--build-arg",
|
||||
"INSTALL_LOCAL_WHEELS=false",
|
||||
".",
|
||||
)
|
||||
docker_compose("up", "-d", "--wait")
|
||||
|
||||
setup_cmd = "invenio db init && invenio db create && invenio alembic upgrade head && invenio collect -v && invenio index init"
|
||||
docker_compose("exec", "worker", "bash", "-c", setup_cmd)
|
||||
|
||||
logger.success("Production deployment complete!")
|
||||
|
||||
|
||||
@app.command()
|
||||
def prod_update(
|
||||
auto_rollback: bool = typer.Option(
|
||||
False, help="Automatically rollback if healthcheck fails"
|
||||
),
|
||||
):
|
||||
"""Update the application stack, with optional auto-rollback."""
|
||||
lock_file = ROOT_DIR / "update.lock"
|
||||
|
||||
if lock_file.exists():
|
||||
logger.error("Update already in progress (update.lock exists).")
|
||||
raise typer.Exit(1)
|
||||
|
||||
logger.info("Updating production deployment...")
|
||||
|
||||
try:
|
||||
lock_file.touch()
|
||||
|
||||
logger.info("Tagging current version for potential rollback...")
|
||||
tag_version()
|
||||
|
||||
git("switch", "prod")
|
||||
git("pull", "origin", "prod")
|
||||
with local.cwd(REPO_DIR):
|
||||
docker_compose("pull")
|
||||
docker(
|
||||
"build",
|
||||
"-t",
|
||||
"i-form-data-repository:latest",
|
||||
"--no-cache",
|
||||
"--build-arg",
|
||||
"INSTALL_LOCAL_WHEELS=false",
|
||||
".",
|
||||
)
|
||||
docker_compose("up", "-d", "--wait")
|
||||
|
||||
update_cmd = "invenio alembic upgrade head && invenio collect -v"
|
||||
docker_compose("exec", "worker", "bash", "-c", update_cmd)
|
||||
|
||||
try:
|
||||
healthcheck()
|
||||
except typer.Exit:
|
||||
if auto_rollback:
|
||||
logger.warning("Healthcheck failed, triggering auto-rollback...")
|
||||
rollback(None)
|
||||
else:
|
||||
logger.error(
|
||||
"Healthcheck failed. Consider running 'uv run cli deploy rollback' manually."
|
||||
)
|
||||
raise
|
||||
|
||||
cleanup_versions()
|
||||
logger.success("Production update complete!")
|
||||
|
||||
finally:
|
||||
if lock_file.exists():
|
||||
lock_file.unlink()
|
||||
|
||||
|
||||
@app.command()
|
||||
def merge_and_push_prod():
|
||||
"""Merge main into prod and push all branches."""
|
||||
logger.info("Merging main into prod...")
|
||||
current = git("branch", "--show-current").strip()
|
||||
|
||||
try:
|
||||
git("switch", "prod")
|
||||
git("merge", "main")
|
||||
git("switch", "main")
|
||||
logger.info("Pushing all branches...")
|
||||
git("push", "--all")
|
||||
logger.success("Merged and pushed to production.")
|
||||
finally:
|
||||
if current:
|
||||
git("switch", current)
|
||||
|
||||
|
||||
@app.command()
|
||||
def prod_clean():
|
||||
"""Clean all production build artifacts."""
|
||||
logger.info("Cleaning production build artifacts...")
|
||||
from plumbum.cmd import find, rm
|
||||
|
||||
root = get_project_root()
|
||||
with local.cwd(root):
|
||||
rm("-rf", ".venv", "build", "dist")
|
||||
for egg in local.path(".") // "*.egg-info":
|
||||
rm("-rf", egg)
|
||||
|
||||
try:
|
||||
find(
|
||||
".",
|
||||
"-type",
|
||||
"d",
|
||||
"-name",
|
||||
"__pycache__",
|
||||
"-exec",
|
||||
"rm",
|
||||
"-r",
|
||||
"{}",
|
||||
"+",
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
rm("-rf", "static", "node_modules")
|
||||
|
||||
logger.success("Clean complete. Re-create environment before next deploy.")
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
import trustme
|
||||
import typer
|
||||
from loguru import logger
|
||||
|
||||
from cli.config import config
|
||||
from cli.utils import docker_compose, get_project_root, get_repo_dir
|
||||
|
||||
app = typer.Typer(help="Tool for generating development SSL certificates.")
|
||||
|
||||
|
||||
@app.command()
|
||||
def generate():
|
||||
"""Generates a self-signed localhost certificate using trustme."""
|
||||
repo_dir = get_repo_dir()
|
||||
nginx_dir = repo_dir / "docker" / "nginx"
|
||||
|
||||
cert_path = repo_dir / config.ssl_cert_name
|
||||
key_path = repo_dir / config.ssl_key_name
|
||||
|
||||
if cert_path.exists() and key_path.exists():
|
||||
logger.info(f"Certificates already exist at {nginx_dir}. Skipping generation.")
|
||||
return
|
||||
|
||||
logger.info("Generating self-signed dev certificates using trustme...")
|
||||
|
||||
ca = trustme.CA()
|
||||
server_cert = ca.issue_cert("localhost", "127.0.0.1", "::1")
|
||||
|
||||
server_cert.private_key_pem.write_to_path(key_path)
|
||||
server_cert.cert_chain_pems[0].write_to_path(cert_path)
|
||||
|
||||
logger.success(f"Successfully generated {cert_path.name} and {key_path.name}.")
|
||||
|
||||
|
||||
@app.command()
|
||||
def fmt():
|
||||
"""Format codebase using prettier via npx."""
|
||||
logger.info("Running prettier via npx...")
|
||||
from plumbum.cmd import npx
|
||||
|
||||
try:
|
||||
npx(
|
||||
"prettier",
|
||||
"--write",
|
||||
"**/*.{js,jsx,ts,tsx,html,css,scss,sass,svelte,yaml,json,markdown}",
|
||||
)
|
||||
logger.success("Formatting complete.")
|
||||
except Exception as e:
|
||||
logger.error(f"Formatting failed: {e}")
|
||||
raise typer.Exit(1)
|
||||
|
||||
|
||||
@app.command()
|
||||
def build_wheels():
|
||||
"""Build and copy wheels for local packages (theme and config)."""
|
||||
from plumbum import local
|
||||
from plumbum.cmd import cp, direnv, rm
|
||||
|
||||
root = get_project_root()
|
||||
theme_dir = root.parent / config.theme_dir_name
|
||||
config_dir = root.parent / config.config_dir_name
|
||||
repo_dir = get_repo_dir()
|
||||
|
||||
logger.info("Building theme wheel...")
|
||||
with local.cwd(theme_dir):
|
||||
rm("-rf", "dist")
|
||||
direnv("exec", ".", "uv", "build", "--package", config.theme_dir_name)
|
||||
|
||||
logger.info("Building config wheel...")
|
||||
with local.cwd(config_dir):
|
||||
rm("-rf", "dist")
|
||||
direnv("exec", ".", "uv", "build", "--package", config.config_dir_name)
|
||||
|
||||
logger.info("Copying wheels to repository...")
|
||||
wheels_dir = repo_dir / config.local_wheels_dir
|
||||
wheels_dir.mkdir(exist_ok=True)
|
||||
rm("-f", local.path(str(wheels_dir)) // "*.whl")
|
||||
|
||||
for whl in local.path(str(theme_dir / "dist")) // "*.whl":
|
||||
cp(whl, wheels_dir)
|
||||
for whl in local.path(str(config_dir / "dist")) // "*.whl":
|
||||
cp(whl, wheels_dir)
|
||||
|
||||
logger.success("Successfully built and copied fresh wheels.")
|
||||
|
||||
|
||||
@app.command()
|
||||
def test_local():
|
||||
"""Rebuild and restart local docker stack with fresh wheels."""
|
||||
from plumbum import local
|
||||
from plumbum.cmd import curl, docker
|
||||
|
||||
build_wheels()
|
||||
|
||||
logger.info("Rebuilding and restarting local docker stack...")
|
||||
repo_dir = get_repo_dir()
|
||||
|
||||
with local.cwd(repo_dir):
|
||||
docker_compose("down")
|
||||
docker(
|
||||
"build",
|
||||
"-t",
|
||||
config.docker_image_name,
|
||||
"--no-cache",
|
||||
"--build-arg",
|
||||
"INSTALL_LOCAL_WHEELS=true",
|
||||
".",
|
||||
)
|
||||
docker_compose("up", "-d", "--wait")
|
||||
|
||||
setup_cmd = "invenio db init || true; invenio db create || true; invenio alembic upgrade || true; invenio index init || true"
|
||||
docker_compose("exec", "worker", "bash", "-c", setup_cmd)
|
||||
|
||||
try:
|
||||
curl("-skI", "https://127.0.0.1:8443/")
|
||||
logger.success("HTTPS verification successful.")
|
||||
except Exception:
|
||||
logger.warning("HTTPS verification failed.")
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import typer
|
||||
from loguru import logger
|
||||
|
||||
from cli.utils import get_project_root
|
||||
|
||||
app = typer.Typer(help="Environment validation and templating.")
|
||||
|
||||
import shutil
|
||||
|
||||
|
||||
@app.command()
|
||||
def template():
|
||||
"""Generate a .env.template file."""
|
||||
logger.info("Generating .env.template...")
|
||||
|
||||
source = get_project_root() / "cli" / "data" / "env.template"
|
||||
target = get_project_root() / ".env.template"
|
||||
|
||||
if not source.exists():
|
||||
logger.error(f"Template file not found at {source}")
|
||||
raise typer.Exit(1)
|
||||
|
||||
shutil.copy2(source, target)
|
||||
logger.success(f"Generated {target.name}")
|
||||
@@ -0,0 +1,110 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import boto3
|
||||
import typer
|
||||
from botocore.client import Config
|
||||
from loguru import logger
|
||||
|
||||
from cli.config import config
|
||||
from cli.utils import get_project_root
|
||||
|
||||
app = typer.Typer(help="Impossible Cloud S3 Management Tool")
|
||||
|
||||
|
||||
def get_s3_client():
|
||||
if not config.s3_access_key_id or not config.s3_secret_access_key:
|
||||
logger.warning(
|
||||
"S3_ACCESS_KEY_ID or S3_SECRET_ACCESS_KEY not found in environment. Boto3 will attempt to use default credential provider chain."
|
||||
)
|
||||
|
||||
kwargs = {
|
||||
"service_name": "s3",
|
||||
"endpoint_url": str(config.s3_endpoint_url),
|
||||
"region_name": config.s3_region,
|
||||
"config": Config(signature_version="s3v4"),
|
||||
}
|
||||
|
||||
if config.s3_access_key_id and config.s3_secret_access_key:
|
||||
kwargs["aws_access_key_id"] = config.s3_access_key_id
|
||||
kwargs["aws_secret_access_key"] = config.s3_secret_access_key.get_secret_value()
|
||||
else:
|
||||
logger.info("Using default AWS credential provider chain...")
|
||||
|
||||
return boto3.client(**kwargs)
|
||||
|
||||
|
||||
@app.command()
|
||||
def list_buckets():
|
||||
"""List all buckets in the S3 account."""
|
||||
client = get_s3_client()
|
||||
response = client.list_buckets()
|
||||
logger.info("Buckets:")
|
||||
for bucket in response.get("Buckets", []):
|
||||
logger.info(f" - {bucket['Name']}")
|
||||
|
||||
|
||||
@app.command()
|
||||
def create_bucket(bucket_name: str):
|
||||
"""Create a new bucket."""
|
||||
client = get_s3_client()
|
||||
try:
|
||||
if config.s3_region == "us-east-1":
|
||||
client.create_bucket(Bucket=bucket_name)
|
||||
else:
|
||||
client.create_bucket(
|
||||
Bucket=bucket_name,
|
||||
CreateBucketConfiguration={"LocationConstraint": config.s3_region},
|
||||
)
|
||||
logger.success(f"Successfully created bucket: {bucket_name}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error creating bucket {bucket_name}: {e}")
|
||||
raise typer.Exit(1)
|
||||
|
||||
|
||||
@app.command()
|
||||
def upload_file(
|
||||
file_path: Path = typer.Argument(..., help="Path to local file"),
|
||||
bucket_name: str = typer.Argument(..., help="Target bucket name"),
|
||||
object_name: str | None = typer.Option(
|
||||
None, "--object-name", help="S3 object name (defaults to file name)"
|
||||
),
|
||||
):
|
||||
"""Upload a local file to a bucket."""
|
||||
client = get_s3_client()
|
||||
if object_name is None:
|
||||
object_name = file_path.name
|
||||
try:
|
||||
client.upload_file(str(file_path), bucket_name, object_name)
|
||||
logger.success(f"Uploaded {file_path} to {bucket_name}/{object_name}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error uploading file: {e}")
|
||||
raise typer.Exit(1)
|
||||
|
||||
|
||||
@app.command()
|
||||
def apply_cors(
|
||||
bucket_name: str = typer.Argument(config.s3_bucket_name, help="Target bucket name"),
|
||||
cors_file: Path = typer.Option(
|
||||
get_project_root() / "cli" / "data" / "s3_cors.json",
|
||||
help="Path to CORS JSON file",
|
||||
),
|
||||
):
|
||||
"""Apply a CORS configuration from a JSON file to a bucket."""
|
||||
client = get_s3_client()
|
||||
|
||||
if not cors_file.exists():
|
||||
logger.error(f"CORS file not found: {cors_file}")
|
||||
raise typer.Exit(1)
|
||||
|
||||
try:
|
||||
with open(cors_file, "r") as f:
|
||||
cors_rules = json.load(f)
|
||||
|
||||
client.put_bucket_cors(
|
||||
Bucket=bucket_name, CORSConfiguration={"CORSRules": cors_rules}
|
||||
)
|
||||
logger.success(f"Successfully applied CORS configuration to {bucket_name}")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to apply CORS config: {e}")
|
||||
raise typer.Exit(1)
|
||||
@@ -0,0 +1,83 @@
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
from loguru import logger
|
||||
|
||||
|
||||
def get_project_root() -> Path:
|
||||
"""Dynamically determine the project root using git."""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["git", "rev-parse", "--show-toplevel"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
return Path(result.stdout.strip())
|
||||
except subprocess.CalledProcessError:
|
||||
logger.warning(
|
||||
"Not inside a git repository, falling back to script path resolution."
|
||||
)
|
||||
return Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
def get_repo_dir() -> Path:
|
||||
"""Return the repository directory path."""
|
||||
from cli.config import config
|
||||
|
||||
return get_project_root() / config.repo_dir_name
|
||||
|
||||
|
||||
def get_dynamic_s3_credentials() -> dict:
|
||||
import atexit
|
||||
|
||||
import boto3
|
||||
|
||||
from cli.bitwarden import lock as bw_lock
|
||||
from cli.bitwarden import login as bw_login
|
||||
from cli.bitwarden import pull as bw_pull
|
||||
|
||||
logger.info("Checking for native AWS credentials...")
|
||||
session = boto3.Session()
|
||||
creds = session.get_credentials()
|
||||
if creds and creds.access_key and creds.secret_key:
|
||||
logger.success("Found existing AWS credentials natively. Skipping Bitwarden.")
|
||||
return {
|
||||
"INVENIO_S3_ACCESS_KEY_ID": creds.access_key,
|
||||
"INVENIO_S3_SECRET_ACCESS_KEY": creds.secret_key,
|
||||
}
|
||||
|
||||
logger.info("No native AWS credentials found. Falling back to Bitwarden...")
|
||||
if bw_login():
|
||||
atexit.register(bw_lock)
|
||||
|
||||
return bw_pull()
|
||||
|
||||
|
||||
_deploy_env_vars = None
|
||||
|
||||
|
||||
def docker_compose(*args):
|
||||
global _deploy_env_vars
|
||||
import typer
|
||||
from plumbum import local
|
||||
from plumbum.cmd import docker
|
||||
|
||||
from cli.config import config
|
||||
|
||||
env_file = get_project_root() / ".env"
|
||||
|
||||
if not env_file.exists():
|
||||
logger.error(
|
||||
"The .env file does not exist! Please run `uv run cli bootstrap server` first to generate and configure it."
|
||||
)
|
||||
raise typer.Exit(1)
|
||||
|
||||
if _deploy_env_vars is None:
|
||||
_deploy_env_vars = get_dynamic_s3_credentials()
|
||||
|
||||
compose = docker[
|
||||
"compose", "-f", config.docker_compose_file, "--env-file", str(env_file)
|
||||
]
|
||||
with local.env(**_deploy_env_vars):
|
||||
return compose(*args)
|
||||
+11
@@ -7,6 +7,7 @@
|
||||
}: {
|
||||
packages = with pkgs; [
|
||||
awscli2
|
||||
bitwarden-cli
|
||||
cairo
|
||||
cairomm
|
||||
git
|
||||
@@ -18,6 +19,13 @@
|
||||
|
||||
dotenv.enable = true;
|
||||
|
||||
enterShell = ''
|
||||
# Only set the exit trap if we are NOT in a direnv subshell
|
||||
if [ -z "$DIRENV_DIR" ]; then
|
||||
trap 'uv run cli bw lock' EXIT
|
||||
fi
|
||||
'';
|
||||
|
||||
languages = {
|
||||
python = {
|
||||
enable = true;
|
||||
@@ -36,5 +44,8 @@
|
||||
cairomm
|
||||
]);
|
||||
NIX_LD = lib.fileContents "${pkgs.stdenv.cc}/nix-support/dynamic-linker";
|
||||
AWS_SHARED_CREDENTIALS_FILE = "${toString ./.}/.aws/credentials";
|
||||
AWS_CONFIG_FILE = "${toString ./.}/.aws/config";
|
||||
AWS_ENDPOINT_URL = "https://eu-west-1.storage.impossibleapi.net";
|
||||
};
|
||||
}
|
||||
|
||||
+7
-7
@@ -1,8 +1,8 @@
|
||||
inputs:
|
||||
nixpkgs:
|
||||
url: github:cachix/devenv-nixpkgs/rolling
|
||||
nixpkgs-python:
|
||||
url: github:cachix/nixpkgs-python
|
||||
inputs:
|
||||
nixpkgs:
|
||||
follows: nixpkgs
|
||||
nixpkgs:
|
||||
url: github:cachix/devenv-nixpkgs/rolling
|
||||
nixpkgs-python:
|
||||
url: github:cachix/nixpkgs-python
|
||||
inputs:
|
||||
nixpkgs:
|
||||
follows: nixpkgs
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
if [[ "$*" == *--dev* ]]; then
|
||||
echo "Configuring env in development mode"
|
||||
ENV_FILE="invenio_dev.env"
|
||||
else
|
||||
echo "Configuring env in production mode"
|
||||
ENV_FILE="invenio_prod.env"
|
||||
fi
|
||||
|
||||
{
|
||||
echo "# Secrets fetched from AWS Secrets Manager"
|
||||
aws secretsmanager get-secret-value --secret-id Invenio | \
|
||||
jq -r '.SecretString | fromjson | to_entries | .[] | .key + "=\"" + .value + "\""'
|
||||
echo ""
|
||||
} > secrets.env
|
||||
|
||||
cat secrets.env ./env/invenio.env "./env/$ENV_FILE" > .env
|
||||
rm secrets.env
|
||||
|
||||
echo "Environment set up using $ENV_FILE"
|
||||
Vendored
-18
@@ -1,18 +0,0 @@
|
||||
{
|
||||
debug
|
||||
}
|
||||
|
||||
localhost {
|
||||
reverse_proxy invenio-rdm:5000 {
|
||||
header_down Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"
|
||||
header_down Pragma "no-cache"
|
||||
header_down Expires "0"
|
||||
}
|
||||
|
||||
encode gzip
|
||||
|
||||
log {
|
||||
format console
|
||||
level DEBUG
|
||||
}
|
||||
}
|
||||
Vendored
-6
@@ -1,6 +0,0 @@
|
||||
# Development environment settings
|
||||
INVENIO_APP_ALLOWED_HOSTS=invenio.i-form.ie,localhost,localhost:8443,127.0.0.1,127.0.0.1:8443,0.0.0.0,0.0.0.0:8443
|
||||
INVENIO_SITE_UI_URL=https://localhost
|
||||
INVENIO_SITE_API_URL=https://localhost
|
||||
COMPOSE_PROFILES=development
|
||||
FLASK_DEBUG=true
|
||||
Vendored
-6
@@ -1,6 +0,0 @@
|
||||
# Production environment settings
|
||||
INVENIO_APP_ALLOWED_HOSTS=invenio.i-form.ie
|
||||
INVENIO_SITE_UI_URL=https://invenio.i-form.ie
|
||||
INVENIO_SITE_API_URL=https://invenio.i-form.ie/api
|
||||
COMPOSE_PROFILES=production
|
||||
FLASK_DEBUG=false
|
||||
Vendored
-8
@@ -1,8 +0,0 @@
|
||||
{
|
||||
admin off
|
||||
}
|
||||
|
||||
invenio.i-form.ie {
|
||||
reverse_proxy invenio-rdm:5000
|
||||
encode gzip
|
||||
}
|
||||
@@ -18,8 +18,11 @@ process.
|
||||
|
||||
Once running, visit https://127.0.0.1 in your browser.
|
||||
|
||||
**Note**: The server is using a self-signed SSL certificate, so your browser
|
||||
will issue a warning that you will have to by-pass.
|
||||
**Note**: The server uses a self-signed SSL certificate. You must generate it first by running:
|
||||
```console
|
||||
just generate-dev-certs
|
||||
```
|
||||
Your browser will issue a warning that you will have to by-pass.
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
subjects:
|
||||
pid-type: sub
|
||||
schemes:
|
||||
- id: FOS
|
||||
name: Fields of Science and Technology
|
||||
uri: "http://www.oecd.org/science/inno/38235147.pdf"
|
||||
data-file: vocabularies/subjects_oecd_fos.yaml
|
||||
pid-type: sub
|
||||
schemes:
|
||||
- id: FOS
|
||||
name: Fields of Science and Technology
|
||||
uri: "http://www.oecd.org/science/inno/38235147.pdf"
|
||||
data-file: vocabularies/subjects_oecd_fos.yaml
|
||||
# Minimal example vocabularies
|
||||
# can be used for quick testing, or a basis for building your own customized vocabularies.
|
||||
#names:
|
||||
|
||||
@@ -1,96 +1,96 @@
|
||||
- id: ara
|
||||
props:
|
||||
alpha_2: ar
|
||||
alpha_2: ar
|
||||
tags:
|
||||
- macrolanguage
|
||||
- living
|
||||
- macrolanguage
|
||||
- living
|
||||
title:
|
||||
en: Arabic
|
||||
en: Arabic
|
||||
- id: cym
|
||||
props:
|
||||
alpha_2: cy
|
||||
alpha_2: cy
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Welsh
|
||||
en: Welsh
|
||||
- id: deu
|
||||
props:
|
||||
alpha_2: de
|
||||
alpha_2: de
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: German
|
||||
en: German
|
||||
- id: eng
|
||||
props:
|
||||
alpha_2: en
|
||||
alpha_2: en
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: English
|
||||
en: English
|
||||
- id: fra
|
||||
props:
|
||||
alpha_2: fr
|
||||
alpha_2: fr
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: French
|
||||
en: French
|
||||
- id: ita
|
||||
props:
|
||||
alpha_2: it
|
||||
alpha_2: it
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Italian
|
||||
en: Italian
|
||||
- id: nor
|
||||
props:
|
||||
alpha_2: 'no'
|
||||
alpha_2: "no"
|
||||
tags:
|
||||
- macrolanguage
|
||||
- living
|
||||
- macrolanguage
|
||||
- living
|
||||
title:
|
||||
en: Norwegian
|
||||
en: Norwegian
|
||||
- id: roh
|
||||
props:
|
||||
alpha_2: rm
|
||||
alpha_2: rm
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Romansh
|
||||
en: Romansh
|
||||
- id: spa
|
||||
props:
|
||||
alpha_2: es
|
||||
alpha_2: es
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Spanish
|
||||
en: Spanish
|
||||
- id: tur
|
||||
props:
|
||||
alpha_2: tr
|
||||
alpha_2: tr
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Turkish
|
||||
en: Turkish
|
||||
- id: aag
|
||||
props:
|
||||
alpha_2: ''
|
||||
alpha_2: ""
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Ambrak
|
||||
en: Ambrak
|
||||
- id: aah
|
||||
props:
|
||||
alpha_2: ''
|
||||
alpha_2: ""
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Abu' Arapesh
|
||||
en: Abu' Arapesh
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
- affiliations:
|
||||
- name: University of Zurich
|
||||
- name: Humboldt University of Berlin
|
||||
- name: Kaiser Wilhelm Institute for Physics
|
||||
- name: University of Zurich
|
||||
- name: Humboldt University of Berlin
|
||||
- name: Kaiser Wilhelm Institute for Physics
|
||||
family_name: Einstein
|
||||
given_name: Albert
|
||||
id: gnd:118529579
|
||||
identifiers:
|
||||
- identifier: gnd:118529579
|
||||
scheme: gnd
|
||||
- identifier: gnd:118529579
|
||||
scheme: gnd
|
||||
- affiliations:
|
||||
- name: University of Cambridge
|
||||
- name: California Institute of Technology
|
||||
- name: University of Oxford
|
||||
- name: University of Cambridge
|
||||
- name: California Institute of Technology
|
||||
- name: University of Oxford
|
||||
family_name: Hawking
|
||||
given_name: Stephen
|
||||
id: 0000-0002-9079-593X
|
||||
identifiers:
|
||||
- identifier: https://orcid.org/0000-0002-9079-593X
|
||||
scheme: orcid
|
||||
- identifier: https://orcid.org/0000-0002-9079-593X
|
||||
scheme: orcid
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
* Add here all the overridden components of your app.
|
||||
*/
|
||||
|
||||
export const overriddenComponents = {}
|
||||
export const overriddenComponents = {};
|
||||
|
||||
@@ -17,8 +17,15 @@ services:
|
||||
- "INVENIO_SEARCH_HOSTS=['search:9200']"
|
||||
- "INVENIO_SECRET_KEY=CHANGE_ME"
|
||||
- "INVENIO_SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://i-form-data-repository:i-form-data-repository@db/i-form-data-repository"
|
||||
- "INVENIO_WSGI_PROXIES=2"
|
||||
- "INVENIO_WSGI_PROXIES=1"
|
||||
- "INVENIO_RATELIMIT_STORAGE_URL=redis://cache:6379/3"
|
||||
- "INVENIO_S3_ACCESS_KEY_ID=${INVENIO_S3_ACCESS_KEY_ID}"
|
||||
- "INVENIO_S3_SECRET_ACCESS_KEY=${INVENIO_S3_SECRET_ACCESS_KEY}"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "50m"
|
||||
max-file: "3"
|
||||
frontend:
|
||||
build:
|
||||
context: ./docker/nginx/
|
||||
@@ -28,6 +35,11 @@ services:
|
||||
ports:
|
||||
- "${DOCKER_SERVICES_IP_BIND:-127.0.0.1}:8080:80"
|
||||
- "${DOCKER_SERVICES_IP_BIND:-127.0.0.1}:8443:443"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "50m"
|
||||
max-file: "3"
|
||||
cache:
|
||||
image: docker.io/library/redis:7
|
||||
restart: "unless-stopped"
|
||||
@@ -35,14 +47,26 @@ services:
|
||||
ports:
|
||||
- "${DOCKER_SERVICES_IP_BIND:-127.0.0.1}:6379:6379"
|
||||
db:
|
||||
image: docker.io/library/postgres:14.13
|
||||
image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres:ubi8-14.11-0
|
||||
restart: "unless-stopped"
|
||||
environment:
|
||||
- "POSTGRES_USER=i-form-data-repository"
|
||||
- "POSTGRES_PASSWORD=i-form-data-repository"
|
||||
- "POSTGRES_DB=i-form-data-repository"
|
||||
- "PGBACKREST_REPO1_TYPE=s3"
|
||||
- "PGBACKREST_REPO1_S3_BUCKET=${INVENIO_S3_BUCKET_NAME}"
|
||||
- "PGBACKREST_REPO1_S3_ENDPOINT=${INVENIO_S3_ENDPOINT_URL}"
|
||||
- "PGBACKREST_REPO1_S3_KEY=${INVENIO_S3_ACCESS_KEY_ID}"
|
||||
- "PGBACKREST_REPO1_S3_KEY_SECRET=${INVENIO_S3_SECRET_ACCESS_KEY}"
|
||||
- "PGBACKREST_REPO1_S3_REGION=${INVENIO_S3_REGION_NAME}"
|
||||
- "PGBACKREST_REPO1_PATH=/backup/meta_db"
|
||||
ports:
|
||||
- "${DOCKER_SERVICES_IP_BIND:-127.0.0.1}:5432:5432"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "50m"
|
||||
max-file: "3"
|
||||
pgadmin:
|
||||
image: docker.io/dpage/pgadmin4:6
|
||||
restart: "unless-stopped"
|
||||
@@ -66,7 +90,7 @@ services:
|
||||
# settings only for development. DO NOT use in production!
|
||||
- bootstrap.memory_lock=true
|
||||
- "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||
- "OPENSEARCH_INITIAL_ADMIN_PASSWORD=guekxe3mvqieke1!%&ieIADE"
|
||||
- "OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_PASSWORD:-guekxe3mvqieke1!%&ieIADE}"
|
||||
- "DISABLE_INSTALL_DEMO_CONFIG=true"
|
||||
- "DISABLE_SECURITY_PLUGIN=true"
|
||||
- "discovery.type=single-node"
|
||||
@@ -82,6 +106,11 @@ services:
|
||||
ports:
|
||||
- "${DOCKER_SERVICES_IP_BIND:-127.0.0.1}:9200:9200"
|
||||
- "${DOCKER_SERVICES_IP_BIND:-127.0.0.1}:9600:9600"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "50m"
|
||||
max-file: "3"
|
||||
opensearch-dashboards:
|
||||
image: docker.io/opensearchproject/opensearch-dashboards:2.17.1
|
||||
ports:
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
test.crt
|
||||
test.key
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"Servers": {
|
||||
"1": {
|
||||
"Name": "i-form-data-repository-db",
|
||||
"Group": "Servers",
|
||||
"Host": "i-form-data-repository-db-1",
|
||||
"Port": 5432,
|
||||
"MaintenanceDB": "postgres",
|
||||
"Username": "i-form-data-repository",
|
||||
"SSLMode": "prefer"
|
||||
"Servers": {
|
||||
"1": {
|
||||
"Name": "i-form-data-repository-db",
|
||||
"Group": "Servers",
|
||||
"Host": "i-form-data-repository-db-1",
|
||||
"Port": 5432,
|
||||
"MaintenanceDB": "postgres",
|
||||
"Username": "i-form-data-repository",
|
||||
"SSLMode": "prefer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +1,46 @@
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import json
|
||||
|
||||
|
||||
def main():
|
||||
# 1. Ensure ga directories exist and have translations.json
|
||||
packages = [
|
||||
'invenio_communities',
|
||||
'invenio_search_ui',
|
||||
'invenio_app_rdm',
|
||||
'invenio_requests',
|
||||
'invenio_jobs',
|
||||
'invenio_rdm_records',
|
||||
'invenio_administration'
|
||||
"invenio_communities",
|
||||
"invenio_search_ui",
|
||||
"invenio_app_rdm",
|
||||
"invenio_requests",
|
||||
"invenio_jobs",
|
||||
"invenio_rdm_records",
|
||||
"invenio_administration",
|
||||
]
|
||||
bases = [
|
||||
'/opt/invenio/src/.venv/lib/python3.12/site-packages',
|
||||
'/opt/invenio/var/instance/assets/translations'
|
||||
"/opt/invenio/src/.venv/lib/python3.12/site-packages",
|
||||
"/opt/invenio/var/instance/assets/translations",
|
||||
]
|
||||
for pkg in packages:
|
||||
for base in bases:
|
||||
for root, dirs, files_in_dir in os.walk(base):
|
||||
if root.endswith('messages') and pkg in root:
|
||||
ga_dir = os.path.join(root, 'ga')
|
||||
if root.endswith("messages") and pkg in root:
|
||||
ga_dir = os.path.join(root, "ga")
|
||||
os.makedirs(ga_dir, exist_ok=True)
|
||||
json_path = os.path.join(ga_dir, 'translations.json')
|
||||
json_path = os.path.join(ga_dir, "translations.json")
|
||||
if not os.path.exists(json_path) or os.path.getsize(json_path) <= 2:
|
||||
with open(json_path, 'w') as fp:
|
||||
fp.write('{}')
|
||||
with open(json_path, "w") as fp:
|
||||
fp.write("{}")
|
||||
print(f"Created empty translations.json: {json_path}")
|
||||
|
||||
# 2. Copy the actual compiled translations if they exist
|
||||
copies = [
|
||||
(
|
||||
'/opt/invenio/src/.venv/lib/python3.12/site-packages/invenio_communities/assets/semantic-ui/translations/invenio_communities/messages/ga/translations.json',
|
||||
'/opt/invenio/var/instance/assets/translations/invenio_communities/messages/ga/translations.json'
|
||||
"/opt/invenio/src/.venv/lib/python3.12/site-packages/invenio_communities/assets/semantic-ui/translations/invenio_communities/messages/ga/translations.json",
|
||||
"/opt/invenio/var/instance/assets/translations/invenio_communities/messages/ga/translations.json",
|
||||
),
|
||||
(
|
||||
'/opt/invenio/src/.venv/lib/python3.12/site-packages/invenio_search_ui/assets/semantic-ui/translations/invenio_search_ui/messages/ga/translations.json',
|
||||
'/opt/invenio/var/instance/assets/translations/invenio_search_ui/messages/ga/translations.json'
|
||||
)
|
||||
"/opt/invenio/src/.venv/lib/python3.12/site-packages/invenio_search_ui/assets/semantic-ui/translations/invenio_search_ui/messages/ga/translations.json",
|
||||
"/opt/invenio/var/instance/assets/translations/invenio_search_ui/messages/ga/translations.json",
|
||||
),
|
||||
]
|
||||
for src, dst in copies:
|
||||
if os.path.exists(src):
|
||||
@@ -48,57 +49,68 @@ def main():
|
||||
print(f"Copied compiled translations: {src} -> {dst}")
|
||||
|
||||
# 3. Extract app_rdm translations from global ga.json
|
||||
global_ga = '/opt/invenio/var/instance/translations/ga.json'
|
||||
app_rdm_dst = '/opt/invenio/var/instance/assets/translations/invenio_app_rdm/messages/ga/translations.json'
|
||||
global_ga = "/opt/invenio/var/instance/translations/ga.json"
|
||||
app_rdm_dst = "/opt/invenio/var/instance/assets/translations/invenio_app_rdm/messages/ga/translations.json"
|
||||
if os.path.exists(global_ga):
|
||||
try:
|
||||
with open(global_ga, 'r') as fp:
|
||||
with open(global_ga, "r") as fp:
|
||||
ga_data = json.load(fp)
|
||||
app_rdm_data = ga_data.get('invenio_app_rdm', {})
|
||||
app_rdm_data = ga_data.get("invenio_app_rdm", {})
|
||||
os.makedirs(os.path.dirname(app_rdm_dst), exist_ok=True)
|
||||
with open(app_rdm_dst, 'w') as fp:
|
||||
with open(app_rdm_dst, "w") as fp:
|
||||
json.dump(app_rdm_data, fp, indent=2)
|
||||
print(f"Extracted invenio_app_rdm translations to {app_rdm_dst}")
|
||||
|
||||
|
||||
# Also extract search_ui and communities if they were not copied
|
||||
search_ui_dst = '/opt/invenio/var/instance/assets/translations/invenio_search_ui/messages/ga/translations.json'
|
||||
if 'invenio_search_ui' in ga_data:
|
||||
search_ui_dst = "/opt/invenio/var/instance/assets/translations/invenio_search_ui/messages/ga/translations.json"
|
||||
if "invenio_search_ui" in ga_data:
|
||||
os.makedirs(os.path.dirname(search_ui_dst), exist_ok=True)
|
||||
with open(search_ui_dst, 'w') as fp:
|
||||
json.dump(ga_data['invenio_search_ui'], fp, indent=2)
|
||||
with open(search_ui_dst, "w") as fp:
|
||||
json.dump(ga_data["invenio_search_ui"], fp, indent=2)
|
||||
print(f"Extracted invenio_search_ui translations to {search_ui_dst}")
|
||||
|
||||
communities_dst = '/opt/invenio/var/instance/assets/translations/invenio_communities/messages/ga/translations.json'
|
||||
if 'invenio_communities' in ga_data:
|
||||
|
||||
communities_dst = "/opt/invenio/var/instance/assets/translations/invenio_communities/messages/ga/translations.json"
|
||||
if "invenio_communities" in ga_data:
|
||||
os.makedirs(os.path.dirname(communities_dst), exist_ok=True)
|
||||
with open(communities_dst, 'w') as fp:
|
||||
json.dump(ga_data['invenio_communities'], fp, indent=2)
|
||||
print(f"Extracted invenio_communities translations to {communities_dst}")
|
||||
with open(communities_dst, "w") as fp:
|
||||
json.dump(ga_data["invenio_communities"], fp, indent=2)
|
||||
print(
|
||||
f"Extracted invenio_communities translations to {communities_dst}"
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Error extracting translations: {e}")
|
||||
|
||||
# 4. Patch all _generatedTranslations.js files
|
||||
files = glob.glob('/opt/invenio/src/.venv/lib/python3.12/site-packages/**/_generatedTranslations.js', recursive=True) + glob.glob('/opt/invenio/var/instance/assets/**/_generatedTranslations.js', recursive=True)
|
||||
files = glob.glob(
|
||||
"/opt/invenio/src/.venv/lib/python3.12/site-packages/**/_generatedTranslations.js",
|
||||
recursive=True,
|
||||
) + glob.glob(
|
||||
"/opt/invenio/var/instance/assets/**/_generatedTranslations.js", recursive=True
|
||||
)
|
||||
for f in files:
|
||||
with open(f, 'r') as fp:
|
||||
with open(f, "r") as fp:
|
||||
content = fp.read()
|
||||
if 'TRANSLATE_GA' not in content:
|
||||
lines = content.split('\n')
|
||||
if "TRANSLATE_GA" not in content:
|
||||
lines = content.split("\n")
|
||||
last_import = -1
|
||||
for i, line in enumerate(lines):
|
||||
if line.startswith('import '):
|
||||
if line.startswith("import "):
|
||||
last_import = i
|
||||
if last_import != -1:
|
||||
lines.insert(last_import + 1, 'import TRANSLATE_GA from "./ga/translations.json";')
|
||||
content = '\n'.join(lines)
|
||||
if 'export const translations = {' in content:
|
||||
content = content.replace(
|
||||
'export const translations = {',
|
||||
'export const translations = {\n ga: { translation: TRANSLATE_GA },'
|
||||
lines.insert(
|
||||
last_import + 1,
|
||||
'import TRANSLATE_GA from "./ga/translations.json";',
|
||||
)
|
||||
with open(f, 'w') as fp:
|
||||
content = "\n".join(lines)
|
||||
if "export const translations = {" in content:
|
||||
content = content.replace(
|
||||
"export const translations = {",
|
||||
"export const translations = {\n ga: { translation: TRANSLATE_GA },",
|
||||
)
|
||||
with open(f, "w") as fp:
|
||||
fp.write(content)
|
||||
print(f"Patched _generatedTranslations.js: {f}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from flask import Blueprint
|
||||
|
||||
|
||||
#
|
||||
# Registration
|
||||
#
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
{
|
||||
"invenio_search_ui": {
|
||||
"invenio_search_ui:Search records...": "Cuardaigh taifid..."
|
||||
},
|
||||
"invenio_communities": {
|
||||
"invenio_communities:You are not a member of any community.": "Níl tú mar bhall d'aon phobal.",
|
||||
"invenio_communities:There are no new communities.": "Níl aon phobail nua ann.",
|
||||
"invenio_communities:My Communities": "Mo Phobail",
|
||||
"invenio_communities:New Communities": "Pobail Nua",
|
||||
"invenio_communities:Search communities...": "Cuardaigh pobail...",
|
||||
"invenio_communities:Organize, curate and share your research. Ideal for research projects, departments or temporary working groups.": "Eagraigh, coimeád agus comhroinn do chuid taighde. Ideal do thionscadail taighde, ranna nó grúpaí oibre sealadacha."
|
||||
},
|
||||
"invenio_app_rdm": {
|
||||
"invenio_app_rdm:Search records...": "Cuardaigh taifid...",
|
||||
"invenio_app_rdm:Search in my communities": "Cuardaigh i mo phobail",
|
||||
"invenio_app_rdm:Search in my communities...": "Cuardaigh i mo phobail...",
|
||||
"invenio_app_rdm:My communities": "Mo phobail",
|
||||
"invenio_app_rdm:Search in my uploads...": "Cuardaigh i mo chuid uaslódálacha...",
|
||||
"invenio_app_rdm:My uploads": "Mo chuid uaslódálacha",
|
||||
"invenio_app_rdm:Overview": "Foramharc",
|
||||
"invenio_app_rdm:Uploads": "Uaslódálacha"
|
||||
}
|
||||
"invenio_search_ui": {
|
||||
"invenio_search_ui:Search records...": "Cuardaigh taifid..."
|
||||
},
|
||||
"invenio_communities": {
|
||||
"invenio_communities:You are not a member of any community.": "Níl tú mar bhall d'aon phobal.",
|
||||
"invenio_communities:There are no new communities.": "Níl aon phobail nua ann.",
|
||||
"invenio_communities:My Communities": "Mo Phobail",
|
||||
"invenio_communities:New Communities": "Pobail Nua",
|
||||
"invenio_communities:Search communities...": "Cuardaigh pobail...",
|
||||
"invenio_communities:Organize, curate and share your research. Ideal for research projects, departments or temporary working groups.": "Eagraigh, coimeád agus comhroinn do chuid taighde. Ideal do thionscadail taighde, ranna nó grúpaí oibre sealadacha."
|
||||
},
|
||||
"invenio_app_rdm": {
|
||||
"invenio_app_rdm:Search records...": "Cuardaigh taifid...",
|
||||
"invenio_app_rdm:Search in my communities": "Cuardaigh i mo phobail",
|
||||
"invenio_app_rdm:Search in my communities...": "Cuardaigh i mo phobail...",
|
||||
"invenio_app_rdm:My communities": "Mo phobail",
|
||||
"invenio_app_rdm:Search in my uploads...": "Cuardaigh i mo chuid uaslódálacha...",
|
||||
"invenio_app_rdm:My uploads": "Mo chuid uaslódálacha",
|
||||
"invenio_app_rdm:Overview": "Foramharc",
|
||||
"invenio_app_rdm:Uploads": "Uaslódálacha"
|
||||
}
|
||||
}
|
||||
|
||||
-443
File diff suppressed because one or more lines are too long
@@ -1,161 +0,0 @@
|
||||
update auto-rollback="false":
|
||||
#!/usr/bin/env bash
|
||||
if [ ! -f update.lock ]; then
|
||||
touch update.lock
|
||||
just tag-version
|
||||
cd i-form-data-repository && docker compose -f docker-compose.full.yml --env-file ../.env down
|
||||
git pull
|
||||
cd i-form-data-repository && docker compose -f docker-compose.full.yml --env-file ../.env pull
|
||||
cd i-form-data-repository && docker compose -f docker-compose.full.yml --env-file ../.env build
|
||||
cd i-form-data-repository && docker compose -f docker-compose.full.yml --env-file ../.env up -d --wait
|
||||
rm update.lock
|
||||
if [ "{{auto-rollback}}" = "true" ]; then
|
||||
just healthcheck || just rollback
|
||||
else
|
||||
just healthcheck || echo "Healthcheck failed. Consider rolling back by running \"just rollback\" manually if needed."
|
||||
fi
|
||||
else
|
||||
echo "Update already in progress"
|
||||
fi
|
||||
|
||||
merge-and-push-prod:
|
||||
#!/usr/bin/env bash
|
||||
git switch prod
|
||||
git merge main
|
||||
git switch main
|
||||
git push --all
|
||||
|
||||
tag-version:
|
||||
#!/usr/bin/env bash
|
||||
git tag backup-$(date +%Y%m%d-%H%M%S)
|
||||
mkdir -p versions
|
||||
cd i-form-data-repository && docker compose -f docker-compose.full.yml --env-file ../.env images | grep -v "REPOSITORY" > ../versions/$(date +%Y%m%d-%H%M%S).txt
|
||||
|
||||
healthcheck:
|
||||
#!/usr/bin/env bash
|
||||
for i in 1 2 3; do
|
||||
curl -f http://localhost/health && exit 0
|
||||
sleep 5
|
||||
done
|
||||
exit 1
|
||||
|
||||
rollback version="":
|
||||
#!/usr/bin/env bash
|
||||
current_branch=$(git branch --show-current)
|
||||
if [ -z "{{version}}" ]; then # Get last backup tag if no version specified
|
||||
version=$(git tag | grep backup | sort -r | head -n1)
|
||||
else # Or get the specified version
|
||||
version="backup-{{version}}"
|
||||
fi
|
||||
|
||||
# Find corresponding version file
|
||||
version_date=${version#backup-} # Remove 'backup-' prefix
|
||||
version_file="versions/$version_date.txt"
|
||||
|
||||
if [ ! -f "$version_file" ]; then
|
||||
echo "No version file found for $version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Read the old image versions and pull them specifically
|
||||
while read -r repo tag image_id _; do
|
||||
if [ ! -z "$repo" ]; then
|
||||
docker pull "$repo:$tag"
|
||||
fi
|
||||
done < "$version_file"
|
||||
|
||||
# Then check out the version and update
|
||||
git checkout $version
|
||||
cd i-form-data-repository && docker compose -f docker-compose.full.yml --env-file ../.env down
|
||||
cd i-form-data-repository && docker compose -f docker-compose.full.yml --env-file ../.env build --no-cache
|
||||
cd i-form-data-repository && docker compose -f docker-compose.full.yml --env-file ../.env up -d
|
||||
git switch $current_branch # Return to original branch
|
||||
|
||||
cleanup-versions:
|
||||
#!/usr/bin/env bash
|
||||
# Keep last 5 backup tags
|
||||
for tag in $(git tag | grep backup | sort -r | tail -n +6); do
|
||||
git tag -d $tag
|
||||
rm -f "versions/${tag#backup-}.txt"
|
||||
done
|
||||
|
||||
deploy *args:
|
||||
./env.sh {{args}}
|
||||
cd i-form-data-repository && docker compose -f docker-compose.full.yml --env-file ../.env up -d --wait
|
||||
cd i-form-data-repository && docker compose -f docker-compose.full.yml --env-file ../.env exec worker bash -c "invenio db init || true; invenio db create || true; invenio alembic upgrade || true; invenio index init || true"
|
||||
|
||||
fmt:
|
||||
bun run prettier --write "**/*.{js,jsx,ts,tsx,html,css,scss,sass,svelte,yaml,json,markdown}"
|
||||
|
||||
[working-directory("../invenio-theme-iform/")]
|
||||
build-theme-wheel:
|
||||
rm -rf dist
|
||||
direnv exec . uv build --package invenio-theme-iform
|
||||
|
||||
[working-directory("../invenio-config-iform/")]
|
||||
build-config-wheel:
|
||||
rm -rf dist
|
||||
direnv exec . uv build --package invenio-config-iform
|
||||
|
||||
build-wheels: build-theme-wheel build-config-wheel
|
||||
echo "Building fresh wheels for local packages..."
|
||||
mkdir -p i-form-data-repository/local_wheels
|
||||
rm -f i-form-data-repository/local_wheels/*.whl
|
||||
cp ../invenio-theme-iform/dist/*.whl i-form-data-repository/local_wheels/
|
||||
cp ../invenio-config-iform/dist/*.whl i-form-data-repository/local_wheels/
|
||||
|
||||
test-local: build-wheels
|
||||
#!/usr/bin/env bash
|
||||
echo "Rebuilding and restarting local docker stack..."
|
||||
cd i-form-data-repository
|
||||
docker compose -f docker-compose.full.yml --env-file ../.env down
|
||||
docker build -t i-form-data-repository:latest --no-cache --build-arg INSTALL_LOCAL_WHEELS=true .
|
||||
docker compose -f docker-compose.full.yml --env-file ../.env up -d --wait
|
||||
docker compose -f docker-compose.full.yml --env-file ../.env exec worker bash -c "invenio db init || true; invenio db create || true; invenio alembic upgrade || true; invenio index init || true"
|
||||
curl -skI https://127.0.0.1:8443/ || echo "HTTPS verification failed"
|
||||
# Production deployment commands using Docker/Podman
|
||||
|
||||
# Load AWS secrets (adjust path as needed)
|
||||
load-aws-secrets:
|
||||
@if [ -f aws_secrets.sh ]; then . ./aws_secrets.sh; else echo "AWS secrets file not found"; exit 1; fi
|
||||
|
||||
# First-time deployment to production
|
||||
prod-deploy: load-aws-secrets build-wheels
|
||||
#!/usr/bin/env bash
|
||||
echo "Deploying to production (first-time)..."
|
||||
git switch prod
|
||||
git pull origin prod
|
||||
# Build and start containers
|
||||
cd i-form-data-repository
|
||||
docker build -t i-form-data-repository:latest --no-cache --build-arg INSTALL_LOCAL_WHEELS=true .
|
||||
docker compose -f docker-compose.full.yml --env-file ../.env up -d --wait
|
||||
# Run initial database setup, migrations, and collect static assets
|
||||
docker compose -f docker-compose.full.yml --env-file ../.env exec worker bash -c " \
|
||||
invenio db init && \
|
||||
invenio db create && \
|
||||
invenio alembic upgrade head && \
|
||||
invenio collect -v && \
|
||||
invenio index init \
|
||||
"
|
||||
|
||||
# Update production without full redeploy (pull + migrations + static)
|
||||
prod-update: load-aws-secrets build-wheels
|
||||
#!/usr/bin/env bash
|
||||
echo "Updating production deployment..."
|
||||
git switch prod
|
||||
git pull origin prod
|
||||
cd i-form-data-repository
|
||||
docker build -t i-form-data-repository:latest --no-cache --build-arg INSTALL_LOCAL_WHEELS=true .
|
||||
docker compose -f docker-compose.full.yml --env-file ../.env up -d --wait
|
||||
docker compose -f docker-compose.full.yml --env-file ../.env exec worker bash -c " \
|
||||
invenio alembic upgrade head && \
|
||||
invenio collect -v \
|
||||
"
|
||||
|
||||
# Clean all build artefacts and environment
|
||||
prod-clean:
|
||||
@echo "Cleaning production build artefacts..."
|
||||
rm -rf .venv build dist *.egg-info
|
||||
find . -type d -name "__pycache__" -exec rm -r {} + || true
|
||||
rm -rf static node_modules
|
||||
echo "Clean complete. Re‑create environment before next deploy."
|
||||
+47
-1
@@ -4,4 +4,50 @@ version = "0.1.0"
|
||||
description = "The source code for the I-Form Data Repository"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = ["invenio-cli>=1.9.2"]
|
||||
dependencies = [
|
||||
"boto3>=1.43.68",
|
||||
"bumpver>=2026.1132",
|
||||
"click-repl>=0.3.0",
|
||||
"invenio-cli>=1.9.2",
|
||||
"loguru>=0.7.3",
|
||||
"plumbum>=2.0.2",
|
||||
"pydantic-settings>=2.15.0",
|
||||
"python-dotenv>=1.2.2",
|
||||
"requests>=2.32.5",
|
||||
"trustme>=1.2.1",
|
||||
"typer>=0.27.1",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
cli = "cli.__main__:app"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pre-commit>=3.5.0",
|
||||
"ruff>=0.16.2",
|
||||
"ty>=0.0.70",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.ruff.lint]
|
||||
ignore = ["BLE001", "B008", "S110", "C408"]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["cli"]
|
||||
|
||||
[tool.bumpver]
|
||||
current_version = "2026.8.1"
|
||||
version_pattern = "YYYY.MM.INC0"
|
||||
commit_message = "bump version {old_version} -> {new_version}"
|
||||
commit = true
|
||||
tag = true
|
||||
push = false
|
||||
|
||||
[tool.bumpver.file_patterns]
|
||||
"pyproject.toml" = [
|
||||
'version = "{version}"',
|
||||
]
|
||||
|
||||
|
||||
@@ -2,6 +2,24 @@ version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "annotated-doc"
|
||||
version = "0.0.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5a/8e/38aa427ed5402449e226975b649c5dc73ccadfefeb95e6aecb8f8ea4b6b6/annotated_doc-0.0.5.tar.gz", hash = "sha256:c7e58ce09192557605d8bbd92836d7e1d520ac9580096042c0bfd197efacf1bb", size = 10758, upload-time = "2026-07-28T13:50:58.129Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/30/e900b21425a860e195f32e37657aa1f7c7f2b1bfb26f03ca209b90933c06/annotated_doc-0.0.5-py3-none-any.whl", hash = "sha256:117bac03a25ede5df5440e855b32d556049ca169ead221505badf432fed4b101", size = 5302, upload-time = "2026-07-28T13:50:57.239Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "annotated-types"
|
||||
version = "0.8.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5f/56/a8120250d128bed162cd73c76d45f6ef9991f3e068f62a8ee060afa3104a/annotated_types-0.8.0.tar.gz", hash = "sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7", size = 15893, upload-time = "2026-07-23T20:16:13.995Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/99/91/8acff4f5e50511b911bbccb72b8628a49c68ce14148cd9f6431094859a90/annotated_types-0.8.0-py3-none-any.whl", hash = "sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0", size = 13427, upload-time = "2026-07-23T20:16:12.938Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrow"
|
||||
version = "1.4.0"
|
||||
@@ -36,6 +54,49 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/24/7e/f7b6f453e6481d1e233540262ccbfcf89adcd43606f44a028d7f5fae5eb2/binaryornot-0.4.4-py2.py3-none-any.whl", hash = "sha256:b8b71173c917bddcd2c16070412e369c3ed7f0528926f70cac18a6c97fd563e4", size = 9006, upload-time = "2017-08-03T15:55:31.23Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "boto3"
|
||||
version = "1.43.68"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "botocore" },
|
||||
{ name = "jmespath" },
|
||||
{ name = "s3transfer" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/35/40/95db6388539e6194b7d8863e4228263e7a778fff0164b17d0e4530d44ce2/boto3-1.43.68.tar.gz", hash = "sha256:4be7531c45fbf8eb145ecd0f385c7b8f9d66ba2fd0c256522717260e67fca89d", size = 112664, upload-time = "2026-08-10T19:22:07.864Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/96/bd/36dd3f5718160ea7f8ef5a81b461cfb9d0f0b289bb31ed416ae6a1cbfee3/boto3-1.43.68-py3-none-any.whl", hash = "sha256:4be071482312d05ea345ae8a2ea307637d3e2f4fdce44b8ebeb0192929aa2644", size = 140027, upload-time = "2026-08-10T19:22:05.592Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "botocore"
|
||||
version = "1.43.68"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "jmespath" },
|
||||
{ name = "python-dateutil" },
|
||||
{ name = "urllib3" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e1/dc/ff7e35ecb25e2584e22ce8d5a13c5f991687597fd77d7cc388f2e4768cf3/botocore-1.43.68.tar.gz", hash = "sha256:a6c7ac88724c96f2ad5a7657f87d545d8218a74a1b219ba4397e3d37481941cd", size = 15894825, upload-time = "2026-08-10T19:22:02.501Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/32/48/18dc095a908da94e2389d8e4127f4438b185dfd2dd9190fe6f946b9f41ac/botocore-1.43.68-py3-none-any.whl", hash = "sha256:9985c6eb9b7896f88bd89c07d543accd6985ea772af9d796087012ad40f78420", size = 15579433, upload-time = "2026-08-10T19:21:58.157Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpver"
|
||||
version = "2026.1132"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "colorama" },
|
||||
{ name = "lexid" },
|
||||
{ name = "toml" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/25/22/c0c9bf9e7ad6877e4c7c3dedd464e390d9fadb8927c61d6d77547eb17539/bumpver-2026.1132.tar.gz", hash = "sha256:80b223c23fca9bc9dd569b7a44680949d34bee23a738860d9a9b36f1abe3b0e0", size = 116784, upload-time = "2026-05-22T18:40:32.333Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ab/d6/45c1bf6bcf7b3f174ec0c7fe2d7dce773cbc853cfd8fde06c3153104ffff/bumpver-2026.1132-py2.py3-none-any.whl", hash = "sha256:b060170e7ff5d9ad7043a9d3d6288c7175f9c126744d08a2d6ef9b8377f6bd60", size = 65963, upload-time = "2026-05-22T18:40:30.515Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2025.11.12"
|
||||
@@ -45,6 +106,100 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cffi"
|
||||
version = "2.1.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pycparser", marker = "implementation_name != 'PyPy'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9e/ef/008a1939e372c06329a3fce4279c02f328488f3526744906eeec3da7ad5f/cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be", size = 530807, upload-time = "2026-08-03T21:21:18.939Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/10/69/43965eccfdead3b9220015fd1320e117be8c6ed01a62ffab76eeb752f5d5/cffi-2.1.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0", size = 184821, upload-time = "2026-08-03T21:19:44.887Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/7d/16e5a096677b5e313ca80cd5e5170efa3ea44624a82bb111925522da64b1/cffi-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf", size = 184719, upload-time = "2026-08-03T21:19:46.129Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/56/e6/8941622732edec876dd17d0453dce07317ae96db34f2ec1436c9d3785986/cffi-2.1.1-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a", size = 214799, upload-time = "2026-08-03T21:19:47.218Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/de/f98430906df1545ffde0d543dd124a7a439bc2cd32b36b9c53f805df7333/cffi-2.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890", size = 222389, upload-time = "2026-08-03T21:19:48.331Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/5b/717f1526b9957b34456313c31645c5b82b8fb5c3fe9e4752999be7128bfc/cffi-2.1.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50", size = 210249, upload-time = "2026-08-03T21:19:49.543Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/b3/f8aa4f3e34986c7e4ec45072d1b1b9dd295b6b18007b45518d79726dd725/cffi-2.1.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e", size = 208775, upload-time = "2026-08-03T21:19:50.918Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/db/dceb9dd5b231e1da801793f8acc9f3c52a7e1afe40bb1aae37e02b0faad5/cffi-2.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf", size = 221822, upload-time = "2026-08-03T21:19:52.054Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/d2/6cd24ae3be000a634109c247d1475d62e5616d0dc78c82770942ec384248/cffi-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517", size = 225232, upload-time = "2026-08-03T21:19:53.109Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/52/3fa190537004dd7f0ab860a6dc7c0175b8667f68d1e618a46f5498d30250/cffi-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735", size = 223597, upload-time = "2026-08-03T21:19:54.515Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/fb/0bb75b7039588c074b37ae99f40d9bfddf990ecb2fbc346ebccd2e56b9be/cffi-2.1.1-cp312-cp312-win32.whl", hash = "sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e", size = 175292, upload-time = "2026-08-03T21:19:55.566Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/79/615cc094e2fb508cade7de88d3b4f6c4ec2bab695c97bce9153dc65aadf5/cffi-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a", size = 185919, upload-time = "2026-08-03T21:19:56.89Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/c6/d0ea84713fe46b243a436a18fcd47d639732747e21635c8a27191b06dc30/cffi-2.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80", size = 180093, upload-time = "2026-08-03T21:19:58.155Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/f4/035513d4117049066b4779dc3b7c0c0fdad175fa13731c9f4003f1cd1478/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e", size = 194248, upload-time = "2026-08-03T21:19:59.399Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/af/2aeb4dbb5fc41a04161ae9ff1518de7cec08e164f44a8ce6a4cf7fd2cd1d/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c", size = 196908, upload-time = "2026-08-03T21:20:00.746Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/46/2e5fdde8555706dd98139a910ca11be02809f3f605ce956f655d0214e100/cffi-2.1.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6", size = 184805, upload-time = "2026-08-03T21:20:02.02Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/41/4c7042f317b9217502988f0873af87e16ad606dc20f84e546e3e6ce9764c/cffi-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971", size = 184764, upload-time = "2026-08-03T21:20:03.141Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/1f/1c3d90d91811c8f86ced9ed637956c54bfe5b79ca98fe976d7f8c8979f6b/cffi-2.1.1-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c", size = 214722, upload-time = "2026-08-03T21:20:04.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/6f/3b5ce4c3b2192d250f04908f2bfd91ef34552ec8f7716a5d4abdb8d67bb2/cffi-2.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125", size = 222369, upload-time = "2026-08-03T21:20:05.544Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/10/4b3c75dde3d9663c9e02ba05c2668b954f671d4bbe346413ca8c696b295a/cffi-2.1.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264", size = 210175, upload-time = "2026-08-03T21:20:06.75Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/62/14f74b9543e605d17701dc797b815958b8bb70b7624ce1b832ddad48ed6c/cffi-2.1.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3", size = 208670, upload-time = "2026-08-03T21:20:08.04Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/95/86342356ff5953b3fb06f7ef7c5bee212d45e770abc7218d451b9148313c/cffi-2.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2", size = 221824, upload-time = "2026-08-03T21:20:09.274Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/ff/7b3429ff53aafe931ed8a5fc69f481bbef7ba6de87ddcbb63d08f483f613/cffi-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b", size = 225148, upload-time = "2026-08-03T21:20:10.7Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/34/a95870b9221e09cf4f2ce3178b1a210abdfe63a1bd357da940418d7b8d15/cffi-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7", size = 223564, upload-time = "2026-08-03T21:20:12.165Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/ea/839b50531021a647fb5e929f72cf97bc1ff702b5472166164b5b6e76b851/cffi-2.1.1-cp313-cp313-win32.whl", hash = "sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac", size = 175263, upload-time = "2026-08-03T21:20:13.559Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/a6/8b149b2c3f2e11aaa1618ef64500b45f50f22c57a977a4dff1aff1f91042/cffi-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d", size = 185688, upload-time = "2026-08-03T21:20:14.69Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/9a/11f687cb39d6a3504060d5242f04f48c735afb4d3d533958a20594890cb2/cffi-2.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973", size = 180078, upload-time = "2026-08-03T21:20:15.917Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/7b/d6bbf82b8b96e7391438898c42f5bd96dd02030fd5b64937d248220003e2/cffi-2.1.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7dbb61fe3a7699468030f71bbe5f8a0e326a151daa91beb11a6fc1f980c55e1c", size = 194064, upload-time = "2026-08-03T21:20:17.148Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/e6/bcc91b283be94735e268487a054004f0aa19947b6348fa367db53230abc8/cffi-2.1.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:f24fb43132a4c6b4cb4eb029492919b2db645be6808d738f244fd146c03c32cb", size = 196720, upload-time = "2026-08-03T21:20:18.268Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/99/c4b0c17cacdc9c3b8f280026286a9826d6a208c0f047591a3c3ce99b91fd/cffi-2.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d28630f5854ab07ab1fd4aba756de52326c82e6be15d414b12793f1975048b54", size = 184964, upload-time = "2026-08-03T21:20:19.708Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/a9/9db617d05d7367c1ad0ab00b3aa6e6f9281edd689b4ee9ea0e5a84e89c97/cffi-2.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:661c298b4821edebead0c91edd2b00374d67ad7c5a1f7a91d4442633b79d6a72", size = 184962, upload-time = "2026-08-03T21:20:20.833Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/b8/b42132ca113dc567d37684437b46ca1dafc885902b02a110a02d5b511857/cffi-2.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:58acb8ab8e295e6c5ea12f888cbb13cf21511ef2a3303a23f4325c29d17fe5c1", size = 222328, upload-time = "2026-08-03T21:20:22.118Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/10/c5c0cbf0a657aecf59ef511409734230bf556f05a0d6c9eed7aa5c0a0166/cffi-2.1.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:456a61fa52d579ebf9df2e9552ead5129855dbaff6c1e5a9b1bc408809bdc062", size = 209985, upload-time = "2026-08-03T21:20:23.401Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/6c/bfa0b87b03b9238148beca990292843c9396ba069b54496596594173de7b/cffi-2.1.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a4f00aa42f75d6e4595e8866e748cc1705adc0cddfeb2ca86d0d03993d63ba03", size = 208530, upload-time = "2026-08-03T21:20:24.628Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/02/4e7d553a7ac4b4238b38b3c1b80d486e9d4436f8d2acbf87a0997fe3f402/cffi-2.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b0431303acaea1089ad4b3e9ce4e6518193def1118d4073ca848635ee4ea2e96", size = 221525, upload-time = "2026-08-03T21:20:25.758Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/1d/a4aaf9babd75acb4d5f223bff71533bee748dd770a382619a798960ee9ba/cffi-2.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:64faea20f4e2613363a1a9b9c7dd73058f3ecd00133a511e72ad7c511658f527", size = 225053, upload-time = "2026-08-03T21:20:26.985Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/81/10/5dc0e7bdd18e22107054288283380fc97a06ae3f1656a106908d666a3c88/cffi-2.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5c58fe613dc5e5336357eff555824a314d8e43282600435c8d1cb6a7a2fedd13", size = 223213, upload-time = "2026-08-03T21:20:28.277Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/e9/d0061c364cde06ee43168a0d076ac1da512cbc380d44767b844ba34fe2b6/cffi-2.1.1-cp314-cp314-win32.whl", hash = "sha256:1a18a57b58cfb21fc28d72e876acf10eaed67a1ed96226f92af4df681d571c4c", size = 177682, upload-time = "2026-08-03T21:20:44.288Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/06/1c3e01e3ba14c39f6d10bfbac52753b7e22259e38088e5cfe1d704918690/cffi-2.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:3222ba5d678f80a030e6afbcc33dc1ae5cb45facabb61cee2c7016b8432fde48", size = 187949, upload-time = "2026-08-03T21:20:45.623Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/5b/da4e39efe18eeb89cf580ea9cfc66b6a7c3eadb808fc0cc1d3a295cb5a5d/cffi-2.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:ab36d55f9ed2d067327667c2fea18dda018eb628dd6347aa01dda6cf1f5d3836", size = 182947, upload-time = "2026-08-03T21:20:46.955Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/59/40338bf421c5accea1d45158170c87006ef1cd371b05c077e76476949728/cffi-2.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7750c6449dff7864bb9bb27ddfb0267756189201a3afc911d82b3caacd70dfc3", size = 188504, upload-time = "2026-08-03T21:20:29.495Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/47/5ecf1023850036e674c77ec4de86182d309ae344e39e7cba984b7df5d647/cffi-2.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0beceaabe56af686895136a2de78db54ecd8e4046b236b8fd6d6cb61389e9bf2", size = 188259, upload-time = "2026-08-03T21:20:31.291Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/9c/92934c3bea9f785b23eba304538c0b4d37a2a96d2431eb3a1bc87a11aa19/cffi-2.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:49cbc70e6542d4ccccb936558d1064a8012541e78f821f955cff24e357776c94", size = 223864, upload-time = "2026-08-03T21:20:32.571Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/45/ba4c93527bc38616a8bd36488acb69a2212d60486794f0c1f318949bbb76/cffi-2.1.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e2d65b31f36619cda3999b78b2aa9632e76b78448e7a56fc4240824200e7c4fc", size = 211538, upload-time = "2026-08-03T21:20:33.808Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/e9/b6ef565e452acb932fb0cb5443f44a78efbd1233e566f02b5a83855e9115/cffi-2.1.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:28907ab9bfb6aa13184cfc17c6b8e1023c5ab6fd7076d8c20a35e59fe04f8f29", size = 210688, upload-time = "2026-08-03T21:20:34.974Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/95/eff5f0cee78d2eabc7eebffec40d3fc1876b5f3c95582e018bb4b99601f2/cffi-2.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51b31d1c98274844cfd7838ce00bfc27c7423a4dc00fc0772fc3331c2cc90676", size = 223803, upload-time = "2026-08-03T21:20:36.564Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/01/579d39fb8bef00a335a23d83757b44feb24cd6345a2c451b64cb67b9c362/cffi-2.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e7cecbaadb83884793e05828cee59b210b24583b9c7425d0ba6a754fe22eb4e", size = 226763, upload-time = "2026-08-03T21:20:37.816Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/b0/0b44f47c60b01b57b6e2bbd92343f13a85a1d93bc46ccf6e47e244acd99c/cffi-2.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:25792eac27877609e7bb06d42ff88278a6624fff2ba9bbb523c09616b117e80f", size = 225688, upload-time = "2026-08-03T21:20:38.959Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/d2/3b7176cb570a1d3e27faf67b72f591af508036e0d8b2be2ef9af9e8c84bb/cffi-2.1.1-cp314-cp314t-win32.whl", hash = "sha256:8ef53b2de9bcb9197d31854256575d59dbac0cba72ac627bb291ef5eceb74be4", size = 182868, upload-time = "2026-08-03T21:20:40.388Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/56/78/31f00c1bcd97c9bbf55f1bfdf5bc809a5de8887473e90bb9960dca825e80/cffi-2.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:616f097f2fe415bc92a247f02e11f634e1f9e9a83d327e3c915c15089c87869e", size = 194104, upload-time = "2026-08-03T21:20:41.725Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/1b/58496f2ed0a35de575250c02a43ab3cc2c04d494a88fed31c1cabc0fd176/cffi-2.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ad2c86c495b899d862ea0f4b42891b8713a3bd45dd4105c7fd51c2a72f39f3a5", size = 186402, upload-time = "2026-08-03T21:20:43.042Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/8f/9ebe220eab48a093d1a5a5e339ab0dc7316eef3bb04d63c42f0251b61f50/cffi-2.1.1-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:dddad92b554513a31f272570678ba307fb9f618f05e3d4a5eacafff9eae03e1d", size = 194043, upload-time = "2026-08-03T21:20:48.179Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/69/844bad3ece306c4782c2ecb93597035b6690d48704b803914c199da1e8b3/cffi-2.1.1-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:da0e573f9f97159390c89d9f1a9e41908b66d408cc5b58d08cf3847d844c531b", size = 196737, upload-time = "2026-08-03T21:20:49.457Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/8a/af668013284634733f02d683458a0728739c7d6ddb5e14cb0c20832266fe/cffi-2.1.1-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:fb92203a88b3d3053034db775110081c49d28be6551923805e039924093761e4", size = 184933, upload-time = "2026-08-03T21:20:50.639Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/75/2f5207ff6d1a613133b23a5203cc0c2a628313b5eb3974d7956ae3c57950/cffi-2.1.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2ae64be792b8966f2c69538199728b290e34726562896df1e5dc8ffd8d8188e8", size = 185002, upload-time = "2026-08-03T21:20:52.173Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/31/9e1313b0a6e30e91b3b3d3fff51ae99c857c07738e3afcce1f7334e1b7ab/cffi-2.1.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:507a24c282e0f42f8ed737cf048572cbf580468da5555764a8331735e9c736b6", size = 222271, upload-time = "2026-08-03T21:20:53.462Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/e3/f6234a833e6e08c7007003074723c406559eecf9b48dfc97471e5a8eb7a0/cffi-2.1.1-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:246fa40ce8645a614ff682e0b70f37134e460eaf93a775e0cbe3cca585a67a80", size = 209919, upload-time = "2026-08-03T21:20:54.783Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/fc/5f74e293fced6edb51af3a46c4ccf6c23c9943774ecb375ddbd522c76add/cffi-2.1.1-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:471cee653ae88de62096552e6d24ccb4a5adb8c8c9f10b5054d0122c15bf2779", size = 208529, upload-time = "2026-08-03T21:20:56.066Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/16/29e6d01b388bef055ecd6ca8244b3f4d336bd09e92d5d892187b9601084e/cffi-2.1.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aeae0e330c9f6acd681f647d46cefd30c29f93e3392882e792e82080c9691399", size = 221630, upload-time = "2026-08-03T21:20:57.336Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/18/fa7f1f6857d5eb88a4ca99ffcbfb7c387a287ccc154c64a73e86314745d7/cffi-2.1.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:42a494cee34437f05546455144f2b5d9ac09b1face62bcfce597d2e521066688", size = 225134, upload-time = "2026-08-03T21:20:58.675Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/9f/e8e3dfa04a1b4c241f8c91faacad872b4d4efd051d49764ad4e2fd4b9fea/cffi-2.1.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:cc572dace3f60ef98d7b12ff411d20f5362feb31a0439eab0085bbfd349982d7", size = 223197, upload-time = "2026-08-03T21:20:59.968Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/7e/8debeb04f1ab9fe2a6963964cd6f1aaf7192627b83926586a6a4e089c9fa/cffi-2.1.1-cp315-cp315-win32.whl", hash = "sha256:4f42141fc14250de6dde5ee7ea4432be017252d91f19c5ad043c084cea629cac", size = 177683, upload-time = "2026-08-03T21:21:14.901Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/31/5158704cc474ab65c1647932e88be78dc0873f47130e253be38bcaf13d01/cffi-2.1.1-cp315-cp315-win_amd64.whl", hash = "sha256:e6e8cff14d6fb0be70a09c0bdc58096f501952d04624ebf867e0e56da2df8960", size = 187897, upload-time = "2026-08-03T21:21:16.108Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/4b/b3a2da8570c704ffc0f9762cdc3ec0f02c8573798e0b5cf7f11c82bbb70f/cffi-2.1.1-cp315-cp315-win_arm64.whl", hash = "sha256:27350daa11d4f10c540e6e89dada4c54feb7256ad03e9a4dc075ebad7ba360d1", size = 182935, upload-time = "2026-08-03T21:21:17.271Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/ef/5443574510a1207e6f6bc38ba6e1f1de36cb48fef07b2728bb896a21f430/cffi-2.1.1-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:c26608d2222fb1e94487e4a387d85f13eb55d5ed725cb25a0c589ac4ee60e7bc", size = 188464, upload-time = "2026-08-03T21:21:01.163Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/ae/a56fa8c4686ad50e148fcbc8d3ae0d03915ff5c30d795058988c24118cef/cffi-2.1.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:4be96343e422f2dfcd12ab5c9f5aebe03f82f737c6bffeca6830b3875cb44aab", size = 188262, upload-time = "2026-08-03T21:21:02.382Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/b2/6187f46f2912276a3ae284076109cc5c8680482f11f766ccf26db4a86427/cffi-2.1.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:937c0052c05a31ca1daf18de3158eed4dbfcb9cc107adbea227728d647be701e", size = 223779, upload-time = "2026-08-03T21:21:03.553Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/f6/c3ad28bd19f77047a03084424fbd4cbe997303267c14423737324be0385d/cffi-2.1.1-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:df423d40ee8654634421812bc3b196da3f9bd7d32929da813f8394c4348a5358", size = 211520, upload-time = "2026-08-03T21:21:04.863Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/cd/ccac9013a5bd9fd764de118674ab9c805b5ca10c19270d90ee273f8b2240/cffi-2.1.1-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a730a083190634c65cca36ba5f489531576ebd79bcd5c8e172130f6453127231", size = 210673, upload-time = "2026-08-03T21:21:06.223Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/86/2976131c639aead931c5bee5aba67e4b09fbeb8018b6f282f70803f923a7/cffi-2.1.1-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:363e05fa78e15116c3c32c210ee36884fd6b9afa6d440e47112c3bd511d64cb6", size = 223835, upload-time = "2026-08-03T21:21:07.539Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/0c/33a7aeab2f9c76918c52e084beb39c570db3588133412929e8ec06fab90b/cffi-2.1.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:770de9db11e84213beec501cfcaa013b019820ca881e03344dea5844f7876d94", size = 226705, upload-time = "2026-08-03T21:21:08.774Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/26/2cde30fdde421130bfc18f70395731a6e6b2053c6a1978a5258ff04e72fa/cffi-2.1.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:7da0c5eff80f0197f3b3d1232ec5a682a9325f4ae9016a78f5f5ca35f9ced1f5", size = 225539, upload-time = "2026-08-03T21:21:09.911Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/cd/a361394c94b2129d604bb846f624a8e88255a3ee33129c434a00d715e64f/cffi-2.1.1-cp315-cp315t-win32.whl", hash = "sha256:06c72bb76605a4b0cd0aad6930b69d4baf7dd5d806cfc409b824191099700e66", size = 182707, upload-time = "2026-08-03T21:21:11.226Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/b5/ba2b299993c26577d529b6ae29841f9e15b9fcf004d65f423f4fcf94ade9/cffi-2.1.1-cp315-cp315t-win_amd64.whl", hash = "sha256:d9c275eaacd24aa73f94ffd6de08fc3f932424d8b6c376f4bed7cde376fe7bc3", size = 193772, upload-time = "2026-08-03T21:21:12.39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/29/35e016098c814cd93de9cd320c66b5bfba14dc6ecedd3cb518fa7c408c69/cffi-2.1.1-cp315-cp315t-win_arm64.whl", hash = "sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692", size = 186360, upload-time = "2026-08-03T21:21:13.636Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfgv"
|
||||
version = "3.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chardet"
|
||||
version = "5.2.0"
|
||||
@@ -135,6 +290,19 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/1a/aff8bb287a4b1400f69e09a53bd65de96aa5cee5691925b38731c67fc695/click_default_group-1.2.4-py2.py3-none-any.whl", hash = "sha256:9b60486923720e7fc61731bdb32b617039aba820e22e1c88766b1125592eaa5f", size = 4123, upload-time = "2023-08-04T07:54:56.875Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click-repl"
|
||||
version = "0.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "prompt-toolkit" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/cb/a2/57f4ac79838cfae6912f997b4d1a64a858fb0c86d7fcaae6f7b58d267fca/click-repl-0.3.0.tar.gz", hash = "sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9", size = 10449, upload-time = "2023-06-15T12:43:51.141Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/52/40/9d857001228658f0d59e97ebd4c346fe73e138c6de1bce61dc568a57c7f8/click_repl-0.3.0-py3-none-any.whl", hash = "sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812", size = 10289, upload-time = "2023-06-15T12:43:48.626Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
@@ -163,6 +331,56 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/d9/0137658a353168ffa9d0fc14b812d3834772040858ddd1cb6eeaf09f7a44/cookiecutter-2.6.0-py3-none-any.whl", hash = "sha256:a54a8e37995e4ed963b3e82831072d1ad4b005af736bb17b99c2cbd9d41b6e2d", size = 39177, upload-time = "2024-02-21T18:02:39.569Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cryptography"
|
||||
version = "50.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/de/41/6cbdcf9142d00fe82836fbb51e503e58088575cf7a0fe1dbff6695bf0840/cryptography-50.0.0.tar.gz", hash = "sha256:eeac2acb5a20ed25e0ad6d1df9891a520b78b404266b6d11778f25d5d691a6c9", size = 880201, upload-time = "2026-07-31T14:25:10.11Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/5c/59086b4aac5e879d38ddbcf74e4be7ade89cebc3eb199a55da998c3bb46a/cryptography-50.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:031e2d5dd4bb9caa3ca9c82e5a197fd8ae680232cee62603d1a813f3f07e3d03", size = 4001252, upload-time = "2026-07-31T14:23:33.331Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/ef/8f2df13c7216bcad3e1c74e07f6e193d93e998e114f524a53877c9af27ad/cryptography-50.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd9192b7b70c573d7f214eb1ae35e00d359f6f5e4b27c7e21e30de1fc6204645", size = 4719554, upload-time = "2026-07-31T14:23:35.611Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/41/029086c34d91052fc3b88bcc8056f709a7c915c7a23b235a54eb800b1c97/cryptography-50.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:06a32a980526a6ab9a4b9bf8f7385800791e2bb960903cb6b530e4817509a3b7", size = 4702130, upload-time = "2026-07-31T14:23:37.635Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/ff/b6ce0954962e7f7b969f850a883744197bb3910bdfd7b6da162eab7d9f68/cryptography-50.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a1b30560f2acc95aa8b2e06e716a13dbfc97314747b80d9707e307f77b40d6b3", size = 4725244, upload-time = "2026-07-31T14:23:39.471Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/1e/63a1027cb7fec360a182208e1b7767d5aa1fe57be3d6aa856e69a321edc0/cryptography-50.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:8d89f3976b10b4ce31118de72329025f70d2c6ead14a8217c5514dd2c6d5a78f", size = 5342265, upload-time = "2026-07-31T14:23:41.286Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/72/a1116d683a6d7ece94590013882515de087edf9ef0e6292aae615a44df73/cryptography-50.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b42a28c1844fd9de8f3f7d540e36b66f3a9c83fceac7170ebc7a6a19edd9dcae", size = 4734609, upload-time = "2026-07-31T14:23:43.139Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/37/36a9c479bbe49acea2636c7fd3360d20f7b7e079c300352011c44850b181/cryptography-50.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:900131fafd8aead39ac7dd3a7e833be754c17a95cfd91221636949fe4eb0aa8a", size = 4356517, upload-time = "2026-07-31T14:23:44.939Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/98/8a151d64367204cbc63ec65d37502f1d9c53cf4bfc6ec3c532614dbec60d/cryptography-50.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:07949c449a1abcf60d1ee6e88956d89404c7df3c8258f46589e912988e551987", size = 4724529, upload-time = "2026-07-31T14:23:46.93Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/f6/ec13b470172126464a86bf54d2294a46d29837fc51ba3e45d4047946fb5e/cryptography-50.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:f89831ef99dd7dd169ab06d63a831adb9e20a87aac6d380266bbda5823349169", size = 5299852, upload-time = "2026-07-31T14:23:48.851Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/3a/f05e32c99d440c9bb891ea0e36c9091891e36be5a9a87ab2ee6ea20729f6/cryptography-50.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:82148ec5bddac30b51a5b3c1945075f896fa022cb93f8e4a01e9f6ee95292c5f", size = 4734462, upload-time = "2026-07-31T14:23:50.861Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/dc/bd72b26be8953f80625f63151efd38eee71c76ca6cf591c08ff34615a79e/cryptography-50.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1489e263a8048bb8b6a8bac662eb2d402ea5d2b7b4699b72f385f1e2772db105", size = 4852708, upload-time = "2026-07-31T14:23:52.715Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/20/c930314a2ab476d15dec966ec87e2e9637bb02b06106b12c0396c57bb603/cryptography-50.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7cec5b856506da6defb290f30c9ee687d5f5e8cb0bd3f6459dde43b0b4fa40ef", size = 5004179, upload-time = "2026-07-31T14:23:54.887Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/2e/c9db68a0c4bfa28e310707527c0ee3a2bd254104d2e02e68f368e197aa4c/cryptography-50.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:bd1c592e4d5974f0d08d4888e432157adba757c66da0246918e43677fafa2d30", size = 3840395, upload-time = "2026-07-31T14:23:56.677Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/fb/951032a3bf22a5697c83183fb6294a4843772947a70e616c57b3ff5f522e/cryptography-50.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:49e7d93abdbd2990caced757e5fade25302f719c3c8fb6e6fff2dde98999fc41", size = 3989258, upload-time = "2026-07-31T14:23:58.881Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/67/91eb047e69c5e845f2f14b8a2e4a1aab0f283cb885531e9e22c8adb176bc/cryptography-50.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:19736989797678c6af1e55cd49055cdbcb55d8f6b5583ac5335f933aba9101dc", size = 4700648, upload-time = "2026-07-31T14:24:00.702Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/82/85f0f7425c856b9f96459411eb12e74ef72df9caf6f8f15bf23a33ff131f/cryptography-50.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80b63928fa35083b33966ce1efb70e5b9607181e49dcd1c22c8c005e319f667f", size = 4682442, upload-time = "2026-07-31T14:24:02.538Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/28/b555a365adff1cca2fbe7b9e487d68a40de6bc67ff2cb587473eb43de0e7/cryptography-50.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:d58c3db7cd6eed54e6c06744db55456b65ebd7492ddeae9c1e93cfca7aa857d3", size = 4707596, upload-time = "2026-07-31T14:24:04.394Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/d8/f52538140cc719df62a01cf87d1c7142318d235817109d6f4054d7c352d6/cryptography-50.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:df2a58a472f332225671c35b0a830208b86d004f82baa8530fa3782c85646533", size = 5314552, upload-time = "2026-07-31T14:24:06.31Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/14/6120e5bd7c5aa022ad15424ba4d5c5269d0d9448ed4d55e492ea91e3c1c4/cryptography-50.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:11b74db56cdbe3cdee6e3f6982ecb70334fa10dce99ed58bf7894aaaa3b2a037", size = 4717113, upload-time = "2026-07-31T14:24:08.349Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/71/190bf38c3ee2e0f8efc9860ae100c9df4169742eef274b91e7aa1cb133b9/cryptography-50.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f59e38625469987d7ef6d495323c55e7db6c212eaf6112267e0d3b565a2e9c9f", size = 4338580, upload-time = "2026-07-31T14:24:10.227Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/63/504ccfbbe61fd8aa983f7f146399cdf034c72c2fc55f5b2dfdcdcdb20c99/cryptography-50.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:ecfed7367f965a0328cfbdd70da860f15441f002f613185668c6e6ebf5a0ac11", size = 4707038, upload-time = "2026-07-31T14:24:12.169Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/77/2cf79bbfc4d12ca106437a6e170d6aaa01a373e93093118aaaef0e801bd4/cryptography-50.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:9aa87839c383bdbab6ef865787a1fb877af8dd03464c4400322726feaaadfc6d", size = 5273110, upload-time = "2026-07-31T14:24:14.38Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/45/8aae2972c520145377ea3559a605a899bebe227bf070b33cdb445929a9b9/cryptography-50.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:6ba6a53445bd3cfa809ef3ef5f1589aa6ba08784a1d962bf47d0940e871dab1c", size = 4716439, upload-time = "2026-07-31T14:24:16.415Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/20/4fe50b619a48c2525cc46e2dbc1ac490708d704be5d467bdaac6dc955682/cryptography-50.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3f5735ffe4996d28b809371756219f5354864902a3b9e7c0b9ee87041209fc9c", size = 4837383, upload-time = "2026-07-31T14:24:18.553Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/91/3a31366e183343d3703f8995c095f5734676bd6938118047e50fcf279eb4/cryptography-50.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1b4a266766514614f8aa60416e71f2fc6e575d36e7bdc90f644fadb2f4b75b95", size = 4985772, upload-time = "2026-07-31T14:24:20.385Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/9a/02ffe35b2853d121689871eb5dce862092562b3a1ed5cc98f1aaed441506/cryptography-50.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:12b9c6996425c76ea6c457ace4f3073e715b8c545add07cd1a8f3a4f90691269", size = 3816291, upload-time = "2026-07-31T14:24:22.125Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/37/73d005be173aff344af30e9fd2a576575cb2391a7101d9cd3842e1fa8cce/cryptography-50.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ccdc4a71a4dabae05de219404f9f4abc38e3b58422177ff93d0da05967dafa07", size = 4036009, upload-time = "2026-07-31T14:24:24.122Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/c6/7a6202a534e32103a285b7834a120869557fe198d51d7cfe59754c8bda9c/cryptography-50.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:910e1d2668e7de9648f2bcee30e180db2a6b15c30f887d7c4c93ddf96e3992e3", size = 4745252, upload-time = "2026-07-31T14:24:26.118Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/4f/0fa8c2f4428198f15d9ff8d63400e27afbf94ce833f6108da1eb3753f945/cryptography-50.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a91296cb61e8df6f86d0c19cc4068228da256bf59bf86049fbd821084565327f", size = 4728939, upload-time = "2026-07-31T14:24:27.994Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/63/54dd723490ba2dc09b299682c10b38db38f159728bcaae8c591b8af2f22d/cryptography-50.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e722f16708d854fe924790e051061f6704a472c3bac347b6fd88033ea8dd0dc5", size = 4748483, upload-time = "2026-07-31T14:24:30.254Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/dd/7c77d26285cc7f6991efce64a0f5b4f9383bfa5dd8c5033003eaf7db4cdb/cryptography-50.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d764dcf130c428ef66786f866dd750f53182bc608813489915e9fc106bb0c82f", size = 5367599, upload-time = "2026-07-31T14:24:32.457Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/c9/f60aed34c013f317f92817b6c171c2d22a78270fa41109bd4b08af26b194/cryptography-50.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:105110f43a471dbd0060b9c9516cb8a6a79233631a04cc2ba16f28323ac6e025", size = 4762647, upload-time = "2026-07-31T14:24:34.599Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/f3/f9a0173b139372c3a48ed98154b45cc6b9de17c789d5ab552e621c293609/cryptography-50.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:828743d939e9629bc267b8e2d08d8bb67cd4319c771a33d4b18b22dd8fb7440a", size = 4385197, upload-time = "2026-07-31T14:24:36.647Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/36/83bb81f6e569bc38e1e4a7bc80f29b46bb9601920bc455fc8e888f5d5742/cryptography-50.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a8183b489dc1f7f80f135780fadc1108f14b31b8a40411c7a5b17425f65f28b", size = 4748095, upload-time = "2026-07-31T14:24:39.493Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/16/d3008eff98c764979865834c3d386d4fd041b5f52e7f34fc29ac1a5eb515/cryptography-50.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6e7d61120573a7f2cd94cc095f9e81f6967c61ccdf194285aa143ecec8e0b708", size = 5325948, upload-time = "2026-07-31T14:24:41.556Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9c/f8/d97f9603efda3888187bfdb893f26c41be4735c10631d05d284ee6b047c4/cryptography-50.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:37fdb0d0111f1e2ff07139dfb79f1b49531f8e213c46f1163dd7642979b58c47", size = 4762400, upload-time = "2026-07-31T14:24:43.636Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/a2/4615c8f7d81a00b1d6e6afe19f694e1543582349fb5f4076f6cb5dc36485/cryptography-50.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87f62a3d3b9888ed0fdde100ec06aa61ca9cd44bad9057d1dff9a516b5f5bb9", size = 4878208, upload-time = "2026-07-31T14:24:45.522Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/1a/efcfb02f91407149a0dacffffab791f7e19bf6385f63b3666dc8b5e5c9c8/cryptography-50.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:65c2c3add92b45fd0709db8594536aea39c2a67af0e27ffcf049c498501140b7", size = 5037050, upload-time = "2026-07-31T14:24:47.697Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/30/4a22984d4f1bdfb8c054f07a92bc176b97a3134cc1d6c4b3bffb1f3688b4/cryptography-50.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:d24fead1d4d076e1bfb006dcec392074a3cd8d7b4fc8a595aa64073b2b7a96ba", size = 3874135, upload-time = "2026-07-31T14:24:50.085Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "distlib"
|
||||
version = "0.4.0"
|
||||
@@ -195,6 +413,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/91/7216b27286936c16f5b4d0c530087e4a54eead683e6b0b73dd0c64844af6/filelock-3.20.0-py3-none-any.whl", hash = "sha256:339b4732ffda5cd79b13f4e2711a31b0365ce445d95d243bb996273d072546a2", size = 16054, upload-time = "2025-10-08T18:03:48.35Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "identify"
|
||||
version = "2.6.19"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/52/63/51723b5f116cc04b061cb6f5a561790abf249d25931d515cd375e063e0f4/identify-2.6.19.tar.gz", hash = "sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842", size = 99567, upload-time = "2026-04-17T18:39:50.265Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl", hash = "sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a", size = 99397, upload-time = "2026-04-17T18:39:49.221Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.11"
|
||||
@@ -207,13 +434,49 @@ wheels = [
|
||||
[[package]]
|
||||
name = "iform-invenio"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "boto3" },
|
||||
{ name = "bumpver" },
|
||||
{ name = "click-repl" },
|
||||
{ name = "invenio-cli" },
|
||||
{ name = "loguru" },
|
||||
{ name = "plumbum" },
|
||||
{ name = "pydantic-settings" },
|
||||
{ name = "python-dotenv" },
|
||||
{ name = "requests" },
|
||||
{ name = "trustme" },
|
||||
{ name = "typer" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "pre-commit" },
|
||||
{ name = "ruff" },
|
||||
{ name = "ty" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [{ name = "invenio-cli", specifier = ">=1.9.2" }]
|
||||
requires-dist = [
|
||||
{ name = "boto3", specifier = ">=1.43.68" },
|
||||
{ name = "bumpver", specifier = ">=2026.1132" },
|
||||
{ name = "click-repl", specifier = ">=0.3.0" },
|
||||
{ name = "invenio-cli", specifier = ">=1.9.2" },
|
||||
{ name = "loguru", specifier = ">=0.7.3" },
|
||||
{ name = "plumbum", specifier = ">=2.0.2" },
|
||||
{ name = "pydantic-settings", specifier = ">=2.15.0" },
|
||||
{ name = "python-dotenv", specifier = ">=1.2.2" },
|
||||
{ name = "requests", specifier = ">=2.32.5" },
|
||||
{ name = "trustme", specifier = ">=1.2.1" },
|
||||
{ name = "typer", specifier = ">=0.27.1" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "pre-commit", specifier = ">=3.5.0" },
|
||||
{ name = "ruff", specifier = ">=0.16.2" },
|
||||
{ name = "ty", specifier = ">=0.0.70" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "invenio-cli"
|
||||
@@ -248,6 +511,37 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jmespath"
|
||||
version = "1.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d3/59/322338183ecda247fb5d1763a6cbe46eff7222eaeebafd9fa65d4bf5cb11/jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d", size = 27377, upload-time = "2026-01-22T16:35:26.279Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64", size = 20419, upload-time = "2026-01-22T16:35:24.919Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lexid"
|
||||
version = "2021.1006"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/60/0b/28a3f9abc75abbf1fa996eb2dd77e1e33a5d1aac62566e3f60a8ec8b8a22/lexid-2021.1006.tar.gz", hash = "sha256:509a3a4cc926d3dbf22b203b18a4c66c25e6473fb7c0e0d30374533ac28bafe5", size = 11525, upload-time = "2021-04-02T20:18:34.668Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/e3/35764404a4b7e2021be1f88f42264c2e92e0c4720273559a62461ce64a47/lexid-2021.1006-py2.py3-none-any.whl", hash = "sha256:5526bb5606fd74c7add23320da5f02805bddd7c77916f2dc1943e6bada8605ed", size = 7587, upload-time = "2021-04-02T20:18:33.129Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "loguru"
|
||||
version = "0.7.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "win32-setctime", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3a/05/a1dae3dffd1116099471c643b8924f5aa6524411dc6c63fdae648c4f1aca/loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6", size = 63559, upload-time = "2024-12-06T11:20:56.608Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/29/0348de65b8cc732daa3e33e67806420b2ae89bdce2b04af740289c5c6c8c/loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c", size = 61595, upload-time = "2024-12-06T11:20:54.538Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markdown-it-py"
|
||||
version = "4.0.0"
|
||||
@@ -332,6 +626,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nodeenv"
|
||||
version = "1.10.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "25.0"
|
||||
@@ -374,6 +677,159 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/73/cb/ac7874b3e5d58441674fb70742e6c374b28b0c7cb988d37d991cde47166c/platformdirs-4.5.0-py3-none-any.whl", hash = "sha256:e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3", size = 18651, upload-time = "2025-10-08T17:44:47.223Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plumbum"
|
||||
version = "2.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6c/d2/578712a979a50e9aba08ea173a38e7598461130d3c9899f176373bc03280/plumbum-2.0.2.tar.gz", hash = "sha256:233751d7819c9e6743ec1c2405927eb4fa52a284c7b894bd10e28106a9309a92", size = 390799, upload-time = "2026-07-22T04:13:12.157Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/55/fdd01894807d20fb6181f13590ae247585b10e909b42e6ada833379fe520/plumbum-2.0.2-py3-none-any.whl", hash = "sha256:a865771826c1d2cce0ca8b2a2c48aa0447ed7a518859e389a95f158e9c369547", size = 168804, upload-time = "2026-07-22T04:13:10.76Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pre-commit"
|
||||
version = "4.6.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cfgv" },
|
||||
{ name = "identify" },
|
||||
{ name = "nodeenv" },
|
||||
{ name = "pyyaml" },
|
||||
{ name = "virtualenv" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/74/89/1f3e8e1fc3e97de0fa963495832f581f025f29471602a309e48808244292/pre_commit-4.6.2.tar.gz", hash = "sha256:8f5d7bfb021ecdbcd9d49d89847082dd24172ccde534390081a679ad046e2441", size = 198670, upload-time = "2026-08-10T22:07:18.421Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/45/e2/bbb7129c9e7999a6b8ee9cca3b66486c25c423ab5a75f34071798b74ce94/pre_commit-4.6.2-py2.py3-none-any.whl", hash = "sha256:e2dde9a75d3bce11bd3831c26d134df00a2803c1d818be6a0383c3dcda25dc4e", size = 226202, upload-time = "2026-08-10T22:07:16.942Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prompt-toolkit"
|
||||
version = "3.0.53"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "wcwidth" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/7d/ea/39b988c938f75cb75d7045b5c69f8bfed47ee2152c8837fb403de29d6fb8/prompt_toolkit-3.0.53.tar.gz", hash = "sha256:9ec8a0ad96d5c56148b3f914aa79c1564c3fde5d2e6b876e7bc327e353cf8fa6", size = 435492, upload-time = "2026-07-26T20:56:14.758Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/54/6f/84908cad2d6aa5144abcf7b42709fe4fdb459bc640ec7ac5786e7693dabc/prompt_toolkit-3.0.53-py3-none-any.whl", hash = "sha256:01c0891d7f9237d5e339f7d3e42cdae80b7534abb1c7c0e3352efba6231492f2", size = 392288, upload-time = "2026-07-26T20:56:12.512Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycparser"
|
||||
version = "3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.13.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-types" },
|
||||
{ name = "pydantic-core" },
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.46.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-settings"
|
||||
version = "2.15.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pydantic" },
|
||||
{ name = "python-dotenv" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/68/ca/31c57507b13119d7d3cfa1576dad2911a4861e3be07b579395f4e9d393f9/pydantic_settings-2.15.0.tar.gz", hash = "sha256:694b793e84f766ba76a90ebdefc01d0a9a045dab0382bee70393da93712ad117", size = 261253, upload-time = "2026-08-07T09:24:57.419Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/30/a4/2bffa9f8e804325a09867f0e9d30795c80ea9f8d62560bd1b6ad6220eb2f/pydantic_settings-2.15.0-py3-none-any.whl", hash = "sha256:0ba092c291c94baceb5eff768aa0d56400a457585bc0175925a5a5510303da42", size = 69413, upload-time = "2026-08-07T09:24:55.839Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.19.2"
|
||||
@@ -404,6 +860,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "1.2.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-slugify"
|
||||
version = "8.0.4"
|
||||
@@ -506,6 +971,43 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.16.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/73/e1/4508a569211b35599016e84ba65c1a992b7a4004b4b6c4bea02a851cba1b/ruff-0.16.2.tar.gz", hash = "sha256:c3d7828d12e8927a6fc65fe38e2c2541b9e762d360a1786d752cb1b8883b3c9c", size = 4885811, upload-time = "2026-08-07T13:31:01.432Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/14/57/db19951540f98859c956b50bdb4d31089b4d91e9f15e2968e7d5193806d5/ruff-0.16.2-py3-none-linux_armv6l.whl", hash = "sha256:3c8de4cf2181f01d57946d87d777aa52916976fc09942aed89938fab5e013318", size = 10847925, upload-time = "2026-08-07T13:30:14.468Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/5a/995fe85a8470d3e391ac0f7fa8054bb454eaf33ee138196d6172ed1079c0/ruff-0.16.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9a48cc05c6fbc811ca81b5d7ba95375affea6582d1b8024e455e41afbbf55344", size = 11072662, upload-time = "2026-08-07T13:30:18.143Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/53/370d767c61c71a971a4ace36703a7ecd8c393956349a7325d7fab2b56827/ruff-0.16.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a2c0d14fcbb26c91f0f867a6dc9bd71bbc30b1b6151829c884f23faeab2e5700", size = 10566771, upload-time = "2026-08-07T13:30:20.899Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/d6/9d96948caf5a632be62d62202d5ec914d6856f204fd79eb036e5915e79ea/ruff-0.16.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:335c621622c4650330be50842561c6586ac6971bb8ab5407fe34dcc9efb16bbe", size = 10975825, upload-time = "2026-08-07T13:30:23.517Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/92/ea87129b3414acb0b5770563779c51804d37ac67675c7ba35447ddb14773/ruff-0.16.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20e66910f2c37cc753f9ef6580c914a621b80c4fa3549d3e3521e29d0f5bfc3f", size = 10649437, upload-time = "2026-08-07T13:30:26.097Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/43/f8f291dcd4af5bb7872b74fdfa41a7cd7c856ca1d4069670971cf1b9f5cb/ruff-0.16.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7e36fbfba65510548156902bcf1350a979a958ce0347ce0f90d73894036b39f", size = 11446761, upload-time = "2026-08-07T13:30:28.752Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/4a/ef991fb2fcf516ab71f0808adcdd8da5e18c8cde447f4ceaf5f47a5132a5/ruff-0.16.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f0eab35f80df8f134aae5d1630e751901321d317cc8e50dc39e36fa3ed34cd12", size = 12336364, upload-time = "2026-08-07T13:30:31.468Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/24/f615e74f307e6ca0e56a482872477b856c70d530aa356abfb6dfe5ca8a80/ruff-0.16.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40ea8c0594feb894e89c8c61ab9c103d38b0ea72dfde6c594107147ca31b1140", size = 11630720, upload-time = "2026-08-07T13:30:34.426Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/d3/8ef50149e8412a77f7ab409efdef0e2b23803707a3863da4fc64cb23d459/ruff-0.16.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab3d62dde0b19facdd632008cc4827fc28ada7736c6bd35ab6f1050f0bfed53f", size = 11466130, upload-time = "2026-08-07T13:30:36.958Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/a7/a19334985c4dea8c381981fa252cd854c7ee52dc4b1686dc16f4a911c702/ruff-0.16.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:e43e1f5b8388da9eca1b9e88328d47a5cec794633ccf6f7484ac2dd15eee92c0", size = 11523634, upload-time = "2026-08-07T13:30:39.822Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/6c/96d192b0e742412ceda08c0a50f9669b253dde9fd6a60ea1a10c9fa79a63/ruff-0.16.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c24788a980581e1d7ea3a0cbe4344c4fbeb0a6a9b1f4713aa46bb104f8294690", size = 10949807, upload-time = "2026-08-07T13:30:42.745Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/51/e26599ceca11e79ee255c7df515995561edf87e9ca1893284e44d98f5a86/ruff-0.16.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:81806b08329130005dd4a8a8394a0c9da8c6f4cafb16ba438d2a2ee6a18bedf1", size = 10646891, upload-time = "2026-08-07T13:30:45.522Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/01/800c4b1f97bc8d7c6029e06b1f20473a3cf1e13c4933d8f3342add83fc55/ruff-0.16.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4ce4e02bad779bef557f541a1b31f20d6abeae1cc05ed1b1ac019d4ffd1044c8", size = 11162063, upload-time = "2026-08-07T13:30:48.131Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/d0/1477ea50fc5a0d4b0b71d1d63d50770bdd794d90b43e37a7618e63ec9894/ruff-0.16.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e0422abdf70070255fc4073ce9dfc814cc03db577013761ddd09bc1e4a9a4fbd", size = 11556038, upload-time = "2026-08-07T13:30:50.686Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/76/a7776f32048d991e16d4fa8ff91790b877342d3596cc3ed04acdbf1aaedc/ruff-0.16.2-py3-none-win32.whl", hash = "sha256:bf3a63d78fb39f4bf5ac8ae52051c5520505301abe19ba4e204c453b3f09bb0b", size = 10872850, upload-time = "2026-08-07T13:30:53.471Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/0d/929c800d920e61397d82a01b60bffc68da3052c17d31de59efaad2e4ed75/ruff-0.16.2-py3-none-win_amd64.whl", hash = "sha256:bcabe2f6d0fc7819f1431793005af4e4de7371927d037345bf941252b195b9fa", size = 12023338, upload-time = "2026-08-07T13:30:56.193Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/6c/93e26c22c5f78ff87363e07da49c84955affbeb1098bd1936bf3b3f293bf/ruff-0.16.2-py3-none-win_arm64.whl", hash = "sha256:d614e95cedf38a2053fd351c55b103ba30d017d61688fdbfd40ee0412852a99f", size = 11374065, upload-time = "2026-08-07T13:30:58.775Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "s3transfer"
|
||||
version = "0.19.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "botocore" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/76/43/35e4d8aa320bffe8287fe8f65f578fa2d2db0a64212f0e710dce58267854/s3transfer-0.19.2.tar.gz", hash = "sha256:ba0309fd86be3c27dbf78cdd813c13c5e1df16e5874b99d2535ebbdfb9892993", size = 165592, upload-time = "2026-07-22T19:30:44.432Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/e7/5c595c75e9f41a44f30e526eda465ea0b4eec93470e074e4a111b253f13a/s3transfer-0.19.2-py3-none-any.whl", hash = "sha256:d8168eccca828cbb2cd573675333f3bddd254313a9c42494b84c76b539e8ba25", size = 90216, upload-time = "2026-07-22T19:30:43.251Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "80.9.0"
|
||||
@@ -515,6 +1017,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shellingham"
|
||||
version = "1.5.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.17.0"
|
||||
@@ -542,6 +1053,80 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", size = 16588, upload-time = "2020-11-01T01:40:20.672Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trustme"
|
||||
version = "1.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cryptography" },
|
||||
{ name = "idna" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4b/c5/931476f4cf1cd9e736f32651005078061a50dc164a2569fb874e00eb2786/trustme-1.2.1.tar.gz", hash = "sha256:6528ba2bbc7f2db41f33825c8dd13e3e3eb9d334ba0f909713c8c3139f4ae47f", size = 26844, upload-time = "2025-01-02T01:55:32.632Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/f3/c34dbabf6da5eda56fe923226769d40e11806952cd7f46655dd06e10f018/trustme-1.2.1-py3-none-any.whl", hash = "sha256:d768e5fc57c86dfc5ec9365102e9b092541cd6954b35d8c1eea01a84f35a762a", size = 16530, upload-time = "2025-01-02T01:55:30.181Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ty"
|
||||
version = "0.0.70"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/58/ed/38a8ab52f1d7c3ed701442a31b23ba774cbc5d6909f2c00da9e1f3c590f9/ty-0.0.70.tar.gz", hash = "sha256:a01bebc128b4081c16002965d906fccb21323d69bb709b9108c1f2406bcffced", size = 6601156, upload-time = "2026-08-10T23:20:26.268Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/c5/ddd6cc5657fd3da85591b264f4dabb1ce5e5b535e73fd5174991c294978b/ty-0.0.70-py3-none-linux_armv6l.whl", hash = "sha256:4fb2d2e55e2160c07152361be2e1a26fdd4f6261055731317d5972daf1749935", size = 12537215, upload-time = "2026-08-10T23:19:43.512Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/8a/acc9b34331cde81e0d63cda92d4db9e4042def5b1efa7d47431ff1d30d17/ty-0.0.70-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9b04d4c21cb029501c05598ca21e9c0829c0b2e35a7ceba1e5b78014c1e8104d", size = 12149070, upload-time = "2026-08-10T23:19:46.369Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/cd/51ac2708f4d077058a0bfeefa40d630883c5ec7a82fd2c15c86519140235/ty-0.0.70-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c605ebf2643f5e64ec4bcb269640a1aa85966d29fa888fb746039c28570369b2", size = 11625729, upload-time = "2026-08-10T23:19:48.535Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/99/afc4fe7e630100dc782ff0cdc8c59c01acfb05299551ff0ef49c93814320/ty-0.0.70-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c38ea76e12909c29e18fcd295ff223b63f3701c1d1c34db2cdc9736340b9de2", size = 12204810, upload-time = "2026-08-10T23:19:51.845Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/38/8cabc3c8ad4c3a02e585ecff12a71ff8e5881f8a00ee71745fd765201da5/ty-0.0.70-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c1ee6bf4edaabf7bd0307f0c0f9ddc2204df0390820fe89f6a9de65f07722aba", size = 12308114, upload-time = "2026-08-10T23:19:54.229Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/7e/bb4e552ecd68bb490bae9368ef323e3d0c79ef85a811857139a2d0f59ddb/ty-0.0.70-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5eef3e11d7d6b800ef66da0cce8ea24f8be804d1ebf359683426cfe848729bf8", size = 13072240, upload-time = "2026-08-10T23:19:56.872Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/c4/1861e1d554e5b6e0d11b3a9f36d40c372253f44a3c4e56ad4bf840f2801e/ty-0.0.70-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a95e4ae7c2599197c9d89652e49ca344ab224f7d12376e6ad8beb0587e8ff83f", size = 13497678, upload-time = "2026-08-10T23:19:59.191Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/22/3b22442133e8f641485e59e463a070a31184db0d6456851f871db8f59763/ty-0.0.70-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:06aca758d1e0016c0a1f57fe9d8de7a21ff83f692306f747a0d97f32de24e27f", size = 13232510, upload-time = "2026-08-10T23:20:01.456Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/b8/911f1e6885b5485b6e1d29aaab19ce5e6deeb3e931b6ad82296da4f22051/ty-0.0.70-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d81825524f1b57ecbcb5fce7d61fb159cb4837a6167a4569309c9fa7fc15a77d", size = 12817128, upload-time = "2026-08-10T23:20:04.275Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/a6/9affc3ca11c32d75b348a66144ab83335fa7fa7100b1581356725e15a668/ty-0.0.70-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:3287dfb09f7320ef28f114f5f9aae5f697b7b1a6ee37fb2a4a3be94481c1b4f8", size = 13089208, upload-time = "2026-08-10T23:20:06.574Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/cb/4776108ea08ec4013b71375b101be9c8a632967cd10f24abbdd4664d66f4/ty-0.0.70-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:9fb1877f6401cdaac4db46c5bf762f327482ba5f891420ea462ebd15d0de4185", size = 12148890, upload-time = "2026-08-10T23:20:08.827Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/d9/814e71f698d9231ef6412bd2c1499d81c6f86f66c2764e952c991e2d6da5/ty-0.0.70-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e78f4997dbb0db2d2270210eb3694466206e5b3a11985e24148770e702158a25", size = 12327084, upload-time = "2026-08-10T23:20:11.023Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/69/9f34bba534c5d1ace391d300ead4f1971f4348c5459e66dc466cfd60661c/ty-0.0.70-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cf758d3b2dad910c9b1d22d2d62fea894b5bc9acd3c00365e8a73ace6090a452", size = 12604372, upload-time = "2026-08-10T23:20:13.366Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/ff/abb34674517b29a8e2489a39c4e01930fcf6aab993a7d6b33aa97f119117/ty-0.0.70-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0d338761617279a4fb6a83e7fad7e21126394637b8c45e13e196b2bb675f39b2", size = 12917800, upload-time = "2026-08-10T23:20:15.841Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/1a/f8289572f4fad5cb16c883b94638548166bc78cf3eb569f0cd9199eb10a0/ty-0.0.70-py3-none-win32.whl", hash = "sha256:a45642cf09dde91f0a3ce9b9e6fffda9779ff69d73f7347c18acf4fb45007c07", size = 11921482, upload-time = "2026-08-10T23:20:18.244Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/ae/8739d7618b4670c3ee4f52d641d53be87928bd121d8bda9c0e3450500b75/ty-0.0.70-py3-none-win_amd64.whl", hash = "sha256:33e7941a926cf39b82553911a59a6ed68ec98c3d3d5a415df633f4d1cd051e6c", size = 12986994, upload-time = "2026-08-10T23:20:20.53Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/44/2bc3301ba4356ad8866daac9f8cfb3687953e52d076ea204f113b9304c42/ty-0.0.70-py3-none-win_arm64.whl", hash = "sha256:0d380f735d52b1d4b773193f8f5c58c065725eab1ebb0008d38a7b830de14f47", size = 12301082, upload-time = "2026-08-10T23:20:23.816Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typer"
|
||||
version = "0.27.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-doc" },
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "rich" },
|
||||
{ name = "shellingham" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ae/40/4a3db7990d1f62a53182aa96eaef57aeb2886a27f90a195bc66713565d31/typer-0.27.1.tar.gz", hash = "sha256:a79bef8469a79c45498e7b814ecf8d603cc7644e9acbd9e19cac0334240b18df", size = 203994, upload-time = "2026-08-03T14:41:03.438Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/43/89/9518bc0c3929bee36b3a4a8e3daddd6e03f92f9961c66d4983b837160543/typer-0.27.1-py3-none-any.whl", hash = "sha256:53150287edd11baeb4e4722c8e394fcdf8181c0ae89485cba8d25c778d5edd56", size = 122874, upload-time = "2026-08-03T14:41:04.391Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.16.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-inspection"
|
||||
version = "0.4.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6d/bc/4eae18cd40c65798a16267572ba346c11f599d44b01603dbd843342042bc/typing_inspection-0.4.3.tar.gz", hash = "sha256:c5f9ec1530b5c1e2c9bc34a84d9a3466ed1b2f3f2fa9f901368d9c5596210e4d", size = 76711, upload-time = "2026-08-10T09:39:18.063Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/42/f7/7a3935abdebd5cf18705a5f0335dd6a3a18bef3baa7cb9edc3b6b9922cc8/typing_inspection-0.4.3-py3-none-any.whl", hash = "sha256:5f42b23858a91e0b4ef521f5418f03a0da3c9216fd2995ef5e73463100e676cd", size = 14693, upload-time = "2026-08-10T09:39:16.693Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tzdata"
|
||||
version = "2025.2"
|
||||
@@ -573,3 +1158,21 @@ sdist = { url = "https://files.pythonhosted.org/packages/20/28/e6f1a6f655d620846
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/79/0c/c05523fa3181fdf0c9c52a6ba91a23fbf3246cc095f26f6516f9c60e6771/virtualenv-20.35.4-py3-none-any.whl", hash = "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b", size = 6005095, upload-time = "2025-10-29T06:57:37.598Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wcwidth"
|
||||
version = "0.8.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/34/74/c6428f875774288bec1396f5bfcbc2d925700a4dad61727fd5f2b12f249d/wcwidth-0.8.2.tar.gz", hash = "sha256:91fbef97204b96a3d4d421609b80340b760cf33e26da123ff243d76b1fda8dda", size = 1466253, upload-time = "2026-06-29T18:11:11.601Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/96/42/3e5985a0a7e57de470b320c6d6a1a67c844f6737a587f3d44dd13d1819e7/wcwidth-0.8.2-py3-none-any.whl", hash = "sha256:d63947694a0539a1d51e01eda7caf800c291020e6cdd7e28ad7b14dd33ad4f85", size = 323166, upload-time = "2026-06-29T18:11:09.888Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "win32-setctime"
|
||||
version = "1.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b3/8f/705086c9d734d3b663af0e9bb3d4de6578d08f46b1b101c2442fd9aecaa2/win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0", size = 4867, upload-time = "2024-12-07T15:28:28.314Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/07/c6fe3ad3e685340704d314d765b7912993bcb8dc198f0e7a89382d37974b/win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390", size = 4083, upload-time = "2024-12-07T15:28:26.465Z" },
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user