CI/CD stuff for auto-publishing
This commit is contained in:
parent
ac3f2c476f
commit
59894780de
29 changed files with 1414 additions and 409 deletions
24
.github/workflows/precommit.yml
vendored
Normal file
24
.github/workflows/precommit.yml
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
name: precommit-action
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
linter_name:
|
||||||
|
name: runner / Pre-commit actions
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Python 3.13
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version-file: '.python-version'
|
||||||
|
|
||||||
|
- name: Setup annotations
|
||||||
|
uses: PennyDreadfulMTG/setup-linters@main
|
||||||
|
|
||||||
|
- name: Install Pre-commit
|
||||||
|
run: |
|
||||||
|
pip install pre-commit
|
||||||
|
|
||||||
|
- name: Run Pre-commit
|
||||||
|
run: |
|
||||||
|
pre-commit run --all-files --show-diff-on-failure
|
37
.github/workflows/publish.yml
vendored
Normal file
37
.github/workflows/publish.yml
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
name: Publish to PyPI
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
env:
|
||||||
|
PACKAGE_NAME: pyfall
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: !github.event.release.prerelease
|
||||||
|
steps:
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v5
|
||||||
|
with:
|
||||||
|
version: "0.6.3"
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.13'
|
||||||
|
|
||||||
|
- name: Install the project
|
||||||
|
run: uv sync --all-extras --dev
|
||||||
|
|
||||||
|
- name: Build and publish packages
|
||||||
|
env:
|
||||||
|
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
||||||
|
run: |
|
||||||
|
uv build
|
||||||
|
uv publish
|
46
.github/workflows/pytest.yml
vendored
Normal file
46
.github/workflows/pytest.yml
vendored
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
name: pytest
|
||||||
|
on: push
|
||||||
|
jobs:
|
||||||
|
pytest:
|
||||||
|
name: runner / pytest tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
max-parallel: 1
|
||||||
|
matrix:
|
||||||
|
python-version:
|
||||||
|
- "3.11"
|
||||||
|
- "3.12"
|
||||||
|
- "3.13"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v5
|
||||||
|
with:
|
||||||
|
version: "0.6.3"
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
cache: 'pip'
|
||||||
|
|
||||||
|
- name: Install the project
|
||||||
|
run: uv sync --all-extras --dev
|
||||||
|
|
||||||
|
- name: Run Tests
|
||||||
|
run: |
|
||||||
|
uv run pytest
|
||||||
|
|
||||||
|
- name: Upload Coverage
|
||||||
|
run: |
|
||||||
|
curl -Os https://uploader.codecov.io/latest/linux/codecov
|
||||||
|
chmod +x codecov
|
||||||
|
./codecov
|
||||||
|
|
||||||
|
- name: Publish Test Report
|
||||||
|
uses: mikepenz/action-junit-report@v3
|
||||||
|
if: always() # always run even if the previous step fails
|
||||||
|
with:
|
||||||
|
report_paths: 'coverage.xml'
|
||||||
|
check_name: 'Pytest Results'
|
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -8,3 +8,10 @@ wheels/
|
||||||
|
|
||||||
# Virtual environments
|
# Virtual environments
|
||||||
.venv
|
.venv
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
report.xml
|
||||||
|
.coverage
|
||||||
|
coverage.xml
|
||||||
|
.pytest_cache/
|
||||||
|
.ruff_cache/
|
41
.pre-commit-config.yaml
Normal file
41
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v5.0.0
|
||||||
|
hooks:
|
||||||
|
- id: requirements-txt-fixer
|
||||||
|
name: Requirements
|
||||||
|
types: [file]
|
||||||
|
exclude_types: ["image"]
|
||||||
|
- id: debug-statements
|
||||||
|
name: Debugging
|
||||||
|
language: python
|
||||||
|
types: [file, python]
|
||||||
|
exclude_types: ["image"]
|
||||||
|
# - id: trailing-whitespace
|
||||||
|
# name: Trailing Whitespace
|
||||||
|
# language: python
|
||||||
|
# types: [file]
|
||||||
|
# exclude: ^\.vscode/
|
||||||
|
# exclude_types: ["image", "binary", "executable"]
|
||||||
|
# - id: end-of-file-fixer
|
||||||
|
# name: EOF Newlines
|
||||||
|
# language: python
|
||||||
|
# types: [file]
|
||||||
|
# exclude_types: ["image", "binary", "executable"]
|
||||||
|
- id: check-yaml
|
||||||
|
name: YAML Structure
|
||||||
|
language: python
|
||||||
|
args: ["--unsafe"]
|
||||||
|
- id: check-toml
|
||||||
|
name: TOML Structure
|
||||||
|
- id: check-merge-conflict
|
||||||
|
name: Merge Conflicts
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
# Ruff version.
|
||||||
|
rev: v0.7.4
|
||||||
|
hooks:
|
||||||
|
# Run the linter.
|
||||||
|
- id: ruff
|
||||||
|
args: [--fix, --exit-non-zero-on-fix]
|
||||||
|
# Run the formatter.
|
||||||
|
- id: ruff-format
|
|
@ -0,0 +1,3 @@
|
||||||
|
from pyfall.client import Pyfall
|
||||||
|
|
||||||
|
__all__ = ["Pyfall"]
|
|
@ -1,24 +1,20 @@
|
||||||
from typing import Any, Literal
|
from typing import Any
|
||||||
|
|
||||||
import httpx
|
|
||||||
|
|
||||||
from pyfall.const import __version__
|
from pyfall.const import __version__
|
||||||
from pyfall.models import *
|
|
||||||
from pyfall.utils import UUID_CHECK
|
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from httpx import AsyncClient
|
from httpx import AsyncClient
|
||||||
|
|
||||||
from pyfall.const import __version__, get_logger
|
from pyfall.const import get_logger
|
||||||
from pyfall.client.error import *
|
from pyfall.client.error import LibraryException, HTTPException, ScryfallError, Forbidden, NotFound
|
||||||
from pyfall.client.http.http_requests.card import CardRequests
|
from pyfall.client.http.http_requests.card import CardRequests
|
||||||
from pyfall.client.http.http_requests.set import SetRequests
|
from pyfall.client.http.http_requests.set import SetRequests
|
||||||
from pyfall.client.route import Route
|
from pyfall.client.route import Route
|
||||||
|
|
||||||
|
|
||||||
class GlobalLock:
|
class GlobalLock:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self._lock = asyncio.Lock()
|
self._lock = asyncio.Lock()
|
||||||
|
@ -26,11 +22,6 @@ class GlobalLock:
|
||||||
self._calls = self.max_requests
|
self._calls = self.max_requests
|
||||||
self._reset_time = 0
|
self._reset_time = 0
|
||||||
|
|
||||||
@property
|
|
||||||
def calls_remaining(self) -> int:
|
|
||||||
"""Returns the amount of calls remaining."""
|
|
||||||
return self.max_requests - self._calls
|
|
||||||
|
|
||||||
def reset_calls(self) -> None:
|
def reset_calls(self) -> None:
|
||||||
"""Resets the calls to the max amount."""
|
"""Resets the calls to the max amount."""
|
||||||
self._calls = self.max_requests
|
self._calls = self.max_requests
|
||||||
|
@ -59,23 +50,25 @@ class GlobalLock:
|
||||||
self.reset_calls()
|
self.reset_calls()
|
||||||
self._calls -= 1
|
self._calls -= 1
|
||||||
|
|
||||||
|
|
||||||
class Pyfall(CardRequests, SetRequests):
|
class Pyfall(CardRequests, SetRequests):
|
||||||
def __init__(self, logger: logging.Logger | None = None):
|
def __init__(self, logger: logging.Logger | None = None):
|
||||||
self.__headers = {
|
self.__headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"UserAgent": f"pyfall/{__version__}",
|
"UserAgent": f"pyfall/{__version__}",
|
||||||
"Accept": "application/json"
|
"Accept": "application/json",
|
||||||
}
|
}
|
||||||
self.__client: AsyncClient = None
|
self.__client: AsyncClient = None # type: ignore
|
||||||
self.global_lock: GlobalLock = GlobalLock()
|
self.global_lock: GlobalLock = GlobalLock()
|
||||||
self._max_attempts: int = 3
|
self._max_attempts: int = 3
|
||||||
|
|
||||||
self.logger = logger
|
self.logger: logging.Logger = logger # type: ignore
|
||||||
if self.logger is None:
|
if self.logger is None:
|
||||||
self.logger = get_logger()
|
self.logger = get_logger()
|
||||||
|
|
||||||
async def request(self, route: Route, params: dict | None = None, **kwargs: dict) -> dict[str, Any]:
|
async def request(self, route: Route, params: dict | None = None, **kwargs: dict) -> dict[str, Any]:
|
||||||
"""Make a request to the Scryfall API.
|
"""
|
||||||
|
Make a request to the Scryfall API.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
route: Route to take
|
route: Route to take
|
||||||
|
@ -83,98 +76,51 @@ class Pyfall(CardRequests, SetRequests):
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
dict[str, Any]: Raw result
|
dict[str, Any]: Raw result
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if params is not None:
|
if params is not None:
|
||||||
kwargs["params"] = params
|
kwargs["params"] = params
|
||||||
if not self.__client:
|
if not self.__client:
|
||||||
self.__client = AsyncClient(headers=self.__headers)
|
self.__client = AsyncClient(headers=self.__headers)
|
||||||
for attempt in range(self._max_attempts):
|
for attempt in range(self._max_attempts):
|
||||||
if self.__client is None:
|
|
||||||
self.__client = AsyncClient()
|
|
||||||
|
|
||||||
await self.global_lock.wait()
|
await self.global_lock.wait()
|
||||||
|
|
||||||
response = await self.__client.request(route.method, route.url, **kwargs)
|
response = await self.__client.request(route.method, route.url, **kwargs) # type: ignore
|
||||||
|
|
||||||
if response.status_code == 429:
|
if response.status_code == 429:
|
||||||
self.logger.warning("Too many requests, waiting 5 seconds")
|
self.logger.warning("Too many requests, waiting 5 seconds")
|
||||||
self.global_lock.set_reset_time(5)
|
self.global_lock.set_reset_time(5)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if response.status_code >= 500:
|
if response.status_code >= 500:
|
||||||
self.logger.warning(f"{route.resolved_endpoint} Received {response.status_code}... retrying in {1 + attempt * 2} seconds")
|
self.logger.warning(
|
||||||
|
f"{route.resolved_endpoint} Received {response.status_code}... retrying in {1 + attempt * 2} seconds"
|
||||||
|
)
|
||||||
await asyncio.sleep(1 + attempt * 2)
|
await asyncio.sleep(1 + attempt * 2)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
result = response.json()
|
result = response.json()
|
||||||
|
|
||||||
if not 300 > response.status_code >= 200:
|
if not 300 > response.status_code >= 200:
|
||||||
await self._raise_exception(response, route, result)
|
await self._raise_exception(response, route, result)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
raise LibraryException(f"Failed to get endpoint {route.endpoint}")
|
||||||
|
|
||||||
async def _raise_exception(self, response, route, result) -> None:
|
async def _raise_exception(self, response, route, result) -> None:
|
||||||
self.logger.error(f"{route.method}::{route.url}: {response.status_code}")
|
self.logger.error(f"{route.method}::{route.url}: {response.status_code}")
|
||||||
|
|
||||||
if response.status_code == 403:
|
if response.status_code == 403:
|
||||||
raise Forbidden(response, route)
|
raise Forbidden(response, route)
|
||||||
if response.status_code == 404:
|
if response.status_code == 404:
|
||||||
raise NotFound(response, route)
|
raise NotFound(response, route)
|
||||||
if response.status_code >= 500:
|
if response.status_code >= 500:
|
||||||
raise ScryfallError(response, route)
|
raise ScryfallError(response, route)
|
||||||
|
|
||||||
raise HTTPException(response, route)
|
raise HTTPException(response, route)
|
||||||
|
|
||||||
async def close(self) -> None:
|
async def close(self) -> None:
|
||||||
"""Close the session."""
|
"""Close the session."""
|
||||||
if self.__client is not None and not self.__client.is_closed:
|
if self.__client is not None and not self.__client.is_closed:
|
||||||
await self.__client.aclose()
|
await self.__client.aclose()
|
||||||
|
|
||||||
# class Pyfall:
|
|
||||||
# """Scryfall API client."""
|
|
||||||
# def __init__(self):
|
|
||||||
# self._headers = {
|
|
||||||
# "Content-Type": "application/json",
|
|
||||||
# "UserAgent": f"pyfall/{__version__}",
|
|
||||||
# "Accept": "application/json"
|
|
||||||
# }
|
|
||||||
# self.__httpx: httpx.AsyncClient = None
|
|
||||||
|
|
||||||
# async def request(self, endpoint: str, method: str = "GET", **kwargs) -> dict[str, Any]:
|
|
||||||
# """Make a request to the API.
|
|
||||||
|
|
||||||
# Args:
|
|
||||||
# endpoint: Endpoint to request from
|
|
||||||
|
|
||||||
# Returns:
|
|
||||||
# Raw API result
|
|
||||||
# """
|
|
||||||
# if not self.__httpx:
|
|
||||||
# self.__httpx = httpx.AsyncClient(headers=self._headers, base_url="https://api.scryfall.com")
|
|
||||||
|
|
||||||
# args = {k: v for k, v in kwargs if v is not None}
|
|
||||||
|
|
||||||
# if method not in ("POST", "PATCH", "PUT"):
|
|
||||||
# response: httpx.Response = await self.__httpx.request(method=method, url=endpoint, params=args)
|
|
||||||
# else:
|
|
||||||
# response: httpx.Response = await self.__httpx.request(method=method, url=endpoint, data=args)
|
|
||||||
# if response.status_code >= 500:
|
|
||||||
# response.raise_for_status()
|
|
||||||
# data = response.json()
|
|
||||||
# return data
|
|
||||||
|
|
||||||
# async def get_card_by_id(self, id: str) -> Card:
|
|
||||||
# """Get a card by ID.
|
|
||||||
|
|
||||||
# Args:
|
|
||||||
# id: UUID of card
|
|
||||||
# """
|
|
||||||
# if not UUID_CHECK.match(id):
|
|
||||||
# raise ValueError("'id' must be a UUID")
|
|
||||||
# data = await self.request(f"cards/{id}")
|
|
||||||
# if data["object"] == "error":
|
|
||||||
# return APIError.model_validate(data)
|
|
||||||
# data["_client"] = self
|
|
||||||
# return Card(**data)
|
|
|
@ -5,50 +5,57 @@ import httpx
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pyfall.client.route import Route
|
from pyfall.client.route import Route
|
||||||
|
|
||||||
|
|
||||||
class LibraryException(Exception):
|
class LibraryException(Exception):
|
||||||
"""Base Exception of pyfall."""
|
"""Base Exception of pyfall."""
|
||||||
|
|
||||||
|
|
||||||
class HTTPException(LibraryException):
|
class HTTPException(LibraryException):
|
||||||
"""
|
"""
|
||||||
An HTTP request resulted in an exception.
|
An HTTP request resulted in an exception.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
response httpx.Response: The response of the HTTP request
|
response httpx.Response: The response of the HTTP request
|
||||||
details str: The text of the exception, could be None
|
details str: The text of the exception, could be None
|
||||||
status int: The HTTP status code
|
status int: The HTTP status code
|
||||||
route Route: The HTTP route that was used
|
route Route: The HTTP route that was used
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, response: httpx.Response, route: "Route") -> None:
|
def __init__(self, response: httpx.Response, route: "Route") -> None:
|
||||||
self.response: httpx.Response = response
|
self.response: httpx.Response = response
|
||||||
self.route: "Route" = route
|
self.route: "Route" = route
|
||||||
|
|
||||||
data = response.json()
|
data = response.json()
|
||||||
|
|
||||||
self.status: int = data.get("status")
|
self.status: int = data.get("status")
|
||||||
self.code: str = data.get("code")
|
self.code: str = data.get("code")
|
||||||
self.details: str = data.get("details")
|
self.details: str = data.get("details")
|
||||||
self.type: str | None = data.get("type", None)
|
self.type: str | None = data.get("type", None)
|
||||||
self.warnings: list[str] | None = data.get("warnings", None)
|
self.warnings: list[str] | None = data.get("warnings", None)
|
||||||
|
|
||||||
super().__init__(f"{self.status}|{self.code}: {f'({self.type})' if self.type else ''}{self.details}")
|
super().__init__(f"{self.status}|{self.code}: {f'({self.type})' if self.type else ''}{self.details}")
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
if not self.warnings:
|
if not self.warnings:
|
||||||
return f"HTTPException: {self.status}|{self.code} || {self.details}"
|
return f"HTTPException: {self.status}|{self.code} || {self.details}"
|
||||||
return f"HTTPException: {self.status}|{self.code}: " + "\n".join(self.warnings)
|
return f"HTTPException: {self.status}|{self.code}: " + "\n".join(self.warnings)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return str(self)
|
return str(self)
|
||||||
|
|
||||||
|
|
||||||
class ScryfallError(HTTPException):
|
class ScryfallError(HTTPException):
|
||||||
"""An error occurred with Scryfall."""
|
"""An error occurred with Scryfall."""
|
||||||
|
|
||||||
|
|
||||||
class BadRequest(HTTPException):
|
class BadRequest(HTTPException):
|
||||||
"""A bad request was made."""
|
"""A bad request was made."""
|
||||||
|
|
||||||
|
|
||||||
class Forbidden(HTTPException):
|
class Forbidden(HTTPException):
|
||||||
"""You do not have access to this."""
|
"""You do not have access to this."""
|
||||||
|
|
||||||
|
|
||||||
class NotFound(HTTPException):
|
class NotFound(HTTPException):
|
||||||
"""This resource could not be found."""
|
"""This resource could not be found."""
|
||||||
|
|
|
@ -1,125 +0,0 @@
|
||||||
import asyncio
|
|
||||||
import logging
|
|
||||||
import time
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from httpx import AsyncClient
|
|
||||||
|
|
||||||
from pyfall.const import __version__, get_logger
|
|
||||||
from pyfall.client.error import *
|
|
||||||
from pyfall.client.http.http_requests.card import CardRequests
|
|
||||||
from pyfall.client.http.http_requests.set import SetRequests
|
|
||||||
from pyfall.client.route import Route
|
|
||||||
|
|
||||||
class GlobalLock:
|
|
||||||
def __init__(self) -> None:
|
|
||||||
self._lock = asyncio.Lock()
|
|
||||||
self.max_requests = 10
|
|
||||||
self._calls = self.max_requests
|
|
||||||
self._reset_time = 0
|
|
||||||
|
|
||||||
@property
|
|
||||||
def calls_remaining(self) -> int:
|
|
||||||
"""Returns the amount of calls remaining."""
|
|
||||||
return self.max_requests - self._calls
|
|
||||||
|
|
||||||
def reset_calls(self) -> None:
|
|
||||||
"""Resets the calls to the max amount."""
|
|
||||||
self._calls = self.max_requests
|
|
||||||
self._reset_time = time.perf_counter() + 1
|
|
||||||
|
|
||||||
def set_reset_time(self, delta: float) -> None:
|
|
||||||
"""
|
|
||||||
Sets the reset time to the current time + delta.
|
|
||||||
|
|
||||||
To be called if a 429 is received.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
delta: The time to wait before resetting the calls.
|
|
||||||
|
|
||||||
"""
|
|
||||||
self._reset_time = time.perf_counter() + delta
|
|
||||||
self._calls = 0
|
|
||||||
|
|
||||||
async def wait(self) -> None:
|
|
||||||
"""Throttles calls to prevent hitting the global rate limit."""
|
|
||||||
async with self._lock:
|
|
||||||
if self._reset_time <= time.perf_counter():
|
|
||||||
self.reset_calls()
|
|
||||||
elif self._calls <= 0:
|
|
||||||
await asyncio.sleep(self._reset_time - time.perf_counter())
|
|
||||||
self.reset_calls()
|
|
||||||
self._calls -= 1
|
|
||||||
|
|
||||||
class HTTPClient(CardRequests, SetRequests):
|
|
||||||
def __init__(self, logger: logging.Logger | None = None):
|
|
||||||
self.__headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"UserAgent": f"pyfall/{__version__}",
|
|
||||||
"Accept": "application/json"
|
|
||||||
}
|
|
||||||
self.__client: AsyncClient = None
|
|
||||||
self.global_lock: GlobalLock = GlobalLock()
|
|
||||||
self._max_attempts: int = 3
|
|
||||||
|
|
||||||
self.logger = logger
|
|
||||||
if self.logger is None:
|
|
||||||
self.logger = get_logger()
|
|
||||||
|
|
||||||
async def request(self, route: Route, params: dict | None = None, **kwargs: dict) -> dict[str, Any]:
|
|
||||||
"""Make a request to the Scryfall API.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
route: Route to take
|
|
||||||
params: Query string parameters. Defaults to None.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict[str, Any]: Raw result
|
|
||||||
"""
|
|
||||||
if params is not None:
|
|
||||||
kwargs["params"] = params
|
|
||||||
if not self.__client:
|
|
||||||
self.__client = AsyncClient(headers=self.__headers)
|
|
||||||
for attempt in range(self._max_attempts):
|
|
||||||
if self.__client is None:
|
|
||||||
self.__client = AsyncClient()
|
|
||||||
|
|
||||||
await self.global_lock.wait()
|
|
||||||
|
|
||||||
response = await self.__client.request(route.method, route.url, **kwargs)
|
|
||||||
|
|
||||||
if response.status_code == 429:
|
|
||||||
self.logger.warning("Too many requests, waiting 5 seconds")
|
|
||||||
self.global_lock.set_reset_time(5)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if response.status_code >= 500:
|
|
||||||
self.logger.warning(f"{route.resolved_endpoint} Received {response.status_code}... retrying in {1 + attempt * 2} seconds")
|
|
||||||
await asyncio.sleep(1 + attempt * 2)
|
|
||||||
continue
|
|
||||||
|
|
||||||
result = response.json()
|
|
||||||
|
|
||||||
if not 300 > response.status_code >= 200:
|
|
||||||
await self._raise_exception(response, route, result)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
async def _raise_exception(self, response, route, result) -> None:
|
|
||||||
self.logger.error(f"{route.method}::{route.url}: {response.status_code}")
|
|
||||||
|
|
||||||
if response.status_code == 403:
|
|
||||||
raise Forbidden(response, route)
|
|
||||||
if response.status_code == 404:
|
|
||||||
raise NotFound(response, route)
|
|
||||||
if response.status_code >= 500:
|
|
||||||
raise ScryfallError(response, route)
|
|
||||||
|
|
||||||
raise HTTPException(response, route)
|
|
||||||
|
|
||||||
async def close(self) -> None:
|
|
||||||
"""Close the session."""
|
|
||||||
if self.__client is not None and not self.__client.is_closed:
|
|
||||||
await self.__client.aclose()
|
|
|
@ -1,4 +1,5 @@
|
||||||
from typing import Any, Literal
|
from typing import Any, Literal
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
from pyfall.models.catalogs import Catalog
|
from pyfall.models.catalogs import Catalog
|
||||||
from pyfall.client.route import Route
|
from pyfall.client.route import Route
|
||||||
|
@ -7,89 +8,121 @@ from pyfall.models.api import APIList
|
||||||
from pyfall.models.rulings import Ruling
|
from pyfall.models.rulings import Ruling
|
||||||
from pyfall.models.internal.protocols import CanRequest
|
from pyfall.models.internal.protocols import CanRequest
|
||||||
|
|
||||||
|
|
||||||
class CardRequests(CanRequest):
|
class CardRequests(CanRequest):
|
||||||
async def get_card_by_id(self, id: str) -> Card:
|
async def get_card_by_id(self, id: str | UUID) -> Card:
|
||||||
"""Get a card by ID.
|
"""
|
||||||
|
Get a card by ID.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
id: UUID of card
|
id: UUID of card
|
||||||
|
|
||||||
"""
|
"""
|
||||||
result = await self.request(Route("GET", f"/cards/{id}"))
|
result = await self.request(Route("GET", f"/cards/{id}"))
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return Card(**result)
|
return Card(**result)
|
||||||
|
|
||||||
async def get_card_by_tcgplayer_id(self, id: int) -> Card:
|
async def get_card_by_tcgplayer_id(self, id: int) -> Card:
|
||||||
"""Get card by TCGPlayer ID
|
"""
|
||||||
|
Get card by TCGPlayer ID
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
id: TCGPlayer ID
|
id: TCGPlayer ID
|
||||||
|
|
||||||
"""
|
"""
|
||||||
result = await self.request(Route("GET", f"/cards/tcgplayer/{id}"))
|
result = await self.request(Route("GET", f"/cards/tcgplayer/{id}"))
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return Card(**result)
|
return Card(**result)
|
||||||
|
|
||||||
async def get_card_by_multiverse_id(self, id: int) -> Card:
|
async def get_card_by_multiverse_id(self, id: int) -> Card:
|
||||||
"""Get card by Multiverse ID
|
"""
|
||||||
|
Get card by Multiverse ID
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
id: Multiverse ID
|
id: Multiverse ID
|
||||||
|
|
||||||
"""
|
"""
|
||||||
result = await self.request(Route("GET", f"/cards/multiverse/{id}"))
|
result = await self.request(Route("GET", f"/cards/multiverse/{id}"))
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return Card(**result)
|
return Card(**result)
|
||||||
|
|
||||||
async def get_card_by_mtgo_id(self, id: int) -> Card:
|
async def get_card_by_mtgo_id(self, id: int) -> Card:
|
||||||
"""Get card by MTGO ID
|
"""
|
||||||
|
Get card by MTGO ID
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
id: MTGO ID
|
id: MTGO ID
|
||||||
|
|
||||||
"""
|
"""
|
||||||
result = await self.request(Route("GET", f"/cards/mtgo/{id}"))
|
result = await self.request(Route("GET", f"/cards/mtgo/{id}"))
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return Card(**result)
|
return Card(**result)
|
||||||
|
|
||||||
async def get_card_by_arena_id(self, id: int) -> Card:
|
async def get_card_by_arena_id(self, id: int) -> Card:
|
||||||
"""Get card by MTG Arena ID
|
"""
|
||||||
|
Get card by MTG Arena ID
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
id: MTG Arena ID
|
id: MTG Arena ID
|
||||||
|
|
||||||
"""
|
"""
|
||||||
result = await self.request(Route("GET", f"/cards/arena/{id}"))
|
result = await self.request(Route("GET", f"/cards/arena/{id}"))
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return Card(**result)
|
return Card(**result)
|
||||||
|
|
||||||
async def get_card_by_cardmarket_id(self, id: int) -> Card:
|
async def get_card_by_cardmarket_id(self, id: int) -> Card:
|
||||||
"""Get card by Cardmarket ID
|
"""
|
||||||
|
Get card by Cardmarket ID
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
id: Cardmarket ID
|
id: Cardmarket ID
|
||||||
|
|
||||||
"""
|
"""
|
||||||
result = await self.request(Route("GET", f"/cards/cardmarket/{id}"))
|
result = await self.request(Route("GET", f"/cards/cardmarket/{id}"))
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return Card(**result)
|
return Card(**result)
|
||||||
|
|
||||||
async def get_rulings_by_card_id(self, id: str) -> list[Ruling]:
|
async def get_rulings_by_card_id(self, id: str | UUID) -> list[Ruling]:
|
||||||
"""Get card rulings by card ID.
|
"""
|
||||||
|
Get card rulings by card ID.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
id: UUID of card
|
id: UUID of card
|
||||||
|
|
||||||
"""
|
"""
|
||||||
result = await self.request(Route("GET", f"/cards/{id}/rulings"))
|
result = await self.request(Route("GET", f"/cards/{id}/rulings"))
|
||||||
return [Ruling(**x) for x in result.get("data")]
|
return [Ruling(**x) for x in result["data"]]
|
||||||
|
|
||||||
async def search_cards(
|
async def search_cards(
|
||||||
self,
|
self,
|
||||||
q: str,
|
q: str,
|
||||||
unique: Literal["cards", "art", "prints"] = "cards",
|
unique: Literal["cards", "art", "prints"] = "cards",
|
||||||
order: Literal["name", "set", "released", "rarity", "color", "usd", "tix", "eur", "cmc", "power", "toughness", "edhrec", "penny", "artist", "review"] = "name",
|
order: Literal[
|
||||||
|
"name",
|
||||||
|
"set",
|
||||||
|
"released",
|
||||||
|
"rarity",
|
||||||
|
"color",
|
||||||
|
"usd",
|
||||||
|
"tix",
|
||||||
|
"eur",
|
||||||
|
"cmc",
|
||||||
|
"power",
|
||||||
|
"toughness",
|
||||||
|
"edhrec",
|
||||||
|
"penny",
|
||||||
|
"artist",
|
||||||
|
"review",
|
||||||
|
] = "name",
|
||||||
dir: Literal["auto", "asc", "desc"] = "auto",
|
dir: Literal["auto", "asc", "desc"] = "auto",
|
||||||
include_extras: bool = False,
|
include_extras: bool = False,
|
||||||
include_multilingual: bool = False,
|
include_multilingual: bool = False,
|
||||||
include_variations: bool = False,
|
include_variations: bool = False,
|
||||||
page: int = 1,
|
page: int = 1,
|
||||||
) -> APIList:
|
) -> APIList:
|
||||||
"""Search for a card using a fulltext string search.
|
"""
|
||||||
|
Search for a card using a fulltext string search.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
q: A fulltext search query. Max length: 1000 Unicode characters
|
q: A fulltext search query. Max length: 1000 Unicode characters
|
||||||
unique: The strategy for omitting cards. Default `cards`
|
unique: The strategy for omitting cards. Default `cards`
|
||||||
|
@ -98,55 +131,55 @@ class CardRequests(CanRequest):
|
||||||
include_extras: If true, extra cards (tokens, planes, etc) will be included. Equivalent to adding `include:extras` to the fulltext search. Default `false`
|
include_extras: If true, extra cards (tokens, planes, etc) will be included. Equivalent to adding `include:extras` to the fulltext search. Default `false`
|
||||||
include_multilingual: If true, cards in every language supported by Scryfall will be included. Default `false`
|
include_multilingual: If true, cards in every language supported by Scryfall will be included. Default `false`
|
||||||
include_variations: If true, rare card variants will by included. Default `false`
|
include_variations: If true, rare card variants will by included. Default `false`
|
||||||
page: Page number to return. Default `1`
|
page: Page number to return. Default `1`
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if len(q) > 1000:
|
if len(q) > 1000:
|
||||||
raise ValueError("Query can only be max of 1000 Unicode characters")
|
raise ValueError("Query can only be max of 1000 Unicode characters")
|
||||||
|
|
||||||
params = dict(
|
params = {
|
||||||
q=q,
|
"q": q,
|
||||||
unique=unique,
|
"unique": unique,
|
||||||
order=order,
|
"order": order,
|
||||||
dir=dir,
|
"dir": dir,
|
||||||
include_extras=include_extras,
|
"include_extras": include_extras,
|
||||||
include_multilingual=include_multilingual,
|
"include_multilingual": include_multilingual,
|
||||||
include_variations=include_variations,
|
"include_variations": include_variations,
|
||||||
page=page
|
"page": page,
|
||||||
)
|
}
|
||||||
|
|
||||||
result = await self.request(
|
result = await self.request(
|
||||||
Route(
|
Route(
|
||||||
"GET",
|
"GET",
|
||||||
"/cards/search",
|
"/cards/search",
|
||||||
),
|
),
|
||||||
params=params
|
params=params,
|
||||||
)
|
)
|
||||||
|
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return APIList(**result)
|
return APIList(**result)
|
||||||
|
|
||||||
async def search_cards_named(
|
async def search_cards_named(
|
||||||
self,
|
self, exact: str | None = None, fuzzy: str | None = None, set: str | None = None
|
||||||
exact: str | None = None,
|
|
||||||
fuzzy: str | None = None,
|
|
||||||
set: str | None = None
|
|
||||||
) -> Card:
|
) -> Card:
|
||||||
"""Search for a card using name search.
|
"""
|
||||||
|
Search for a card using name search.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
exact: Exact string to search for
|
exact: Exact string to search for
|
||||||
fuzzy: Fuzzy string to search for
|
fuzzy: Fuzzy string to search for
|
||||||
set: Set to search in
|
set: Set to search in
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if (not exact and not fuzzy) or (exact and fuzzy):
|
if (not exact and not fuzzy) or (exact and fuzzy):
|
||||||
raise ValueError("Either exact or fuzzy needs provided")
|
raise ValueError("Either exact or fuzzy needs provided")
|
||||||
|
|
||||||
params = dict(set=set)
|
params = {"set": set}
|
||||||
if exact:
|
if exact:
|
||||||
params["exact"] = exact
|
params["exact"] = exact
|
||||||
elif fuzzy:
|
elif fuzzy:
|
||||||
params["fuzzy"] = fuzzy
|
params["fuzzy"] = fuzzy
|
||||||
|
|
||||||
result = await self.request(
|
result = await self.request(
|
||||||
Route(
|
Route(
|
||||||
"GET",
|
"GET",
|
||||||
|
@ -154,60 +187,47 @@ class CardRequests(CanRequest):
|
||||||
),
|
),
|
||||||
params=params,
|
params=params,
|
||||||
)
|
)
|
||||||
|
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return Card(**result)
|
return Card(**result)
|
||||||
|
|
||||||
async def cards_autocomplete(
|
async def cards_autocomplete(self, q: str, include_extras: bool = False) -> Catalog:
|
||||||
self,
|
"""
|
||||||
q: str,
|
Returns a Catalog containing up to 20 full English card names for autocomplete purposes.
|
||||||
include_extras: bool = False
|
|
||||||
) -> Catalog:
|
|
||||||
"""Returns a Catalog containing up to 20 full English card names for autocomplete purposes.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
q: The string to autocomplete
|
q: The string to autocomplete
|
||||||
include_extras: If true, extra cards (tokens, planes, vanguards, etc) will be included. Default False
|
include_extras: If true, extra cards (tokens, planes, vanguards, etc) will be included. Default False
|
||||||
|
|
||||||
"""
|
"""
|
||||||
params = dict(q=q, include_extras=include_extras)
|
params = {"q": q, "include_extras": include_extras}
|
||||||
|
|
||||||
result = await self.request(
|
result = await self.request(
|
||||||
Route(
|
Route("GET", "/cards/autocomplete"),
|
||||||
"GET",
|
|
||||||
"/cards/autocomplete"
|
|
||||||
),
|
|
||||||
params=params,
|
params=params,
|
||||||
)
|
)
|
||||||
|
|
||||||
return Catalog(**result)
|
return Catalog(**result)
|
||||||
|
|
||||||
async def get_random_card(
|
async def get_random_card(
|
||||||
self,
|
self,
|
||||||
q: str | None = None,
|
q: str | None = None,
|
||||||
) -> Card:
|
) -> Card:
|
||||||
params = dict(q=q)
|
params = {"q": q}
|
||||||
|
|
||||||
result = await self.request(
|
result = await self.request(
|
||||||
Route(
|
Route("GET", "/cards/random"),
|
||||||
"GET",
|
|
||||||
"/cards/random"
|
|
||||||
),
|
|
||||||
params=params,
|
params=params,
|
||||||
)
|
)
|
||||||
|
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return Card(**result)
|
return Card(**result)
|
||||||
|
|
||||||
async def get_card_collection(self, identifiers: list[dict[str, Any]]):
|
async def get_card_collection(self, identifiers: list[dict[str, Any]]):
|
||||||
raise NotImplementedError("This endpoint has not been implemented")
|
raise NotImplementedError("This endpoint has not been implemented")
|
||||||
|
|
||||||
async def get_card_by_set_code_and_collector_number(self, code: str, number: str, lang: str | None = None) -> Card:
|
async def get_card_by_set_code_and_collector_number(self, code: str, number: str, lang: str | None = None) -> Card:
|
||||||
result = await self.request(
|
result = await self.request(Route("GET", f"/cards/{code}/{number}{f'/{lang}' if lang else ''}"))
|
||||||
Route(
|
|
||||||
"GET",
|
|
||||||
f"/cards/{code}/{number}{f'/{lang}' if lang else ''}"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return Card(**result)
|
return Card(**result)
|
||||||
|
|
|
@ -1,50 +1,54 @@
|
||||||
from typing import Any, Literal
|
from uuid import UUID
|
||||||
|
|
||||||
from pyfall.models.catalogs import Catalog
|
|
||||||
from pyfall.client.route import Route
|
from pyfall.client.route import Route
|
||||||
from pyfall.models.cards import Card
|
|
||||||
from pyfall.models.api import APIList
|
from pyfall.models.api import APIList
|
||||||
from pyfall.models.rulings import Ruling
|
|
||||||
from pyfall.models.sets import Set
|
from pyfall.models.sets import Set
|
||||||
from pyfall.models.internal.protocols import CanRequest
|
from pyfall.models.internal.protocols import CanRequest
|
||||||
|
|
||||||
|
|
||||||
class SetRequests(CanRequest):
|
class SetRequests(CanRequest):
|
||||||
async def get_all_sets(self) -> APIList:
|
async def get_all_sets(self) -> APIList:
|
||||||
"""Get all MTG sets."""
|
"""Get all MTG sets."""
|
||||||
result = await self.request(Route("GET", "/sets"))
|
result = await self.request(Route("GET", "/sets"))
|
||||||
|
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return APIList(**result)
|
return APIList(**result)
|
||||||
|
|
||||||
async def get_set_by_id(self, id: str) -> Set:
|
async def get_set_by_id(self, id: str | UUID) -> Set:
|
||||||
"""Get MTG set by ID.
|
"""
|
||||||
|
Get MTG set by ID.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
id: UUID of set
|
id: UUID of set
|
||||||
|
|
||||||
"""
|
"""
|
||||||
result = await self.request(Route("GET", f"/sets/{id}"))
|
result = await self.request(Route("GET", f"/sets/{id}"))
|
||||||
|
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return Set(**result)
|
return Set(**result)
|
||||||
|
|
||||||
async def get_set_by_code(self, code: str) -> Set:
|
async def get_set_by_code(self, code: str) -> Set:
|
||||||
"""Get MTG set by set code.
|
"""
|
||||||
|
Get MTG set by set code.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
code: Set code
|
code: Set code
|
||||||
|
|
||||||
"""
|
"""
|
||||||
result = await self.request(Route("GET", f"/sets/{code}"))
|
result = await self.request(Route("GET", f"/sets/{code}"))
|
||||||
|
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return Set(**result)
|
return Set(**result)
|
||||||
|
|
||||||
async def get_set_by_tcgplayer_id(self, id: str) -> Set:
|
async def get_set_by_tcgplayer_id(self, id: int) -> Set:
|
||||||
"""Get MTG set by TCGPlayer ID.
|
"""
|
||||||
|
Get MTG set by TCGPlayer ID.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
id: TCGPlayer ID of set
|
id: TCGPlayer ID of set
|
||||||
|
|
||||||
"""
|
"""
|
||||||
result = await self.request(Route("GET", f"/sets/tcgplayer/{id}"))
|
result = await self.request(Route("GET", f"/sets/tcgplayer/{id}"))
|
||||||
|
|
||||||
result["_client"] = self
|
result["_client"] = self
|
||||||
return Set(**result)
|
return Set(**result)
|
||||||
|
|
|
@ -3,11 +3,12 @@ from urllib.parse import quote as _uriquote
|
||||||
|
|
||||||
PAYLOAD_TYPE = dict[str, int | str | bool | list | None]
|
PAYLOAD_TYPE = dict[str, int | str | bool | list | None]
|
||||||
|
|
||||||
|
|
||||||
class Route:
|
class Route:
|
||||||
BASE: ClassVar[str] = "https://api.scryfall.com"
|
BASE: ClassVar[str] = "https://api.scryfall.com"
|
||||||
path: str
|
path: str
|
||||||
params: dict[str, str | int | bool]
|
params: dict[str, str | int | bool]
|
||||||
|
|
||||||
def __init__(self, method: str, path: str, **params: Any) -> None:
|
def __init__(self, method: str, path: str, **params: Any) -> None:
|
||||||
self.path: str = path
|
self.path: str = path
|
||||||
self.method: str = method
|
self.method: str = method
|
||||||
|
@ -18,7 +19,7 @@ class Route:
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.endpoint
|
return self.endpoint
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def resolved_path(self) -> str:
|
def resolved_path(self) -> str:
|
||||||
"""The endpoint for this route, with all parameters resolved"""
|
"""The endpoint for this route, with all parameters resolved"""
|
||||||
|
@ -32,13 +33,9 @@ class Route:
|
||||||
@property
|
@property
|
||||||
def resolved_endpoint(self) -> str:
|
def resolved_endpoint(self) -> str:
|
||||||
"""The endpoint for this route, with all major parameters resolved"""
|
"""The endpoint for this route, with all major parameters resolved"""
|
||||||
path = self.path
|
return f"{self.method} {self.path}"
|
||||||
for key, value in self.major_params.items():
|
|
||||||
path = path.replace(f"{{{key}}}", str(value))
|
|
||||||
|
|
||||||
return f"{self.method} {path}"
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url(self) -> str:
|
def url(self) -> str:
|
||||||
"""The full url for this route"""
|
"""The full url for this route"""
|
||||||
return f"{self.BASE}{self.resolved_path}"
|
return f"{self.BASE}{self.resolved_path}"
|
||||||
|
|
|
@ -6,6 +6,7 @@ logger_name = "pyfall"
|
||||||
|
|
||||||
_logger = logging.getLogger(logger_name)
|
_logger = logging.getLogger(logger_name)
|
||||||
|
|
||||||
|
|
||||||
def get_logger() -> logging.Logger:
|
def get_logger() -> logging.Logger:
|
||||||
global _logger
|
global _logger
|
||||||
return _logger
|
return _logger
|
||||||
|
|
|
@ -6,4 +6,4 @@ from .rulings import Ruling
|
||||||
from .sets import Set
|
from .sets import Set
|
||||||
from .symbols import CardSymbol
|
from .symbols import CardSymbol
|
||||||
|
|
||||||
__all__ = ["APIError", "APIList", "BulkData", "Card", "Catalog", "Ruling", "Set", "CardSymbol"]
|
__all__ = ["APIError", "APIList", "BulkData", "Card", "Catalog", "Ruling", "Set", "CardSymbol"]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Any, Literal, Self
|
from typing import Any, Literal
|
||||||
|
|
||||||
from pydantic import BaseModel, HttpUrl, ValidationError, model_validator
|
from pydantic import BaseModel, HttpUrl, ValidationError, model_validator
|
||||||
|
|
||||||
|
@ -8,12 +8,8 @@ from pyfall.models.rulings import Ruling
|
||||||
from pyfall.models.sets import Set
|
from pyfall.models.sets import Set
|
||||||
from pyfall.models.symbols import CardSymbol
|
from pyfall.models.symbols import CardSymbol
|
||||||
|
|
||||||
CLASS_LOOKUP = {
|
CLASS_LOOKUP = {"card": Card, "card_symbol": CardSymbol, "ruling": Ruling, "set": Set}
|
||||||
"card": Card,
|
|
||||||
"card_symbol": CardSymbol,
|
|
||||||
"ruling": Ruling,
|
|
||||||
"set": Set
|
|
||||||
}
|
|
||||||
|
|
||||||
class APIError(BaseModel):
|
class APIError(BaseModel):
|
||||||
status: int
|
status: int
|
||||||
|
@ -21,7 +17,8 @@ class APIError(BaseModel):
|
||||||
details: str
|
details: str
|
||||||
type: str | None = None
|
type: str | None = None
|
||||||
warnings: list[str] | None = None
|
warnings: list[str] | None = None
|
||||||
|
|
||||||
|
|
||||||
class APIList(BaseAPIModel):
|
class APIList(BaseAPIModel):
|
||||||
object: Literal["list"]
|
object: Literal["list"]
|
||||||
data: list[Card | CardSymbol | Ruling | Set]
|
data: list[Card | CardSymbol | Ruling | Set]
|
||||||
|
@ -29,19 +26,22 @@ class APIList(BaseAPIModel):
|
||||||
next_page: HttpUrl | None = None
|
next_page: HttpUrl | None = None
|
||||||
total_cards: int | None = None
|
total_cards: int | None = None
|
||||||
warnings: list[str] | None = None
|
warnings: list[str] | None = None
|
||||||
|
|
||||||
@model_validator(mode="before")
|
@model_validator(mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_data(cls, data: Any) -> Any:
|
def validate_data(cls, data: Any) -> Any:
|
||||||
if data.get("object") == "list":
|
if data.get("object") == "list":
|
||||||
for item in data.get("data"):
|
for item in data.get("data"):
|
||||||
item["_client"] = data["_client"]
|
item["_client"] = data["_client"]
|
||||||
item = CLASS_LOOKUP.get(item.get("object"))(**item)
|
obj = item.get("object")
|
||||||
|
if obj not in CLASS_LOOKUP:
|
||||||
|
raise ValidationError("Item missing object field")
|
||||||
|
item = CLASS_LOOKUP[obj](**item)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
async def get_next_page(self) -> Self | None:
|
async def get_next_page(self) -> "APIList | None":
|
||||||
if self.has_more:
|
if self.has_more and self.next_page is not None:
|
||||||
params = dict(self.next_page.query_params())
|
params = dict(self.next_page.query_params())
|
||||||
params.pop("format", None)
|
params.pop("format", None)
|
||||||
return await self._client.cards_search(**params)
|
return await self._client.search_cards(**params) # type: ignore
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -5,11 +5,13 @@ from pydantic import BaseModel
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pyfall.client import Pyfall
|
from pyfall.client import Pyfall
|
||||||
|
|
||||||
|
|
||||||
class BaseAPIModel(BaseModel):
|
class BaseAPIModel(BaseModel):
|
||||||
"""Base API model for base API calls."""
|
"""Base API model for base API calls."""
|
||||||
|
|
||||||
_client: "Pyfall"
|
_client: "Pyfall"
|
||||||
|
|
||||||
def __init__(self, **data):
|
def __init__(self, **data):
|
||||||
client = data.get("_client")
|
client: "Pyfall" = data["_client"]
|
||||||
super().__init__(**data)
|
super().__init__(**data)
|
||||||
self._client = client
|
self._client = client
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
from pydantic import BaseModel, HttpUrl
|
from pydantic import BaseModel, HttpUrl
|
||||||
from pydantic.types import UUID
|
|
||||||
|
|
||||||
class BulkData(BaseModel):
|
class BulkData(BaseModel):
|
||||||
id: UUID
|
id: UUID
|
||||||
|
@ -13,4 +14,4 @@ class BulkData(BaseModel):
|
||||||
updated_at: datetime
|
updated_at: datetime
|
||||||
size: int
|
size: int
|
||||||
content_type: str
|
content_type: str
|
||||||
content_encoding: str
|
content_encoding: str
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from typing import Any, Literal, TYPE_CHECKING
|
from typing import Any, Literal, TYPE_CHECKING
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
from pydantic import BaseModel, HttpUrl, field_validator
|
from pydantic import BaseModel, HttpUrl, field_validator
|
||||||
from pydantic.types import UUID
|
|
||||||
|
|
||||||
# from pyfall.models.api import APIList
|
|
||||||
from pyfall.models.base import BaseAPIModel
|
from pyfall.models.base import BaseAPIModel
|
||||||
from pyfall.models.enums import Color
|
from pyfall.models.enums import Color
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pyfall.client import Pyfall
|
|
||||||
from pyfall.models.rulings import Ruling
|
from pyfall.models.rulings import Ruling
|
||||||
from pyfall.models.sets import Set
|
from pyfall.models.sets import Set
|
||||||
|
|
||||||
|
|
||||||
class RelatedCard(BaseModel):
|
class RelatedCard(BaseModel):
|
||||||
id: UUID
|
id: UUID
|
||||||
object: Literal["related_card"]
|
object: Literal["related_card"]
|
||||||
|
@ -20,7 +19,8 @@ class RelatedCard(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
type_line: str
|
type_line: str
|
||||||
uri: HttpUrl
|
uri: HttpUrl
|
||||||
|
|
||||||
|
|
||||||
class CardFace(BaseModel):
|
class CardFace(BaseModel):
|
||||||
artist: str | None = None
|
artist: str | None = None
|
||||||
artist_id: str | None = None
|
artist_id: str | None = None
|
||||||
|
@ -45,12 +45,13 @@ class CardFace(BaseModel):
|
||||||
toughness: str | None = None
|
toughness: str | None = None
|
||||||
type_line: str | None = None
|
type_line: str | None = None
|
||||||
watermark: str | None = None
|
watermark: str | None = None
|
||||||
|
|
||||||
|
|
||||||
class Preview(BaseModel):
|
class Preview(BaseModel):
|
||||||
previewed_at: date | None = None
|
previewed_at: date | None = None
|
||||||
source_uri: HttpUrl | None = None
|
source_uri: HttpUrl | None = None
|
||||||
source: str | None = None
|
source: str | None = None
|
||||||
|
|
||||||
@field_validator("source_uri", mode="before")
|
@field_validator("source_uri", mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_source_uri(cls, value: Any) -> Any:
|
def validate_source_uri(cls, value: Any) -> Any:
|
||||||
|
@ -59,6 +60,7 @@ class Preview(BaseModel):
|
||||||
return HttpUrl(value)
|
return HttpUrl(value)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class Card(BaseAPIModel):
|
class Card(BaseAPIModel):
|
||||||
# Core fields
|
# Core fields
|
||||||
arena_id: int | None = None
|
arena_id: int | None = None
|
||||||
|
@ -77,7 +79,7 @@ class Card(BaseAPIModel):
|
||||||
rulings_uri: HttpUrl
|
rulings_uri: HttpUrl
|
||||||
scryfall_uri: HttpUrl
|
scryfall_uri: HttpUrl
|
||||||
uri: HttpUrl
|
uri: HttpUrl
|
||||||
|
|
||||||
# Gameplay fields
|
# Gameplay fields
|
||||||
all_parts: list[RelatedCard] | None = None
|
all_parts: list[RelatedCard] | None = None
|
||||||
card_faces: list[CardFace] | None = None
|
card_faces: list[CardFace] | None = None
|
||||||
|
@ -102,7 +104,7 @@ class Card(BaseAPIModel):
|
||||||
reserved: bool
|
reserved: bool
|
||||||
toughness: str | None = None
|
toughness: str | None = None
|
||||||
type_line: str
|
type_line: str
|
||||||
|
|
||||||
# Print fields
|
# Print fields
|
||||||
artist: str | None = None
|
artist: str | None = None
|
||||||
artist_ids: list[UUID] | None = None
|
artist_ids: list[UUID] | None = None
|
||||||
|
@ -150,12 +152,11 @@ class Card(BaseAPIModel):
|
||||||
security_stamp: Literal["oval", "triangle", "acorn", "circle", "arena", "heart"] | None = None
|
security_stamp: Literal["oval", "triangle", "acorn", "circle", "arena", "heart"] | None = None
|
||||||
watermark: str | None = None
|
watermark: str | None = None
|
||||||
preview: Preview | None = None
|
preview: Preview | None = None
|
||||||
|
|
||||||
async def get_set(self) -> "Set":
|
async def get_set(self) -> "Set":
|
||||||
"""Get set card is a part of."""
|
"""Get set card is a part of."""
|
||||||
return await self._client.get_set_by_id(self.set_id)
|
return await self._client.get_set_by_id(self.set_id)
|
||||||
|
|
||||||
async def get_rulings(self) -> "Ruling":
|
async def get_rulings(self) -> list["Ruling"]:
|
||||||
"""Get rulings for card."""
|
"""Get rulings for card."""
|
||||||
return await self._client.get_rulings_by_card_id(self.id)
|
return await self._client.get_rulings_by_card_id(self.id)
|
||||||
|
|
|
@ -2,8 +2,9 @@ from typing import Literal
|
||||||
|
|
||||||
from pydantic import BaseModel, HttpUrl
|
from pydantic import BaseModel, HttpUrl
|
||||||
|
|
||||||
|
|
||||||
class Catalog(BaseModel):
|
class Catalog(BaseModel):
|
||||||
object: Literal["catalog"]
|
object: Literal["catalog"]
|
||||||
uri: HttpUrl | None = None
|
uri: HttpUrl | None = None
|
||||||
total_values: int
|
total_values: int
|
||||||
data: list[str]
|
data: list[str]
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
class Color(Enum):
|
class Color(Enum):
|
||||||
White = "W"
|
White = "W"
|
||||||
Blue = "U"
|
Blue = "U"
|
||||||
Black = "B"
|
Black = "B"
|
||||||
Red = "R"
|
Red = "R"
|
||||||
Green = "G"
|
Green = "G"
|
||||||
Colorless = "C"
|
Colorless = "C"
|
||||||
|
|
|
@ -3,7 +3,8 @@ from typing import Protocol, Any, TypeVar
|
||||||
|
|
||||||
from pyfall.client.route import Route
|
from pyfall.client.route import Route
|
||||||
|
|
||||||
T_co = TypeVar("T", covariant=True)
|
T_co = TypeVar("T", covariant=True) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
@typing.runtime_checkable
|
@typing.runtime_checkable
|
||||||
class CanRequest(Protocol[T_co]):
|
class CanRequest(Protocol[T_co]):
|
||||||
|
@ -13,4 +14,4 @@ class CanRequest(Protocol[T_co]):
|
||||||
params: dict | None = None,
|
params: dict | None = None,
|
||||||
**kwargs: dict,
|
**kwargs: dict,
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
raise NotImplementedError("Derived classes need to implement this.")
|
raise NotImplementedError("Derived classes need to implement this.")
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from pydantic.types import UUID
|
|
||||||
|
|
||||||
class Ruling(BaseModel):
|
class Ruling(BaseModel):
|
||||||
object: Literal["ruling"]
|
object: Literal["ruling"]
|
||||||
oracle_id: UUID
|
oracle_id: UUID
|
||||||
source: Literal["wotc", "scryfall"]
|
source: Literal["wotc", "scryfall"]
|
||||||
published_at: date
|
published_at: date
|
||||||
comment: str
|
comment: str
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from typing import Literal, TYPE_CHECKING
|
from typing import Literal, TYPE_CHECKING
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
from pydantic import HttpUrl
|
from pydantic import HttpUrl
|
||||||
from pydantic.types import UUID
|
|
||||||
|
|
||||||
from pyfall.models.base import BaseAPIModel
|
from pyfall.models.base import BaseAPIModel
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pyfall.client import Pyfall
|
|
||||||
from pyfall.models.api import APIList
|
from pyfall.models.api import APIList
|
||||||
|
|
||||||
|
|
||||||
class Set(BaseAPIModel):
|
class Set(BaseAPIModel):
|
||||||
object: Literal["set"]
|
object: Literal["set"]
|
||||||
id: UUID
|
id: UUID
|
||||||
|
@ -32,8 +32,8 @@ class Set(BaseAPIModel):
|
||||||
uri: HttpUrl
|
uri: HttpUrl
|
||||||
icon_svg_uri: HttpUrl
|
icon_svg_uri: HttpUrl
|
||||||
search_uri: HttpUrl
|
search_uri: HttpUrl
|
||||||
|
|
||||||
async def get_cards(self) -> "APIList":
|
async def get_cards(self) -> "APIList":
|
||||||
"""Get a list of cards from the set."""
|
"""Get a list of cards from the set."""
|
||||||
params = dict(self.search_uri.query_params())
|
params = dict(self.search_uri.query_params())
|
||||||
return await self._client.search_cards(**params)
|
return await self._client.search_cards(**params) # type: ignore
|
||||||
|
|
|
@ -4,6 +4,7 @@ from pydantic import BaseModel, HttpUrl
|
||||||
|
|
||||||
from pyfall.models.enums import Color
|
from pyfall.models.enums import Color
|
||||||
|
|
||||||
|
|
||||||
class CardSymbol(BaseModel):
|
class CardSymbol(BaseModel):
|
||||||
object: Literal["card_symbol"]
|
object: Literal["card_symbol"]
|
||||||
symbol: str
|
symbol: str
|
||||||
|
@ -18,4 +19,4 @@ class CardSymbol(BaseModel):
|
||||||
hybrid: bool
|
hybrid: bool
|
||||||
phyrexian: bool
|
phyrexian: bool
|
||||||
gatherer_alternatives: str | None = None
|
gatherer_alternatives: str | None = None
|
||||||
svg_uri: HttpUrl | None = None
|
svg_uri: HttpUrl | None = None
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
UUID_CHECK = re.compile(r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", flags=re.I)
|
UUID_CHECK = re.compile(r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", flags=re.I)
|
||||||
|
|
135
pyproject.toml
135
pyproject.toml
|
@ -1,18 +1,141 @@
|
||||||
[project]
|
[project]
|
||||||
name = "pyfall"
|
name = "pyfall"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Add your description here"
|
description = "An async Scryfall API wrapper"
|
||||||
|
license = { text = "MIT License" }
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.13"
|
requires-python = ">=3.13"
|
||||||
dependencies = [
|
classifiers = [
|
||||||
"httpx>=0.28.1",
|
"Development Status :: 4 - Beta",
|
||||||
"pydantic>=2.10.6",
|
"Framework :: Hatch",
|
||||||
|
"Framework :: Sphinx",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"License :: OSI Approved :: MIT License",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Programming Language :: Python :: 3.13",
|
||||||
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
|
"Topic :: Utilities",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
dependencies = ["httpx>=0.28.1", "pydantic>=2.10.6"]
|
||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
dev = [
|
dev = [
|
||||||
"black>=25.1.0",
|
"black>=25.1.0",
|
||||||
"ipython>=8.32.0",
|
"ipython>=9.0.0",
|
||||||
"rich>=13.9.4",
|
"rich>=13.9.4",
|
||||||
"ruff>=0.9.7",
|
"ruff>=0.9.9",
|
||||||
|
"pre-commit>=4.0.1",
|
||||||
|
"pytest>=8.3.3",
|
||||||
|
"pytest-cov>=6.0.0",
|
||||||
|
"sphinx-toolbox>=3.9.0",
|
||||||
|
"sphinx>=8.2.1",
|
||||||
|
"sphinx-rtd-theme>=3.0.2",
|
||||||
|
"pytest-asyncio>=0.25.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
minversion = "8.0"
|
||||||
|
testpaths = ["tests"]
|
||||||
|
addopts = "--cov --cov-report term-missing --cov-report xml:coverage.xml --junitxml=report.xml"
|
||||||
|
|
||||||
|
[tool.black]
|
||||||
|
line-length = 120
|
||||||
|
|
||||||
|
[tool.isort]
|
||||||
|
profile = "black"
|
||||||
|
skip = ["__init__.py"]
|
||||||
|
|
||||||
|
[tool.mypy]
|
||||||
|
ignore_missing_imports = true
|
||||||
|
|
||||||
|
[tool.pyright]
|
||||||
|
useLibraryCodeForTypes = true
|
||||||
|
reportMissingImports = false
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 120
|
||||||
|
target-version = "py313"
|
||||||
|
output-format = "full"
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
task-tags = ["TODO", "FIXME", "XXX", "HACK", "REVIEW", "NOTE"]
|
||||||
|
select = ["E", "F", "B", "Q", "RUF", "D", "ANN", "RET", "C"]
|
||||||
|
ignore = [
|
||||||
|
"Q0",
|
||||||
|
"E501",
|
||||||
|
# These default to arguing with Black. We might configure some of them eventually
|
||||||
|
"ANN1",
|
||||||
|
# These insist that we have Type Annotations for self and cls.
|
||||||
|
"D105",
|
||||||
|
"D107",
|
||||||
|
# Missing Docstrings in magic method and __init__
|
||||||
|
"D401",
|
||||||
|
# First line should be in imperative mood; try rephrasing
|
||||||
|
"D400",
|
||||||
|
"D415",
|
||||||
|
# First line should end with a period
|
||||||
|
"D106",
|
||||||
|
# Missing docstring in public nested class. This doesn't work well with Metadata classes.
|
||||||
|
"D417",
|
||||||
|
# Missing argument in the docstring
|
||||||
|
"D406",
|
||||||
|
# Section name should end with a newline
|
||||||
|
"D407",
|
||||||
|
# Missing dashed underline after section
|
||||||
|
"D212",
|
||||||
|
# Multi-line docstring summary should start at the first line
|
||||||
|
"D404",
|
||||||
|
# First word of the docstring should not be This
|
||||||
|
"D203",
|
||||||
|
# 1 blank line required before class docstring
|
||||||
|
|
||||||
|
# Everything below this line is something we care about, but don't currently meet
|
||||||
|
"ANN001",
|
||||||
|
# Missing type annotation for function argument 'token'
|
||||||
|
"ANN002",
|
||||||
|
# Missing type annotation for *args
|
||||||
|
"ANN003",
|
||||||
|
# Missing type annotation for **kwargs
|
||||||
|
"ANN401",
|
||||||
|
# Dynamically typed expressions (typing.Any) are disallowed
|
||||||
|
# "B009",
|
||||||
|
# Do not call getattr with a constant attribute value, it is not any safer than normal property access.
|
||||||
|
"B010",
|
||||||
|
# Do not call setattr with a constant attribute value, it is not any safer than normal property access.
|
||||||
|
"D100",
|
||||||
|
# Missing docstring in public module
|
||||||
|
"D101",
|
||||||
|
# ... class
|
||||||
|
"D102",
|
||||||
|
# ... method
|
||||||
|
"D103",
|
||||||
|
# ... function
|
||||||
|
"D104",
|
||||||
|
# ... package
|
||||||
|
"E712",
|
||||||
|
# Ignore == True because of Beanie
|
||||||
|
# Plugins we don't currently include: flake8-return
|
||||||
|
"RET503",
|
||||||
|
# missing explicit return at the end of function ableto return non-None value.
|
||||||
|
"RET504",
|
||||||
|
# unecessary variable assignement before return statement.
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.ruff.lint.flake8-quotes]
|
||||||
|
docstring-quotes = "double"
|
||||||
|
|
||||||
|
[tool.ruff.lint.flake8-annotations]
|
||||||
|
mypy-init-return = true
|
||||||
|
suppress-dummy-args = true
|
||||||
|
suppress-none-returning = true
|
||||||
|
|
||||||
|
[tool.ruff.lint.flake8-errmsg]
|
||||||
|
max-string-length = 20
|
||||||
|
|
||||||
|
[tool.ruff.lint.mccabe]
|
||||||
|
max-complexity = 13
|
||||||
|
|
87
tests/test_card_endpoints.py
Normal file
87
tests/test_card_endpoints.py
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from pyfall import Pyfall
|
||||||
|
|
||||||
|
test_card_uuid = "1e90c638-d4b2-4243-bbc4-1cc10516c40f"
|
||||||
|
test_card_name = "Arcades, the Strategist"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_card_by_all_ids():
|
||||||
|
client = Pyfall()
|
||||||
|
card = await client.get_card_by_id(test_card_uuid)
|
||||||
|
|
||||||
|
assert card.name == test_card_name
|
||||||
|
assert card.arena_id is not None
|
||||||
|
assert card.mtgo_id is not None
|
||||||
|
assert card.tcgplayer_id is not None
|
||||||
|
assert card.cardmarket_id is not None
|
||||||
|
|
||||||
|
_ = await client.get_card_by_arena_id(card.arena_id)
|
||||||
|
_ = await client.get_card_by_cardmarket_id(card.cardmarket_id)
|
||||||
|
_ = await client.get_card_by_mtgo_id(card.mtgo_id)
|
||||||
|
_ = await client.get_card_by_tcgplayer_id(card.tcgplayer_id)
|
||||||
|
if card.multiverse_ids and len(card.multiverse_ids) > 0:
|
||||||
|
_ = await client.get_card_by_multiverse_id(card.multiverse_ids[0])
|
||||||
|
|
||||||
|
await client.close()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_card_rulings():
|
||||||
|
client = Pyfall()
|
||||||
|
card = await client.get_card_by_id(test_card_uuid)
|
||||||
|
|
||||||
|
rulings = await card.get_rulings()
|
||||||
|
assert len(rulings) > 0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_search_card_all():
|
||||||
|
client = Pyfall()
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
_ = await client.search_cards(q="_" * 1001)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
_ = await client.search_cards_named()
|
||||||
|
|
||||||
|
cards = await client.search_cards(q="arcades, the strategist", unique="cards")
|
||||||
|
assert any(str(x.id) == test_card_uuid for x in cards.data if x.object == "card")
|
||||||
|
assert await cards.get_next_page() is None
|
||||||
|
|
||||||
|
card = await client.search_cards_named(exact="arcades, the strategist")
|
||||||
|
assert str(card.id) == test_card_uuid
|
||||||
|
|
||||||
|
card = await client.search_cards_named(fuzzy="arcades the strategist")
|
||||||
|
assert str(card.id) == test_card_uuid
|
||||||
|
|
||||||
|
cards = await client.search_cards(q="angel")
|
||||||
|
if cards.has_more:
|
||||||
|
cards = await cards.get_next_page()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_cards_autocomplete():
|
||||||
|
client = Pyfall()
|
||||||
|
|
||||||
|
catalog = await client.cards_autocomplete(q="avacyn")
|
||||||
|
|
||||||
|
assert "Avacyn, Angel of Hope" in catalog.data
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_random_card():
|
||||||
|
client = Pyfall()
|
||||||
|
|
||||||
|
card = await client.get_random_card()
|
||||||
|
assert card is not None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_card_set():
|
||||||
|
client = Pyfall()
|
||||||
|
card = await client.get_card_by_id(test_card_uuid)
|
||||||
|
card_set = await card.get_set()
|
||||||
|
|
||||||
|
assert card_set.code == "m19"
|
26
tests/test_set_endpoints.py
Normal file
26
tests/test_set_endpoints.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from pyfall import Pyfall
|
||||||
|
|
||||||
|
test_set_uuid = "2f5f2509-56db-414d-9a7e-6e312ec3760c"
|
||||||
|
test_set_name = "Core Set 2019"
|
||||||
|
test_set_code = "m19"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_all_sets():
|
||||||
|
client = Pyfall()
|
||||||
|
_ = await client.get_all_sets()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_set():
|
||||||
|
client = Pyfall()
|
||||||
|
|
||||||
|
set_ = await client.get_set_by_id(test_set_uuid)
|
||||||
|
assert set_.name == test_set_name
|
||||||
|
|
||||||
|
if set_.tcgplayer_id is not None:
|
||||||
|
assert (await client.get_set_by_tcgplayer_id(set_.tcgplayer_id)) is not None
|
||||||
|
|
||||||
|
assert str((await client.get_set_by_code("m19")).id) == test_set_uuid
|
804
uv.lock
generated
804
uv.lock
generated
|
@ -2,6 +2,15 @@ version = 1
|
||||||
revision = 1
|
revision = 1
|
||||||
requires-python = ">=3.13"
|
requires-python = ">=3.13"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alabaster"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "annotated-types"
|
name = "annotated-types"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -24,6 +33,34 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/46/eb/e7f063ad1fec6b3178a3cd82d1a3c4de82cccf283fc42746168188e1cdd5/anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a", size = 96041 },
|
{ url = "https://files.pythonhosted.org/packages/46/eb/e7f063ad1fec6b3178a3cd82d1a3c4de82cccf283fc42746168188e1cdd5/anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a", size = 96041 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "apeye"
|
||||||
|
version = "1.4.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "apeye-core" },
|
||||||
|
{ name = "domdf-python-tools" },
|
||||||
|
{ name = "platformdirs" },
|
||||||
|
{ name = "requests" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/4f/6b/cc65e31843d7bfda8313a9dc0c77a21e8580b782adca53c7cb3e511fe023/apeye-1.4.1.tar.gz", hash = "sha256:14ea542fad689e3bfdbda2189a354a4908e90aee4bf84c15ab75d68453d76a36", size = 99219 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/89/7b/2d63664777b3e831ac1b1d8df5bbf0b7c8bee48e57115896080890527b1b/apeye-1.4.1-py3-none-any.whl", hash = "sha256:44e58a9104ec189bf42e76b3a7fe91e2b2879d96d48e9a77e5e32ff699c9204e", size = 107989 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "apeye-core"
|
||||||
|
version = "1.1.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "domdf-python-tools" },
|
||||||
|
{ name = "idna" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/e5/4c/4f108cfd06923bd897bf992a6ecb6fb122646ee7af94d7f9a64abd071d4c/apeye_core-1.1.5.tar.gz", hash = "sha256:5de72ed3d00cc9b20fea55e54b7ab8f5ef8500eb33a5368bc162a5585e238a55", size = 96511 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/77/9f/fa9971d2a0c6fef64c87ba362a493a4f230eff4ea8dfb9f4c7cbdf71892e/apeye_core-1.1.5-py3-none-any.whl", hash = "sha256:dc27a93f8c9e246b3b238c5ea51edf6115ab2618ef029b9f2d9a190ec8228fbf", size = 99286 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asttokens"
|
name = "asttokens"
|
||||||
version = "3.0.0"
|
version = "3.0.0"
|
||||||
|
@ -33,6 +70,40 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918 },
|
{ url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autodocsumm"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "sphinx" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/03/96/92afe8a7912b327c01f0a8b6408c9556ee13b1aba5b98d587ac7327ff32d/autodocsumm-0.2.14.tar.gz", hash = "sha256:2839a9d4facc3c4eccd306c08695540911042b46eeafcdc3203e6d0bab40bc77", size = 46357 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/87/bc/3f66af9beb683728e06ca08797e4e9d3e44f432f339718cae3ba856a9cad/autodocsumm-0.2.14-py3-none-any.whl", hash = "sha256:3bad8717fc5190802c60392a7ab04b9f3c97aa9efa8b3780b3d81d615bfe5dc0", size = 14640 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "babel"
|
||||||
|
version = "2.17.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "beautifulsoup4"
|
||||||
|
version = "4.13.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "soupsieve" },
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/f0/3c/adaf39ce1fb4afdd21b611e3d530b183bb7759c9b673d60db0e347fd4439/beautifulsoup4-4.13.3.tar.gz", hash = "sha256:1bd32405dacc920b42b83ba01644747ed77456a65760e285fbc47633ceddaf8b", size = 619516 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f9/49/6abb616eb3cbab6a7cca303dc02fdf3836de2e0b834bf966a7f5271a34d8/beautifulsoup4-4.13.3-py3-none-any.whl", hash = "sha256:99045d7d3f08f91f0d656bc9b7efbae189426cd913d830294a15eefa0ea4df16", size = 186015 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "black"
|
name = "black"
|
||||||
version = "25.1.0"
|
version = "25.1.0"
|
||||||
|
@ -53,6 +124,24 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646 },
|
{ url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cachecontrol"
|
||||||
|
version = "0.14.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "msgpack" },
|
||||||
|
{ name = "requests" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b7/a4/3390ac4dfa1773f661c8780368018230e8207ec4fd3800d2c0c3adee4456/cachecontrol-0.14.2.tar.gz", hash = "sha256:7d47d19f866409b98ff6025b6a0fca8e4c791fb31abbd95f622093894ce903a2", size = 28832 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c8/63/baffb44ca6876e7b5fc8fe17b24a7c07bf479d604a592182db9af26ea366/cachecontrol-0.14.2-py3-none-any.whl", hash = "sha256:ebad2091bf12d0d200dfc2464330db638c5deb41d546f6d7aca079e87290f3b0", size = 21780 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.optional-dependencies]
|
||||||
|
filecache = [
|
||||||
|
{ name = "filelock" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "certifi"
|
name = "certifi"
|
||||||
version = "2025.1.31"
|
version = "2025.1.31"
|
||||||
|
@ -62,6 +151,37 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 },
|
{ url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfgv"
|
||||||
|
version = "3.4.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "charset-normalizer"
|
||||||
|
version = "3.4.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/38/94/ce8e6f63d18049672c76d07d119304e1e2d7c6098f0841b51c666e9f44a0/charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", size = 195698 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/24/2e/dfdd9770664aae179a96561cc6952ff08f9a8cd09a908f259a9dfa063568/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", size = 140162 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/24/4e/f646b9093cff8fc86f2d60af2de4dc17c759de9d554f130b140ea4738ca6/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", size = 150263 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5e/67/2937f8d548c3ef6e2f9aab0f6e21001056f692d43282b165e7c56023e6dd/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", size = 142966 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/52/ed/b7f4f07de100bdb95c1756d3a4d17b90c1a3c53715c1a476f8738058e0fa/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", size = 144992 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/96/2c/d49710a6dbcd3776265f4c923bb73ebe83933dfbaa841c5da850fe0fd20b/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", size = 147162 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b4/41/35ff1f9a6bd380303dea55e44c4933b4cc3c4850988927d4082ada230273/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", size = 140972 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fb/43/c6a0b685fe6910d08ba971f62cd9c3e862a85770395ba5d9cad4fede33ab/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", size = 149095 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4c/ff/a9a504662452e2d2878512115638966e75633519ec11f25fca3d2049a94a/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", size = 152668 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6c/71/189996b6d9a4b932564701628af5cee6716733e9165af1d5e1b285c530ed/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", size = 150073 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e4/93/946a86ce20790e11312c87c75ba68d5f6ad2208cfb52b2d6a2c32840d922/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", size = 145732 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cd/e5/131d2fb1b0dddafc37be4f3a2fa79aa4c037368be9423061dccadfd90091/charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", size = 95391 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/27/f2/4f9a69cc7712b9b5ad8fdb87039fd89abba997ad5cbe690d1835d40405b0/charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", size = 102702 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0e/f6/65ecc6878a89bb1c23a086ea335ad4bf21a588990c3f535a227b9eea9108/charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", size = 49767 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "click"
|
name = "click"
|
||||||
version = "8.1.8"
|
version = "8.1.8"
|
||||||
|
@ -83,6 +203,47 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
|
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "coverage"
|
||||||
|
version = "7.6.12"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/0c/d6/2b53ab3ee99f2262e6f0b8369a43f6d66658eab45510331c0b3d5c8c4272/coverage-7.6.12.tar.gz", hash = "sha256:48cfc4641d95d34766ad41d9573cc0f22a48aa88d22657a1fe01dca0dbae4de2", size = 805941 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/76/89/1adf3e634753c0de3dad2f02aac1e73dba58bc5a3a914ac94a25b2ef418f/coverage-7.6.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:488c27b3db0ebee97a830e6b5a3ea930c4a6e2c07f27a5e67e1b3532e76b9ef1", size = 208673 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ce/64/92a4e239d64d798535c5b45baac6b891c205a8a2e7c9cc8590ad386693dc/coverage-7.6.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d1095bbee1851269f79fd8e0c9b5544e4c00c0c24965e66d8cba2eb5bb535fd", size = 208945 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b4/d0/4596a3ef3bca20a94539c9b1e10fd250225d1dec57ea78b0867a1cf9742e/coverage-7.6.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0533adc29adf6a69c1baa88c3d7dbcaadcffa21afbed3ca7a225a440e4744bf9", size = 242484 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1c/ef/6fd0d344695af6718a38d0861408af48a709327335486a7ad7e85936dc6e/coverage-7.6.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53c56358d470fa507a2b6e67a68fd002364d23c83741dbc4c2e0680d80ca227e", size = 239525 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0c/4b/373be2be7dd42f2bcd6964059fd8fa307d265a29d2b9bcf1d044bcc156ed/coverage-7.6.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64cbb1a3027c79ca6310bf101014614f6e6e18c226474606cf725238cf5bc2d4", size = 241545 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a6/7d/0e83cc2673a7790650851ee92f72a343827ecaaea07960587c8f442b5cd3/coverage-7.6.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:79cac3390bfa9836bb795be377395f28410811c9066bc4eefd8015258a7578c6", size = 241179 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ff/8c/566ea92ce2bb7627b0900124e24a99f9244b6c8c92d09ff9f7633eb7c3c8/coverage-7.6.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9b148068e881faa26d878ff63e79650e208e95cf1c22bd3f77c3ca7b1d9821a3", size = 239288 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7d/e4/869a138e50b622f796782d642c15fb5f25a5870c6d0059a663667a201638/coverage-7.6.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8bec2ac5da793c2685ce5319ca9bcf4eee683b8a1679051f8e6ec04c4f2fd7dc", size = 241032 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ae/28/a52ff5d62a9f9e9fe9c4f17759b98632edd3a3489fce70154c7d66054dd3/coverage-7.6.12-cp313-cp313-win32.whl", hash = "sha256:200e10beb6ddd7c3ded322a4186313d5ca9e63e33d8fab4faa67ef46d3460af3", size = 211315 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bc/17/ab849b7429a639f9722fa5628364c28d675c7ff37ebc3268fe9840dda13c/coverage-7.6.12-cp313-cp313-win_amd64.whl", hash = "sha256:2b996819ced9f7dbb812c701485d58f261bef08f9b85304d41219b1496b591ef", size = 212099 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d2/1c/b9965bf23e171d98505eb5eb4fb4d05c44efd256f2e0f19ad1ba8c3f54b0/coverage-7.6.12-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:299cf973a7abff87a30609879c10df0b3bfc33d021e1adabc29138a48888841e", size = 209511 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/57/b3/119c201d3b692d5e17784fee876a9a78e1b3051327de2709392962877ca8/coverage-7.6.12-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4b467a8c56974bf06e543e69ad803c6865249d7a5ccf6980457ed2bc50312703", size = 209729 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/52/4e/a7feb5a56b266304bc59f872ea07b728e14d5a64f1ad3a2cc01a3259c965/coverage-7.6.12-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2458f275944db8129f95d91aee32c828a408481ecde3b30af31d552c2ce284a0", size = 253988 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/65/19/069fec4d6908d0dae98126aa7ad08ce5130a6decc8509da7740d36e8e8d2/coverage-7.6.12-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a9d8be07fb0832636a0f72b80d2a652fe665e80e720301fb22b191c3434d924", size = 249697 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1c/da/5b19f09ba39df7c55f77820736bf17bbe2416bbf5216a3100ac019e15839/coverage-7.6.12-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d47376a4f445e9743f6c83291e60adb1b127607a3618e3185bbc8091f0467b", size = 252033 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1e/89/4c2750df7f80a7872267f7c5fe497c69d45f688f7b3afe1297e52e33f791/coverage-7.6.12-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b95574d06aa9d2bd6e5cc35a5bbe35696342c96760b69dc4287dbd5abd4ad51d", size = 251535 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/3b/6d3ae3c1cc05f1b0460c51e6f6dcf567598cbd7c6121e5ad06643974703c/coverage-7.6.12-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:ecea0c38c9079570163d663c0433a9af4094a60aafdca491c6a3d248c7432827", size = 249192 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6e/8e/c14a79f535ce41af7d436bbad0d3d90c43d9e38ec409b4770c894031422e/coverage-7.6.12-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2251fabcfee0a55a8578a9d29cecfee5f2de02f11530e7d5c5a05859aa85aee9", size = 250627 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cb/79/b7cee656cfb17a7f2c1b9c3cee03dd5d8000ca299ad4038ba64b61a9b044/coverage-7.6.12-cp313-cp313t-win32.whl", hash = "sha256:eb5507795caabd9b2ae3f1adc95f67b1104971c22c624bb354232d65c4fc90b3", size = 212033 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b6/c3/f7aaa3813f1fa9a4228175a7bd368199659d392897e184435a3b66408dd3/coverage-7.6.12-cp313-cp313t-win_amd64.whl", hash = "sha256:f60a297c3987c6c02ffb29effc70eadcbb412fe76947d394a1091a3615948e2f", size = 213240 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fb/b2/f655700e1024dec98b10ebaafd0cedbc25e40e4abe62a3c8e2ceef4f8f0a/coverage-7.6.12-py3-none-any.whl", hash = "sha256:eb8668cfbc279a536c633137deeb9435d2962caec279c3f8cf8b91fff6ff8953", size = 200552 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cssutils"
|
||||||
|
version = "2.11.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "more-itertools" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/33/9f/329d26121fe165be44b1dfff21aa0dc348f04633931f1d20ed6cf448a236/cssutils-2.11.1.tar.gz", hash = "sha256:0563a76513b6af6eebbe788c3bf3d01c920e46b3f90c8416738c5cfc773ff8e2", size = 711657 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a7/ec/bb273b7208c606890dc36540fe667d06ce840a6f62f9fae7e658fcdc90fb/cssutils-2.11.1-py3-none-any.whl", hash = "sha256:a67bfdfdff4f3867fab43698ec4897c1a828eca5973f4073321b3bccaf1199b1", size = 385747 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "decorator"
|
name = "decorator"
|
||||||
version = "5.1.1"
|
version = "5.1.1"
|
||||||
|
@ -92,6 +253,50 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/d5/50/83c593b07763e1161326b3b8c6686f0f4b0f24d5526546bee538c89837d6/decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186", size = 9073 },
|
{ url = "https://files.pythonhosted.org/packages/d5/50/83c593b07763e1161326b3b8c6686f0f4b0f24d5526546bee538c89837d6/decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186", size = 9073 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dict2css"
|
||||||
|
version = "0.3.0.post1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "cssutils" },
|
||||||
|
{ name = "domdf-python-tools" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/24/eb/776eef1f1aa0188c0fc165c3a60b71027539f71f2eedc43ad21b060e9c39/dict2css-0.3.0.post1.tar.gz", hash = "sha256:89c544c21c4ca7472c3fffb9d37d3d926f606329afdb751dc1de67a411b70719", size = 7845 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fe/47/290daabcf91628f4fc0e17c75a1690b354ba067066cd14407712600e609f/dict2css-0.3.0.post1-py3-none-any.whl", hash = "sha256:f006a6b774c3e31869015122ae82c491fd25e7de4a75607a62aa3e798f837e0d", size = 25647 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "distlib"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "docutils"
|
||||||
|
version = "0.21.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "domdf-python-tools"
|
||||||
|
version = "3.10.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "natsort" },
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/36/8b/ab2d8a292bba8fe3135cacc8bfd3576710a14b8f2d0a8cde19130d5c9d21/domdf_python_tools-3.10.0.tar.gz", hash = "sha256:2ae308d2f4f1e9145f5f4ba57f840fbfd1c2983ee26e4824347789649d3ae298", size = 100458 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5b/11/208f72084084d3f6a2ed5ebfdfc846692c3f7ad6dce65e400194924f7eed/domdf_python_tools-3.10.0-py3-none-any.whl", hash = "sha256:5e71c1be71bbcc1f881d690c8984b60e64298ec256903b3147f068bc33090c36", size = 126860 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "executing"
|
name = "executing"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
|
@ -101,6 +306,15 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702 },
|
{ url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "filelock"
|
||||||
|
version = "3.17.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/dc/9c/0b15fb47b464e1b663b1acd1253a062aa5feecb07d4e597daea542ebd2b5/filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e", size = 18027 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/89/ec/00d68c4ddfedfe64159999e5f8a98fb8442729a63e2077eb9dcd89623d27/filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338", size = 16164 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h11"
|
name = "h11"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
|
@ -110,6 +324,19 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 },
|
{ url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "html5lib"
|
||||||
|
version = "1.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "six" },
|
||||||
|
{ name = "webencodings" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ac/b6/b55c3f49042f1df3dcd422b7f224f939892ee94f22abcf503a9b7339eaf2/html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f", size = 272215 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6c/dd/a834df6482147d48e225a49515aabc28974ad5a4ca3215c18a882565b028/html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d", size = 112173 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httpcore"
|
name = "httpcore"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
|
@ -138,6 +365,15 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 },
|
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "identify"
|
||||||
|
version = "2.6.8"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/f9/fa/5eb460539e6f5252a7c5a931b53426e49258cde17e3d50685031c300a8fd/identify-2.6.8.tar.gz", hash = "sha256:61491417ea2c0c5c670484fd8abbb34de34cdae1e5f39a73ee65e48e4bb663fc", size = 99249 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/8c/4bfcab2d8286473b8d83ea742716f4b79290172e75f91142bc1534b05b9a/identify-2.6.8-py2.py3-none-any.whl", hash = "sha256:83657f0f766a3c8d0eaea16d4ef42494b39b34629a4b3192a9d020d349b3e255", size = 99109 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "3.10"
|
version = "3.10"
|
||||||
|
@ -147,13 +383,32 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
|
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "imagesize"
|
||||||
|
version = "1.4.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iniconfig"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipython"
|
name = "ipython"
|
||||||
version = "8.32.0"
|
version = "9.0.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||||
{ name = "decorator" },
|
{ name = "decorator" },
|
||||||
|
{ name = "ipython-pygments-lexers" },
|
||||||
{ name = "jedi" },
|
{ name = "jedi" },
|
||||||
{ name = "matplotlib-inline" },
|
{ name = "matplotlib-inline" },
|
||||||
{ name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
|
{ name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
|
||||||
|
@ -162,9 +417,21 @@ dependencies = [
|
||||||
{ name = "stack-data" },
|
{ name = "stack-data" },
|
||||||
{ name = "traitlets" },
|
{ name = "traitlets" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/36/80/4d2a072e0db7d250f134bc11676517299264ebe16d62a8619d49a78ced73/ipython-8.32.0.tar.gz", hash = "sha256:be2c91895b0b9ea7ba49d33b23e2040c352b33eb6a519cca7ce6e0c743444251", size = 5507441 }
|
sdist = { url = "https://files.pythonhosted.org/packages/de/39/264894738a202ddaf6abae39b3f84671ddee23fd292dbb3e10039e70300c/ipython-9.0.0.tar.gz", hash = "sha256:9368d65b3d4a471e9a698fed3ea486bbf6737e45111e915279c971b77f974397", size = 4364165 }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/e7/e1/f4474a7ecdb7745a820f6f6039dc43c66add40f1bcc66485607d93571af6/ipython-8.32.0-py3-none-any.whl", hash = "sha256:cae85b0c61eff1fc48b0a8002de5958b6528fa9c8defb1894da63f42613708aa", size = 825524 },
|
{ url = "https://files.pythonhosted.org/packages/85/a1/894e4c0b6ac994045c6edeb2b6fdf69c59f20fcd2e348a42f4e40889181c/ipython-9.0.0-py3-none-any.whl", hash = "sha256:2cce23069b830a54a5b9d3d66ccd6433047c1503a7b9a3b34593c0b5c2c08477", size = 592040 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ipython-pygments-lexers"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "pygments" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074 },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -179,6 +446,18 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278 },
|
{ url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jinja2"
|
||||||
|
version = "3.1.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "markupsafe" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/af/92/b3130cbbf5591acf9ade8708c365f3238046ac7cb8ccba6e81abccb0ccff/jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb", size = 244674 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bd/0f/2ba5fbcd631e3e88689309dbe978c5769e883e4b84ebfe7da30b43275c5a/jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb", size = 134596 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "markdown-it-py"
|
name = "markdown-it-py"
|
||||||
version = "3.0.0"
|
version = "3.0.0"
|
||||||
|
@ -191,6 +470,34 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 },
|
{ url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "markupsafe"
|
||||||
|
version = "3.0.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matplotlib-inline"
|
name = "matplotlib-inline"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
|
@ -212,6 +519,34 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 },
|
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "more-itertools"
|
||||||
|
version = "10.6.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/88/3b/7fa1fe835e2e93fd6d7b52b2f95ae810cf5ba133e1845f726f5a992d62c2/more-itertools-10.6.0.tar.gz", hash = "sha256:2cd7fad1009c31cc9fb6a035108509e6547547a7a738374f10bd49a09eb3ee3b", size = 125009 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/23/62/0fe302c6d1be1c777cab0616e6302478251dfbf9055ad426f5d0def75c89/more_itertools-10.6.0-py3-none-any.whl", hash = "sha256:6eb054cb4b6db1473f6e15fcc676a08e4732548acd47c708f0e179c2c7c01e89", size = 63038 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "msgpack"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/cb/d0/7555686ae7ff5731205df1012ede15dd9d927f6227ea151e901c7406af4f/msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e", size = 167260 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c8/b0/380f5f639543a4ac413e969109978feb1f3c66e931068f91ab6ab0f8be00/msgpack-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf", size = 151142 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c8/ee/be57e9702400a6cb2606883d55b05784fada898dfc7fd12608ab1fdb054e/msgpack-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330", size = 84523 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7e/3a/2919f63acca3c119565449681ad08a2f84b2171ddfcff1dba6959db2cceb/msgpack-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734", size = 81556 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7c/43/a11113d9e5c1498c145a8925768ea2d5fce7cbab15c99cda655aa09947ed/msgpack-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e", size = 392105 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2d/7b/2c1d74ca6c94f70a1add74a8393a0138172207dc5de6fc6269483519d048/msgpack-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca", size = 399979 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/82/8c/cf64ae518c7b8efc763ca1f1348a96f0e37150061e777a8ea5430b413a74/msgpack-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915", size = 383816 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/69/86/a847ef7a0f5ef3fa94ae20f52a4cacf596a4e4a010197fbcc27744eb9a83/msgpack-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d", size = 380973 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/aa/90/c74cf6e1126faa93185d3b830ee97246ecc4fe12cf9d2d31318ee4246994/msgpack-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434", size = 387435 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7a/40/631c238f1f338eb09f4acb0f34ab5862c4e9d7eda11c1b685471a4c5ea37/msgpack-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c", size = 399082 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e9/1b/fa8a952be252a1555ed39f97c06778e3aeb9123aa4cccc0fd2acd0b4e315/msgpack-1.1.0-cp313-cp313-win32.whl", hash = "sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc", size = 69037 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b6/bc/8bd826dd03e022153bfa1766dcdec4976d6c818865ed54223d71f07862b3/msgpack-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f", size = 75140 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mypy-extensions"
|
name = "mypy-extensions"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -221,6 +556,24 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 },
|
{ url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "natsort"
|
||||||
|
version = "8.4.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/e2/a9/a0c57aee75f77794adaf35322f8b6404cbd0f89ad45c87197a937764b7d0/natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581", size = 76575 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ef/82/7a9d0550484a62c6da82858ee9419f3dd1ccc9aa1c26a1e43da3ecd20b0d/natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c", size = 38268 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nodeenv"
|
||||||
|
version = "1.9.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "packaging"
|
name = "packaging"
|
||||||
version = "24.2"
|
version = "24.2"
|
||||||
|
@ -269,6 +622,31 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 },
|
{ url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pluggy"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pre-commit"
|
||||||
|
version = "4.1.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "cfgv" },
|
||||||
|
{ name = "identify" },
|
||||||
|
{ name = "nodeenv" },
|
||||||
|
{ name = "pyyaml" },
|
||||||
|
{ name = "virtualenv" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/2a/13/b62d075317d8686071eb843f0bb1f195eb332f48869d3c31a4c6f1e063ac/pre_commit-4.1.0.tar.gz", hash = "sha256:ae3f018575a588e30dfddfab9a05448bfbd6b73d78709617b5a2b853549716d4", size = 193330 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/43/b3/df14c580d82b9627d173ceea305ba898dca135feb360b6d84019d0803d3b/pre_commit-4.1.0-py2.py3-none-any.whl", hash = "sha256:d29e7cb346295bcc1cc75fc3e92e343495e3ea0196c9ec6ba53f49f10ab6ae7b", size = 220560 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prompt-toolkit"
|
name = "prompt-toolkit"
|
||||||
version = "3.0.50"
|
version = "3.0.50"
|
||||||
|
@ -341,7 +719,7 @@ wheels = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyfall"
|
name = "pyfall"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = { virtual = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "httpx" },
|
{ name = "httpx" },
|
||||||
{ name = "pydantic" },
|
{ name = "pydantic" },
|
||||||
|
@ -351,8 +729,15 @@ dependencies = [
|
||||||
dev = [
|
dev = [
|
||||||
{ name = "black" },
|
{ name = "black" },
|
||||||
{ name = "ipython" },
|
{ name = "ipython" },
|
||||||
|
{ name = "pre-commit" },
|
||||||
|
{ name = "pytest" },
|
||||||
|
{ name = "pytest-asyncio" },
|
||||||
|
{ name = "pytest-cov" },
|
||||||
{ name = "rich" },
|
{ name = "rich" },
|
||||||
{ name = "ruff" },
|
{ name = "ruff" },
|
||||||
|
{ name = "sphinx" },
|
||||||
|
{ name = "sphinx-rtd-theme" },
|
||||||
|
{ name = "sphinx-toolbox" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
|
@ -364,9 +749,16 @@ requires-dist = [
|
||||||
[package.metadata.requires-dev]
|
[package.metadata.requires-dev]
|
||||||
dev = [
|
dev = [
|
||||||
{ name = "black", specifier = ">=25.1.0" },
|
{ name = "black", specifier = ">=25.1.0" },
|
||||||
{ name = "ipython", specifier = ">=8.32.0" },
|
{ name = "ipython", specifier = ">=9.0.0" },
|
||||||
|
{ name = "pre-commit", specifier = ">=4.0.1" },
|
||||||
|
{ name = "pytest", specifier = ">=8.3.3" },
|
||||||
|
{ name = "pytest-asyncio", specifier = ">=0.25.3" },
|
||||||
|
{ name = "pytest-cov", specifier = ">=6.0.0" },
|
||||||
{ name = "rich", specifier = ">=13.9.4" },
|
{ name = "rich", specifier = ">=13.9.4" },
|
||||||
{ name = "ruff", specifier = ">=0.9.7" },
|
{ name = "ruff", specifier = ">=0.9.9" },
|
||||||
|
{ name = "sphinx", specifier = ">=8.2.1" },
|
||||||
|
{ name = "sphinx-rtd-theme", specifier = ">=3.0.2" },
|
||||||
|
{ name = "sphinx-toolbox", specifier = ">=3.9.0" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -378,6 +770,78 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 },
|
{ url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytest"
|
||||||
|
version = "8.3.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||||
|
{ name = "iniconfig" },
|
||||||
|
{ name = "packaging" },
|
||||||
|
{ name = "pluggy" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytest-asyncio"
|
||||||
|
version = "0.25.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "pytest" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/f2/a8/ecbc8ede70921dd2f544ab1cadd3ff3bf842af27f87bbdea774c7baa1d38/pytest_asyncio-0.25.3.tar.gz", hash = "sha256:fc1da2cf9f125ada7e710b4ddad05518d4cee187ae9412e9ac9271003497f07a", size = 54239 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/67/17/3493c5624e48fd97156ebaec380dcaafee9506d7e2c46218ceebbb57d7de/pytest_asyncio-0.25.3-py3-none-any.whl", hash = "sha256:9e89518e0f9bd08928f97a3482fdc4e244df17529460bc038291ccaf8f85c7c3", size = 19467 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytest-cov"
|
||||||
|
version = "6.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "coverage" },
|
||||||
|
{ name = "pytest" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyyaml"
|
||||||
|
version = "6.0.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "requests"
|
||||||
|
version = "2.32.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "certifi" },
|
||||||
|
{ name = "charset-normalizer" },
|
||||||
|
{ name = "idna" },
|
||||||
|
{ name = "urllib3" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rich"
|
name = "rich"
|
||||||
version = "13.9.4"
|
version = "13.9.4"
|
||||||
|
@ -392,28 +856,55 @@ wheels = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff"
|
name = "roman-numerals-py"
|
||||||
version = "0.9.7"
|
version = "3.1.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/39/8b/a86c300359861b186f18359adf4437ac8e4c52e42daa9eedc731ef9d5b53/ruff-0.9.7.tar.gz", hash = "sha256:643757633417907510157b206e490c3aa11cab0c087c912f60e07fbafa87a4c6", size = 3669813 }
|
sdist = { url = "https://files.pythonhosted.org/packages/30/76/48fd56d17c5bdbdf65609abbc67288728a98ed4c02919428d4f52d23b24b/roman_numerals_py-3.1.0.tar.gz", hash = "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d", size = 9017 }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/b1/f3/3a1d22973291226df4b4e2ff70196b926b6f910c488479adb0eeb42a0d7f/ruff-0.9.7-py3-none-linux_armv6l.whl", hash = "sha256:99d50def47305fe6f233eb8dabfd60047578ca87c9dcb235c9723ab1175180f4", size = 11774588 },
|
{ url = "https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", size = 7742 },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8e/c9/b881f4157b9b884f2994fd08ee92ae3663fb24e34b0372ac3af999aa7fc6/ruff-0.9.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d59105ae9c44152c3d40a9c40d6331a7acd1cdf5ef404fbe31178a77b174ea66", size = 11746848 },
|
]
|
||||||
{ url = "https://files.pythonhosted.org/packages/14/89/2f546c133f73886ed50a3d449e6bf4af27d92d2f960a43a93d89353f0945/ruff-0.9.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f313b5800483770bd540cddac7c90fc46f895f427b7820f18fe1822697f1fec9", size = 11177525 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d7/93/6b98f2c12bf28ab9def59c50c9c49508519c5b5cfecca6de871cf01237f6/ruff-0.9.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:042ae32b41343888f59c0a4148f103208bf6b21c90118d51dc93a68366f4e903", size = 11996580 },
|
[[package]]
|
||||||
{ url = "https://files.pythonhosted.org/packages/8e/3f/b3fcaf4f6d875e679ac2b71a72f6691a8128ea3cb7be07cbb249f477c061/ruff-0.9.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:87862589373b33cc484b10831004e5e5ec47dc10d2b41ba770e837d4f429d721", size = 11525674 },
|
name = "ruamel-yaml"
|
||||||
{ url = "https://files.pythonhosted.org/packages/f0/48/33fbf18defb74d624535d5d22adcb09a64c9bbabfa755bc666189a6b2210/ruff-0.9.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a17e1e01bee0926d351a1ee9bc15c445beae888f90069a6192a07a84af544b6b", size = 12739151 },
|
version = "0.18.10"
|
||||||
{ url = "https://files.pythonhosted.org/packages/63/b5/7e161080c5e19fa69495cbab7c00975ef8a90f3679caa6164921d7f52f4a/ruff-0.9.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7c1f880ac5b2cbebd58b8ebde57069a374865c73f3bf41f05fe7a179c1c8ef22", size = 13416128 },
|
source = { registry = "https://pypi.org/simple" }
|
||||||
{ url = "https://files.pythonhosted.org/packages/4e/c8/b5e7d61fb1c1b26f271ac301ff6d9de5e4d9a9a63f67d732fa8f200f0c88/ruff-0.9.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e63fc20143c291cab2841dbb8260e96bafbe1ba13fd3d60d28be2c71e312da49", size = 12870858 },
|
sdist = { url = "https://files.pythonhosted.org/packages/ea/46/f44d8be06b85bc7c4d8c95d658be2b68f27711f279bf9dd0612a5e4794f5/ruamel.yaml-0.18.10.tar.gz", hash = "sha256:20c86ab29ac2153f80a428e1254a8adf686d3383df04490514ca3b79a362db58", size = 143447 }
|
||||||
{ url = "https://files.pythonhosted.org/packages/da/cb/2a1a8e4e291a54d28259f8fc6a674cd5b8833e93852c7ef5de436d6ed729/ruff-0.9.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91ff963baed3e9a6a4eba2a02f4ca8eaa6eba1cc0521aec0987da8d62f53cbef", size = 14786046 },
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/ca/6c/c8f8a313be1943f333f376d79724260da5701426c0905762e3ddb389e3f4/ruff-0.9.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88362e3227c82f63eaebf0b2eff5b88990280fb1ecf7105523883ba8c3aaf6fb", size = 12550834 },
|
{ url = "https://files.pythonhosted.org/packages/c2/36/dfc1ebc0081e6d39924a2cc53654497f967a084a436bb64402dfce4254d9/ruamel.yaml-0.18.10-py3-none-any.whl", hash = "sha256:30f22513ab2301b3d2b577adc121c6471f28734d3d9728581245f1e76468b4f1", size = 117729 },
|
||||||
{ url = "https://files.pythonhosted.org/packages/9d/ad/f70cf5e8e7c52a25e166bdc84c082163c9c6f82a073f654c321b4dff9660/ruff-0.9.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0372c5a90349f00212270421fe91874b866fd3626eb3b397ede06cd385f6f7e0", size = 11961307 },
|
]
|
||||||
{ url = "https://files.pythonhosted.org/packages/52/d5/4f303ea94a5f4f454daf4d02671b1fbfe2a318b5fcd009f957466f936c50/ruff-0.9.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d76b8ab60e99e6424cd9d3d923274a1324aefce04f8ea537136b8398bbae0a62", size = 11612039 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/eb/c8/bd12a23a75603c704ce86723be0648ba3d4ecc2af07eecd2e9fa112f7e19/ruff-0.9.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0c439bdfc8983e1336577f00e09a4e7a78944fe01e4ea7fe616d00c3ec69a3d0", size = 12168177 },
|
[[package]]
|
||||||
{ url = "https://files.pythonhosted.org/packages/cc/57/d648d4f73400fef047d62d464d1a14591f2e6b3d4a15e93e23a53c20705d/ruff-0.9.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:115d1f15e8fdd445a7b4dc9a30abae22de3f6bcabeb503964904471691ef7606", size = 12610122 },
|
name = "ruff"
|
||||||
{ url = "https://files.pythonhosted.org/packages/49/79/acbc1edd03ac0e2a04ae2593555dbc9990b34090a9729a0c4c0cf20fb595/ruff-0.9.7-py3-none-win32.whl", hash = "sha256:e9ece95b7de5923cbf38893f066ed2872be2f2f477ba94f826c8defdd6ec6b7d", size = 9988751 },
|
version = "0.9.9"
|
||||||
{ url = "https://files.pythonhosted.org/packages/6d/95/67153a838c6b6ba7a2401241fd8a00cd8c627a8e4a0491b8d853dedeffe0/ruff-0.9.7-py3-none-win_amd64.whl", hash = "sha256:3770fe52b9d691a15f0b87ada29c45324b2ace8f01200fb0c14845e499eb0c2c", size = 11002987 },
|
source = { registry = "https://pypi.org/simple" }
|
||||||
{ url = "https://files.pythonhosted.org/packages/63/6a/aca01554949f3a401991dc32fe22837baeaccb8a0d868256cbb26a029778/ruff-0.9.7-py3-none-win_arm64.whl", hash = "sha256:b075a700b2533feb7a01130ff656a4ec0d5f340bb540ad98759b8401c32c2037", size = 10177763 },
|
sdist = { url = "https://files.pythonhosted.org/packages/6f/c3/418441a8170e8d53d05c0b9dad69760dbc7b8a12c10dbe6db1e1205d2377/ruff-0.9.9.tar.gz", hash = "sha256:0062ed13f22173e85f8f7056f9a24016e692efeea8704d1a5e8011b8aa850933", size = 3717448 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bc/c3/2c4afa9ba467555d074b146d9aed0633a56ccdb900839fb008295d037b89/ruff-0.9.9-py3-none-linux_armv6l.whl", hash = "sha256:628abb5ea10345e53dff55b167595a159d3e174d6720bf19761f5e467e68d367", size = 10027252 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/33/d1/439e58487cf9eac26378332e25e7d5ade4b800ce1eec7dc2cfc9b0d7ca96/ruff-0.9.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b6cd1428e834b35d7493354723543b28cc11dc14d1ce19b685f6e68e07c05ec7", size = 10840721 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/50/44/fead822c38281ba0122f1b76b460488a175a9bd48b130650a6fb6dbcbcf9/ruff-0.9.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5ee162652869120ad260670706f3cd36cd3f32b0c651f02b6da142652c54941d", size = 10161439 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/11/ae/d404a2ab8e61ddf6342e09cc6b7f7846cce6b243e45c2007dbe0ca928a5d/ruff-0.9.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3aa0f6b75082c9be1ec5a1db78c6d4b02e2375c3068438241dc19c7c306cc61a", size = 10336264 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6a/4e/7c268aa7d84cd709fb6f046b8972313142cffb40dfff1d2515c5e6288d54/ruff-0.9.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:584cc66e89fb5f80f84b05133dd677a17cdd86901d6479712c96597a3f28e7fe", size = 9908774 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cc/26/c618a878367ef1b76270fd027ca93692657d3f6122b84ba48911ef5f2edc/ruff-0.9.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abf3369325761a35aba75cd5c55ba1b5eb17d772f12ab168fbfac54be85cf18c", size = 11428127 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d7/9a/c5588a93d9bfed29f565baf193fe802fa676a0c837938137ea6cf0576d8c/ruff-0.9.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3403a53a32a90ce929aa2f758542aca9234befa133e29f4933dcef28a24317be", size = 12133187 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/ff/e7980a7704a60905ed7e156a8d73f604c846d9bd87deda9cabfa6cba073a/ruff-0.9.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:18454e7fa4e4d72cffe28a37cf6a73cb2594f81ec9f4eca31a0aaa9ccdfb1590", size = 11602937 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/24/78/3690444ad9e3cab5c11abe56554c35f005b51d1d118b429765249095269f/ruff-0.9.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fadfe2c88724c9617339f62319ed40dcdadadf2888d5afb88bf3adee7b35bfb", size = 13771698 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6e/bf/e477c2faf86abe3988e0b5fd22a7f3520e820b2ee335131aca2e16120038/ruff-0.9.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6df104d08c442a1aabcfd254279b8cc1e2cbf41a605aa3e26610ba1ec4acf0b0", size = 11249026 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f7/82/cdaffd59e5a8cb5b14c408c73d7a555a577cf6645faaf83e52fe99521715/ruff-0.9.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d7c62939daf5b2a15af48abbd23bea1efdd38c312d6e7c4cedf5a24e03207e17", size = 10220432 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fe/a4/2507d0026225efa5d4412b6e294dfe54725a78652a5c7e29e6bd0fc492f3/ruff-0.9.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9494ba82a37a4b81b6a798076e4a3251c13243fc37967e998efe4cce58c8a8d1", size = 9874602 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d5/be/f3aab1813846b476c4bcffe052d232244979c3cd99d751c17afb530ca8e4/ruff-0.9.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4efd7a96ed6d36ef011ae798bf794c5501a514be369296c672dab7921087fa57", size = 10851212 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8b/45/8e5fd559bea0d2f57c4e12bf197a2fade2fac465aa518284f157dfbca92b/ruff-0.9.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ab90a7944c5a1296f3ecb08d1cbf8c2da34c7e68114b1271a431a3ad30cb660e", size = 11327490 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/42/55/e6c90f13880aeef327746052907e7e930681f26a164fe130ddac28b08269/ruff-0.9.9-py3-none-win32.whl", hash = "sha256:6b4c376d929c25ecd6d87e182a230fa4377b8e5125a4ff52d506ee8c087153c1", size = 10227912 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/35/b2/da925693cb82a1208aa34966c0f36cb222baca94e729dd22a587bc22d0f3/ruff-0.9.9-py3-none-win_amd64.whl", hash = "sha256:837982ea24091d4c1700ddb2f63b7070e5baec508e43b01de013dc7eff974ff1", size = 11355632 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/31/d8/de873d1c1b020d668d8ec9855d390764cb90cf8f6486c0983da52be8b7b7/ruff-0.9.9-py3-none-win_arm64.whl", hash = "sha256:3ac78f127517209fe6d96ab00f3ba97cafe38718b23b1db3e96d8b2d39e37ddf", size = 10435860 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "six"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -425,6 +916,217 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
|
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snowballstemmer"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/44/7b/af302bebf22c749c56c9c3e8ae13190b5b5db37a33d9068652e8f73b7089/snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", size = 86699 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "soupsieve"
|
||||||
|
version = "2.6"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d7/ce/fbaeed4f9fb8b2daa961f90591662df6a86c1abf25c548329a86920aedfb/soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb", size = 101569 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9", size = 36186 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinx"
|
||||||
|
version = "8.2.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "alabaster" },
|
||||||
|
{ name = "babel" },
|
||||||
|
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||||
|
{ name = "docutils" },
|
||||||
|
{ name = "imagesize" },
|
||||||
|
{ name = "jinja2" },
|
||||||
|
{ name = "packaging" },
|
||||||
|
{ name = "pygments" },
|
||||||
|
{ name = "requests" },
|
||||||
|
{ name = "roman-numerals-py" },
|
||||||
|
{ name = "snowballstemmer" },
|
||||||
|
{ name = "sphinxcontrib-applehelp" },
|
||||||
|
{ name = "sphinxcontrib-devhelp" },
|
||||||
|
{ name = "sphinxcontrib-htmlhelp" },
|
||||||
|
{ name = "sphinxcontrib-jsmath" },
|
||||||
|
{ name = "sphinxcontrib-qthelp" },
|
||||||
|
{ name = "sphinxcontrib-serializinghtml" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/99/4b/95bdb36eaee30698f2d244d52e1b9e58642af56525d4b02fcd0f7312c27c/sphinx-8.2.1.tar.gz", hash = "sha256:e4b932951b9c18b039f73b72e4e63afe967d90408700ec222b981ac24647c01e", size = 8321376 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cf/aa/282768cff0039b227a923cb65686539bb606e448c594d4fdee4d2c7765a1/sphinx-8.2.1-py3-none-any.whl", hash = "sha256:b5d2bb3cdf6207fcacde9f92085d2b97667b05b9c346eaec426ca4be8af505e9", size = 3589415 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinx-autodoc-typehints"
|
||||||
|
version = "3.1.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "sphinx" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/cb/cc/d38e7260b1bd3af0c84ad8285dfd78236584b74544510584e07963e000ec/sphinx_autodoc_typehints-3.1.0.tar.gz", hash = "sha256:a6b7b0b6df0a380783ce5b29150c2d30352746f027a3e294d37183995d3f23ed", size = 36528 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/14/2f/bc5bed0677ae00b9ca7919968ea675e2f696b6b20f1648262f26a7a6c6b4/sphinx_autodoc_typehints-3.1.0-py3-none-any.whl", hash = "sha256:67bdee7e27ba943976ce92ebc5647a976a7a08f9f689a826c54617b96a423913", size = 20404 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinx-jinja2-compat"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "jinja2" },
|
||||||
|
{ name = "markupsafe" },
|
||||||
|
{ name = "standard-imghdr" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/26/df/27282da6f8c549f765beca9de1a5fc56f9651ed87711a5cac1e914137753/sphinx_jinja2_compat-0.3.0.tar.gz", hash = "sha256:f3c1590b275f42e7a654e081db5e3e5fb97f515608422bde94015ddf795dfe7c", size = 4998 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6f/42/2fd09d672eaaa937d6893d8b747d07943f97a6e5e30653aee6ebd339b704/sphinx_jinja2_compat-0.3.0-py3-none-any.whl", hash = "sha256:b1e4006d8e1ea31013fa9946d1b075b0c8d2a42c6e3425e63542c1e9f8be9084", size = 7883 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinx-prompt"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "certifi" },
|
||||||
|
{ name = "docutils" },
|
||||||
|
{ name = "idna" },
|
||||||
|
{ name = "pygments" },
|
||||||
|
{ name = "sphinx" },
|
||||||
|
{ name = "urllib3" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/34/fe/ac4e24f35b5148b31ac717ae7dcc7a2f7ec56eb729e22c7252ed8ad2d9a5/sphinx_prompt-1.9.0.tar.gz", hash = "sha256:471b3c6d466dce780a9b167d9541865fd4e9a80ed46e31b06a52a0529ae995a1", size = 5340 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/76/98/e90ca466e0ede452d3e5a8d92b8fb68db6de269856e019ed9cab69440522/sphinx_prompt-1.9.0-py3-none-any.whl", hash = "sha256:fd731446c03f043d1ff6df9f22414495b23067c67011cc21658ea8d36b3575fc", size = 7311 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinx-rtd-theme"
|
||||||
|
version = "3.0.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "docutils" },
|
||||||
|
{ name = "sphinx" },
|
||||||
|
{ name = "sphinxcontrib-jquery" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/91/44/c97faec644d29a5ceddd3020ae2edffa69e7d00054a8c7a6021e82f20335/sphinx_rtd_theme-3.0.2.tar.gz", hash = "sha256:b7457bc25dda723b20b086a670b9953c859eab60a2a03ee8eb2bb23e176e5f85", size = 7620463 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/85/77/46e3bac77b82b4df5bb5b61f2de98637724f246b4966cfc34bc5895d852a/sphinx_rtd_theme-3.0.2-py2.py3-none-any.whl", hash = "sha256:422ccc750c3a3a311de4ae327e82affdaf59eb695ba4936538552f3b00f4ee13", size = 7655561 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinx-tabs"
|
||||||
|
version = "3.4.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "docutils" },
|
||||||
|
{ name = "pygments" },
|
||||||
|
{ name = "sphinx" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/27/32/ab475e252dc2b704e82a91141fa404cdd8901a5cf34958fd22afacebfccd/sphinx-tabs-3.4.5.tar.gz", hash = "sha256:ba9d0c1e3e37aaadd4b5678449eb08176770e0fc227e769b6ce747df3ceea531", size = 16070 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/20/9f/4ac7dbb9f23a2ff5a10903a4f9e9f43e0ff051f63a313e989c962526e305/sphinx_tabs-3.4.5-py3-none-any.whl", hash = "sha256:92cc9473e2ecf1828ca3f6617d0efc0aa8acb06b08c56ba29d1413f2f0f6cf09", size = 9904 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinx-toolbox"
|
||||||
|
version = "3.9.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "apeye" },
|
||||||
|
{ name = "autodocsumm" },
|
||||||
|
{ name = "beautifulsoup4" },
|
||||||
|
{ name = "cachecontrol", extra = ["filecache"] },
|
||||||
|
{ name = "dict2css" },
|
||||||
|
{ name = "docutils" },
|
||||||
|
{ name = "domdf-python-tools" },
|
||||||
|
{ name = "filelock" },
|
||||||
|
{ name = "html5lib" },
|
||||||
|
{ name = "ruamel-yaml" },
|
||||||
|
{ name = "sphinx" },
|
||||||
|
{ name = "sphinx-autodoc-typehints" },
|
||||||
|
{ name = "sphinx-jinja2-compat" },
|
||||||
|
{ name = "sphinx-prompt" },
|
||||||
|
{ name = "sphinx-tabs" },
|
||||||
|
{ name = "tabulate" },
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/df/32/e10c272614a1f4d84b680007bd45f9b77db3262ee6c3c61a0e27932a55b7/sphinx_toolbox-3.9.0.tar.gz", hash = "sha256:9ee0603b090762d6eed4d0ec9fa91445e3ef95d40a584af125308541c1bf7b8d", size = 114497 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5d/7e/9811c8cf0df10c2b6c9c72667837d731dd4f0dc0d0e68980938c8eb6f7f8/sphinx_toolbox-3.9.0-py3-none-any.whl", hash = "sha256:49024961c7791ad6e9dd39c611f89b5162550afa26ccad087be38388c3dd3c1e", size = 195429 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinxcontrib-applehelp"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinxcontrib-devhelp"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinxcontrib-htmlhelp"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinxcontrib-jquery"
|
||||||
|
version = "4.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "sphinx" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/de/f3/aa67467e051df70a6330fe7770894b3e4f09436dea6881ae0b4f3d87cad8/sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a", size = 122331 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/76/85/749bd22d1a68db7291c89e2ebca53f4306c3f205853cf31e9de279034c3c/sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae", size = 121104 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinxcontrib-jsmath"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinxcontrib-qthelp"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sphinxcontrib-serializinghtml"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stack-data"
|
name = "stack-data"
|
||||||
version = "0.6.3"
|
version = "0.6.3"
|
||||||
|
@ -439,6 +1141,24 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521 },
|
{ url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "standard-imghdr"
|
||||||
|
version = "3.10.14"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/09/d2/2eb5521072c9598886035c65c023f39f7384bcb73eed70794f469e34efac/standard_imghdr-3.10.14.tar.gz", hash = "sha256:2598fe2e7c540dbda34b233295e10957ab8dc8ac6f3bd9eaa8d38be167232e52", size = 5474 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fb/d0/9852f70eb01f814843530c053542b72d30e9fbf74da7abb0107e71938389/standard_imghdr-3.10.14-py3-none-any.whl", hash = "sha256:cdf6883163349624dee9a81d2853a20260337c4cd41c04e99c082e01833a08e2", size = 5598 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tabulate"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "traitlets"
|
name = "traitlets"
|
||||||
version = "5.14.3"
|
version = "5.14.3"
|
||||||
|
@ -457,6 +1177,29 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
|
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "urllib3"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "virtualenv"
|
||||||
|
version = "20.29.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "distlib" },
|
||||||
|
{ name = "filelock" },
|
||||||
|
{ name = "platformdirs" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/f1/88/dacc875dd54a8acadb4bcbfd4e3e86df8be75527116c91d8f9784f5e9cab/virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728", size = 4320272 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/93/fa/849483d56773ae29740ae70043ad88e068f98a6401aa819b5d6bee604683/virtualenv-20.29.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a", size = 4301478 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wcwidth"
|
name = "wcwidth"
|
||||||
version = "0.2.13"
|
version = "0.2.13"
|
||||||
|
@ -465,3 +1208,12 @@ sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166 },
|
{ url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webencodings"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774 },
|
||||||
|
]
|
||||||
|
|
Loading…
Add table
Reference in a new issue