Compare commits
18 Commits
8-backport
...
b7e8383abb
Author | SHA1 | Date | |
---|---|---|---|
b7e8383abb | |||
58b113d934 | |||
8441d90deb
|
|||
f81bf8c4df | |||
3064d0231c | |||
5c73d55d91
|
|||
9e70fc25d4
|
|||
63ee619aef
|
|||
06abde6f6f
|
|||
99e0887505
|
|||
4bc78716ee | |||
a27f88a62b | |||
2d94c8b561 | |||
b4b2b2ec5d | |||
ec8e3e491e | |||
2245698405 | |||
9ee3ec2018 | |||
356da4d8ec |
26
README.md
26
README.md
@@ -5,15 +5,27 @@ Nixpkgs PR status checker.
|
|||||||
## Example
|
## Example
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ nixprstatus 345501
|
$ nixprstatus pr 345501
|
||||||
|
ktailctl: 0.18.0 -> 0.18.1
|
||||||
|
|
||||||
|
✅ merged
|
||||||
✅ master
|
✅ master
|
||||||
❌ nixos-unstable-small
|
✅ nixos-unstable-small
|
||||||
❌ nixos-unstable
|
✅ nixos-unstable
|
||||||
❌ nixos-24.05
|
❌ nixos-24.05
|
||||||
|
|
||||||
|
$ nixprstatus --help
|
||||||
|
Usage: python -m nixprstatus [OPTIONS] COMMAND [ARGS]...
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--install-completion Install completion for the current shell.
|
||||||
|
--show-completion Show completion for the current shell, to copy it or
|
||||||
|
customize the installation.
|
||||||
|
--help Show this message and exit.
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
pr Get merge status of pull request.
|
||||||
|
since Return the count of commits that has happened between the...
|
||||||
|
watchlist Manage watchlist.
|
||||||
```
|
```
|
||||||
|
|
||||||
## TODO
|
|
||||||
|
|
||||||
* Support backported commits
|
|
||||||
* JSON output
|
|
||||||
|
30
flake.lock
generated
30
flake.lock
generated
@@ -5,11 +5,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1726560853,
|
"lastModified": 1731533236,
|
||||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -44,11 +44,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1720066371,
|
"lastModified": 1729742964,
|
||||||
"narHash": "sha256-uPlLYH2S0ACj0IcgaK9Lsf4spmJoGejR9DotXiXSBZQ=",
|
"narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nix-github-actions",
|
"repo": "nix-github-actions",
|
||||||
"rev": "622f829f5fe69310a866c8a6cd07e747c44ef820",
|
"rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -59,11 +59,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1727634051,
|
"lastModified": 1732521221,
|
||||||
"narHash": "sha256-S5kVU7U82LfpEukbn/ihcyNt2+EvG7Z5unsKW9H/yFA=",
|
"narHash": "sha256-2ThgXBUXAE1oFsVATK1ZX9IjPcS4nKFOAjhPNKuiMn0=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "06cf0e1da4208d3766d898b7fdab6513366d45b9",
|
"rev": "4633a7c72337ea8fd23a4f2ba3972865e3ec685d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -84,11 +84,11 @@
|
|||||||
"treefmt-nix": "treefmt-nix"
|
"treefmt-nix": "treefmt-nix"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1727711975,
|
"lastModified": 1731205797,
|
||||||
"narHash": "sha256-zkkL5gw+TNXhVO2zpeH70TKh2dSzUbkBbO6gKHO37s0=",
|
"narHash": "sha256-F7N1mxH1VrkVNHR3JGNMRvp9+98KYO4b832KS8Gl2xI=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "poetry2nix",
|
"repo": "poetry2nix",
|
||||||
"rev": "ef877b8e159b23f36ebc39155021657bed744a68",
|
"rev": "f554d27c1544d9c56e5f1f8e2b8aff399803674e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -156,11 +156,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1727431250,
|
"lastModified": 1730120726,
|
||||||
"narHash": "sha256-uGRlRT47ecicF9iLD1G3g43jn2e+b5KaMptb59LHnvM=",
|
"narHash": "sha256-LqHYIxMrl/1p3/kvm2ir925tZ8DkI0KA10djk8wecSk=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "treefmt-nix",
|
"repo": "treefmt-nix",
|
||||||
"rev": "879b29ae9a0378904fbbefe0dadaed43c8905754",
|
"rev": "9ef337e492a5555d8e17a51c911ff1f02635be15",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@@ -32,7 +32,12 @@
|
|||||||
{
|
{
|
||||||
packages = {
|
packages = {
|
||||||
nixprstatus = mkPoetryApplication {
|
nixprstatus = mkPoetryApplication {
|
||||||
projectDir = ./.;
|
projectDir = pkgs.lib.sourceFilesBySuffices ./. [
|
||||||
|
"pyproject.toml"
|
||||||
|
"poetry.lock"
|
||||||
|
"README.md"
|
||||||
|
".py"
|
||||||
|
];
|
||||||
python = pkgs.python312;
|
python = pkgs.python312;
|
||||||
nativeBuildInputs = [ pkgs.installShellFiles ];
|
nativeBuildInputs = [ pkgs.installShellFiles ];
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
@@ -49,6 +54,7 @@
|
|||||||
inputsFrom = [ self.packages.${system}.nixprstatus ];
|
inputsFrom = [ self.packages.${system}.nixprstatus ];
|
||||||
packages = [
|
packages = [
|
||||||
pkgs.poetry
|
pkgs.poetry
|
||||||
|
pkgs.ruff
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +1,14 @@
|
|||||||
import typer
|
import typer
|
||||||
import json
|
import json
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
from rich.console import Console
|
|
||||||
from nixprstatus.pr import pr_merge_status
|
from nixprstatus.pr import pr_merge_status
|
||||||
from nixprstatus.pr import commits_since
|
from nixprstatus.pr import commits_since
|
||||||
|
from nixprstatus.watchlist import Watchlist
|
||||||
|
from nixprstatus.watchlist import OutputFormat
|
||||||
|
|
||||||
app = typer.Typer()
|
app = typer.Typer(rich_markup_mode=None)
|
||||||
|
watchlist_app = typer.Typer()
|
||||||
|
app.add_typer(watchlist_app, name="watchlist", help="Manage watchlist.")
|
||||||
|
|
||||||
DEFAULT_HEADERS = {
|
DEFAULT_HEADERS = {
|
||||||
"Accept": "application/vnd.github.text+json",
|
"Accept": "application/vnd.github.text+json",
|
||||||
@@ -20,24 +23,17 @@ def pr(
|
|||||||
branches: Annotated[
|
branches: Annotated[
|
||||||
list[str] | None, typer.Option(help="Check specific branch")
|
list[str] | None, typer.Option(help="Check specific branch")
|
||||||
] = None,
|
] = None,
|
||||||
|
format: Annotated[
|
||||||
|
OutputFormat, typer.Option(help="Output format")
|
||||||
|
] = OutputFormat.CONSOLE,
|
||||||
):
|
):
|
||||||
"""Get status of pull request"""
|
"""Get merge status of pull request."""
|
||||||
console = Console()
|
|
||||||
|
|
||||||
if branches:
|
if branches:
|
||||||
status = pr_merge_status(pr, branches)
|
status = pr_merge_status(pr, branches)
|
||||||
else:
|
else:
|
||||||
status = pr_merge_status(pr)
|
status = pr_merge_status(pr)
|
||||||
merged = ":white_check_mark: merged" if status.merged else ":x: merged"
|
|
||||||
console.print(merged, highlight=False)
|
|
||||||
|
|
||||||
for branch in status.branches:
|
status.print(format=format)
|
||||||
output = (
|
|
||||||
f":white_check_mark: {branch}"
|
|
||||||
if status.branches[branch]
|
|
||||||
else f":x: {branch}"
|
|
||||||
)
|
|
||||||
console.print(output, highlight=False)
|
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
@@ -60,6 +56,34 @@ def since(
|
|||||||
typer.echo(count)
|
typer.echo(count)
|
||||||
|
|
||||||
|
|
||||||
|
@watchlist_app.command()
|
||||||
|
def list(watchlist: str | None = None, format: OutputFormat = OutputFormat.CONSOLE):
|
||||||
|
"""List PRs in watchlist."""
|
||||||
|
wl = Watchlist.from_file(path=watchlist)
|
||||||
|
wl.print(format=format)
|
||||||
|
|
||||||
|
|
||||||
|
@watchlist_app.command()
|
||||||
|
def add(pr: int, watchlist: str | None = None):
|
||||||
|
"""Add PR to watchlist."""
|
||||||
|
wl = Watchlist.from_file(path=watchlist)
|
||||||
|
info = wl.add_pr(pr)
|
||||||
|
wl.to_file(path=watchlist)
|
||||||
|
print(f"Added #{info.pr}: {info.title} to watchlist.")
|
||||||
|
|
||||||
|
|
||||||
|
@watchlist_app.command()
|
||||||
|
def remove(pr: int):
|
||||||
|
"""Remove PR from watchlist."""
|
||||||
|
wl = Watchlist.from_file()
|
||||||
|
if pr not in wl:
|
||||||
|
print(f"#{pr} not in watchlist.")
|
||||||
|
return
|
||||||
|
wl.remove(pr)
|
||||||
|
wl.to_file()
|
||||||
|
print(f"Removed #{pr} from watchlist.")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
app()
|
app()
|
||||||
|
|
||||||
|
6
nixprstatus/output.py
Normal file
6
nixprstatus/output.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class OutputFormat(str, Enum):
|
||||||
|
CONSOLE = "console"
|
||||||
|
JSON = "json"
|
@@ -1,5 +1,8 @@
|
|||||||
import requests
|
import requests
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
from rich.console import Console
|
||||||
|
|
||||||
|
from nixprstatus.output import OutputFormat
|
||||||
|
|
||||||
DEFAULT_HEADERS = {
|
DEFAULT_HEADERS = {
|
||||||
"Accept": "application/vnd.github.text+json",
|
"Accept": "application/vnd.github.text+json",
|
||||||
@@ -9,9 +12,30 @@ BACKPORT_LABEL = "backport release-24.05"
|
|||||||
|
|
||||||
|
|
||||||
class PRStatus(BaseModel):
|
class PRStatus(BaseModel):
|
||||||
|
title: str
|
||||||
merged: bool
|
merged: bool
|
||||||
branches: dict[str, bool]
|
branches: dict[str, bool]
|
||||||
|
|
||||||
|
def print(self, format: OutputFormat = OutputFormat.CONSOLE):
|
||||||
|
match format:
|
||||||
|
case OutputFormat.JSON:
|
||||||
|
print(self.model_dump_json())
|
||||||
|
case OutputFormat.CONSOLE:
|
||||||
|
console = Console(highlight=False)
|
||||||
|
console.print(f"{self.title}\n")
|
||||||
|
merged = ":white_check_mark: merged" if self.merged else ":x: merged"
|
||||||
|
console.print(merged)
|
||||||
|
|
||||||
|
for branch in self.branches:
|
||||||
|
output = (
|
||||||
|
f":white_check_mark: {branch}"
|
||||||
|
if self.branches[branch]
|
||||||
|
else f":x: {branch}"
|
||||||
|
)
|
||||||
|
console.print(output)
|
||||||
|
case _:
|
||||||
|
raise ValueError(f"Unknown format: {format}")
|
||||||
|
|
||||||
|
|
||||||
def commit_in_branch(commit_sha: str, branch: str) -> bool:
|
def commit_in_branch(commit_sha: str, branch: str) -> bool:
|
||||||
url = f"https://api.github.com/repos/NixOS/nixpkgs/compare/{branch}...{commit_sha}"
|
url = f"https://api.github.com/repos/NixOS/nixpkgs/compare/{branch}...{commit_sha}"
|
||||||
@@ -32,6 +56,14 @@ def commits_since(first_ref: str, last_ref: str) -> int:
|
|||||||
return commit_response.json()["behind_by"]
|
return commit_response.json()["behind_by"]
|
||||||
|
|
||||||
|
|
||||||
|
def get_pr(pr: int) -> dict:
|
||||||
|
url = f"https://api.github.com/repos/NixOS/nixpkgs/pulls/{pr}"
|
||||||
|
pr_response = requests.get(url, headers=DEFAULT_HEADERS)
|
||||||
|
pr_response.raise_for_status()
|
||||||
|
|
||||||
|
return pr_response.json()
|
||||||
|
|
||||||
|
|
||||||
def pr_merge_status(
|
def pr_merge_status(
|
||||||
pr: int, branches: list[str] = DEFAULT_BRANCHES, check_backport: bool = True
|
pr: int, branches: list[str] = DEFAULT_BRANCHES, check_backport: bool = True
|
||||||
) -> PRStatus:
|
) -> PRStatus:
|
||||||
@@ -40,10 +72,13 @@ def pr_merge_status(
|
|||||||
pr_response.raise_for_status()
|
pr_response.raise_for_status()
|
||||||
|
|
||||||
pr_data = pr_response.json()
|
pr_data = pr_response.json()
|
||||||
|
title = pr_data["title"]
|
||||||
|
|
||||||
merged = pr_data["merged"]
|
merged = pr_data["merged"]
|
||||||
if merged is False:
|
if merged is False:
|
||||||
return PRStatus(merged=False, branches={branch: False for branch in branches})
|
return PRStatus(
|
||||||
|
title=title, merged=False, branches={branch: False for branch in branches}
|
||||||
|
)
|
||||||
|
|
||||||
commit_sha = pr_data.get("merge_commit_sha")
|
commit_sha = pr_data.get("merge_commit_sha")
|
||||||
|
|
||||||
@@ -54,6 +89,13 @@ def pr_merge_status(
|
|||||||
|
|
||||||
results = {}
|
results = {}
|
||||||
|
|
||||||
|
# Check if base branch is in our list, if it is
|
||||||
|
# no need to call commit_in_branch
|
||||||
|
merge_base_branch = pr_data.get("base", {}).get("ref")
|
||||||
|
if merge_base_branch in branches:
|
||||||
|
results[merge_base_branch] = True
|
||||||
|
branches.remove(merge_base_branch)
|
||||||
|
|
||||||
for branch in branches:
|
for branch in branches:
|
||||||
in_branch = commit_in_branch(commit_sha, branch)
|
in_branch = commit_in_branch(commit_sha, branch)
|
||||||
results[branch] = in_branch
|
results[branch] = in_branch
|
||||||
@@ -77,11 +119,11 @@ def pr_merge_status(
|
|||||||
backport_sha = backport_response.json().get("merge_commit_sha")
|
backport_sha = backport_response.json().get("merge_commit_sha")
|
||||||
if backport_sha is None:
|
if backport_sha is None:
|
||||||
results[f"nixos-24.05 (#{backport_pr})"] = False
|
results[f"nixos-24.05 (#{backport_pr})"] = False
|
||||||
return PRStatus(merged=True, branches=results)
|
return PRStatus(title=title, merged=True, branches=results)
|
||||||
|
|
||||||
results.pop("nixos-24.05")
|
results.pop("nixos-24.05")
|
||||||
results[f"nixos-24.05 (#{backport_pr})"] = commit_in_branch(
|
results[f"nixos-24.05 (#{backport_pr})"] = commit_in_branch(
|
||||||
backport_sha, "nixos-24.05"
|
backport_sha, "nixos-24.05"
|
||||||
)
|
)
|
||||||
|
|
||||||
return PRStatus(merged=True, branches=results)
|
return PRStatus(title=title, merged=True, branches=results)
|
||||||
|
88
nixprstatus/watchlist.py
Normal file
88
nixprstatus/watchlist.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from rich.console import Console
|
||||||
|
|
||||||
|
from nixprstatus.pr import get_pr
|
||||||
|
from nixprstatus.output import OutputFormat
|
||||||
|
|
||||||
|
|
||||||
|
class PRInfo(BaseModel):
|
||||||
|
pr: int
|
||||||
|
title: str
|
||||||
|
|
||||||
|
|
||||||
|
class Watchlist(BaseModel):
|
||||||
|
prs: list[PRInfo]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_file(cls, path: str | None = None) -> "Watchlist":
|
||||||
|
if not path:
|
||||||
|
path = _default_path()
|
||||||
|
|
||||||
|
p = Path(path).expanduser()
|
||||||
|
|
||||||
|
if not p.exists():
|
||||||
|
return cls(prs=[])
|
||||||
|
|
||||||
|
with open(p, "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return cls(**data)
|
||||||
|
|
||||||
|
def to_file(self, path: str | None = None):
|
||||||
|
if not path:
|
||||||
|
_ensure_default_path()
|
||||||
|
path = _default_path()
|
||||||
|
|
||||||
|
p = Path(path).expanduser()
|
||||||
|
|
||||||
|
with open(p, "w") as f:
|
||||||
|
f.write(self.model_dump_json())
|
||||||
|
|
||||||
|
def add_pr(self, pr: int) -> PRInfo:
|
||||||
|
# Lookup PR info
|
||||||
|
info = get_pr(pr)
|
||||||
|
|
||||||
|
title = info["title"]
|
||||||
|
info = PRInfo(pr=pr, title=title)
|
||||||
|
self.prs.append(info)
|
||||||
|
return info
|
||||||
|
|
||||||
|
def remove(self, pr: int):
|
||||||
|
self.prs = [p for p in self.prs if p.pr != pr]
|
||||||
|
|
||||||
|
def print(self, format: OutputFormat = OutputFormat.CONSOLE):
|
||||||
|
match format:
|
||||||
|
case OutputFormat.CONSOLE:
|
||||||
|
console = Console()
|
||||||
|
for pr in self.prs:
|
||||||
|
console.print(f"{pr.pr}: {pr.title}")
|
||||||
|
case OutputFormat.JSON:
|
||||||
|
print(self.model_dump_json())
|
||||||
|
case _:
|
||||||
|
raise ValueError(f"Unknown format: {format}")
|
||||||
|
|
||||||
|
def pr(self, pr: int) -> PRInfo | None:
|
||||||
|
for p in self.prs:
|
||||||
|
if p.pr == pr:
|
||||||
|
return p
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __contains__(self, item: PRInfo | int):
|
||||||
|
match item:
|
||||||
|
case PRInfo():
|
||||||
|
return any([x == item for x in self.prs])
|
||||||
|
case int():
|
||||||
|
return any([x.pr == item for x in self.prs])
|
||||||
|
|
||||||
|
|
||||||
|
def _default_path() -> str:
|
||||||
|
if "XDG_STATE_HOME" in os.environ:
|
||||||
|
return f"{os.environ['XDG_STATE_HOME']}/nixprstatus/watchlist.json"
|
||||||
|
return "~/.config/nixprstatus/watchlist.json"
|
||||||
|
|
||||||
|
|
||||||
|
def _ensure_default_path():
|
||||||
|
p = Path(_default_path()).expanduser()
|
||||||
|
p.parent.mkdir(parents=True, exist_ok=True)
|
213
poetry.lock
generated
213
poetry.lock
generated
@@ -42,101 +42,116 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "charset-normalizer"
|
name = "charset-normalizer"
|
||||||
version = "3.3.2"
|
version = "3.4.0"
|
||||||
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7.0"
|
python-versions = ">=3.7.0"
|
||||||
files = [
|
files = [
|
||||||
{file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
|
{file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"},
|
||||||
{file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
|
{file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"},
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
|
{file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"},
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"},
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"},
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"},
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"},
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"},
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"},
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"},
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"},
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"},
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"},
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"},
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"},
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"},
|
||||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
|
{file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"},
|
||||||
{file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
|
{file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"},
|
||||||
{file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
|
{file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"},
|
||||||
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
|
{file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"},
|
||||||
|
{file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"},
|
||||||
|
{file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -205,13 +220,13 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipython"
|
name = "ipython"
|
||||||
version = "8.27.0"
|
version = "8.28.0"
|
||||||
description = "IPython: Productive Interactive Computing"
|
description = "IPython: Productive Interactive Computing"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.10"
|
python-versions = ">=3.10"
|
||||||
files = [
|
files = [
|
||||||
{file = "ipython-8.27.0-py3-none-any.whl", hash = "sha256:f68b3cb8bde357a5d7adc9598d57e22a45dfbea19eb6b98286fa3b288c9cd55c"},
|
{file = "ipython-8.28.0-py3-none-any.whl", hash = "sha256:530ef1e7bb693724d3cdc37287c80b07ad9b25986c007a53aa1857272dac3f35"},
|
||||||
{file = "ipython-8.27.0.tar.gz", hash = "sha256:0b99a2dc9f15fd68692e898e5568725c6d49c527d36a9fb5960ffbdeaa82ff7e"},
|
{file = "ipython-8.28.0.tar.gz", hash = "sha256:0d0d15ca1e01faeb868ef56bc7ee5a0de5bd66885735682e8a322ae289a13d1a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -536,13 +551,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rich"
|
name = "rich"
|
||||||
version = "13.8.1"
|
version = "13.9.2"
|
||||||
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
|
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7.0"
|
python-versions = ">=3.8.0"
|
||||||
files = [
|
files = [
|
||||||
{file = "rich-13.8.1-py3-none-any.whl", hash = "sha256:1760a3c0848469b97b558fc61c85233e3dafb69c7a071b4d60c38099d3cd4c06"},
|
{file = "rich-13.9.2-py3-none-any.whl", hash = "sha256:8c82a3d3f8dcfe9e734771313e606b39d8247bb6b826e196f4914b333b743cf1"},
|
||||||
{file = "rich-13.8.1.tar.gz", hash = "sha256:8260cda28e3db6bf04d2d1ef4dbc03ba80a824c88b0e7668a0f23126a424844a"},
|
{file = "rich-13.9.2.tar.gz", hash = "sha256:51a2c62057461aaf7152b4d611168f93a9fc73068f8ded2790f29fe2b5366d0c"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -667,4 +682,4 @@ files = [
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.12"
|
python-versions = "^3.12"
|
||||||
content-hash = "fe84b0646831111f9ab9ccb6d779eb5e06fac3b7581cf480741bb3c319bd9470"
|
content-hash = "31019803c6d5ce9b3aa759c1c05edfed0b5605ac0be87ca777a057d71b412749"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "nixprstatus"
|
name = "nixprstatus"
|
||||||
version = "0.1.1"
|
version = "0.1.5"
|
||||||
description = "Nixpkgs PR status checker"
|
description = "Nixpkgs PR status checker"
|
||||||
authors = ["Torjus Håkestad <torjus@usit.uio.no>"]
|
authors = ["Torjus Håkestad <torjus@usit.uio.no>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
@@ -8,16 +8,16 @@ readme = "README.md"
|
|||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.12"
|
python = "^3.12"
|
||||||
requests = "^2.32.3"
|
requests = "^2"
|
||||||
typer = "^0.12.5"
|
typer = "^0.12"
|
||||||
pydantic = "^2.9.2"
|
pydantic = "^2"
|
||||||
|
|
||||||
|
|
||||||
[tool.poetry.scripts]
|
[tool.poetry.scripts]
|
||||||
nixprstatus = "nixprstatus.__main__:main"
|
nixprstatus = "nixprstatus.__main__:main"
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
ipython = "^8.27.0"
|
ipython = "*"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core"]
|
requires = ["poetry-core"]
|
||||||
|
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
32
tests/helpers/mocks.py
Normal file
32
tests/helpers/mocks.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
def mocked_requests_get(*args, **kwargs):
|
||||||
|
class MockedResponse:
|
||||||
|
def __init__(self, json_data, status_code):
|
||||||
|
self.json_data = json_data
|
||||||
|
self.status_code = status_code
|
||||||
|
|
||||||
|
def json(self):
|
||||||
|
return json.loads(self.json_data)
|
||||||
|
|
||||||
|
def raise_for_status(self):
|
||||||
|
if self.status_code not in [200, 201]:
|
||||||
|
raise requests.exceptions.HTTPError()
|
||||||
|
|
||||||
|
if "pulls" in args[0]:
|
||||||
|
pr = args[0].split("/")[-1]
|
||||||
|
with open(f"tests/fixtures/pulls_{pr}.json") as f:
|
||||||
|
data = f.read()
|
||||||
|
return MockedResponse(data, 200)
|
||||||
|
elif "compare" in args[0]:
|
||||||
|
branch, commit_sha = args[0].split("/")[-1].split("...")
|
||||||
|
with open(f"tests/fixtures/compare_{branch}_{commit_sha}.json") as f:
|
||||||
|
data = f.read()
|
||||||
|
return MockedResponse(data, 200)
|
||||||
|
elif "comments" in args[0]:
|
||||||
|
pr = args[0].split("/")[-2]
|
||||||
|
with open(f"tests/fixtures/comments_{pr}.json") as f:
|
||||||
|
data = f.read()
|
||||||
|
return MockedResponse(data, 200)
|
@@ -1,39 +1,8 @@
|
|||||||
import unittest
|
import unittest
|
||||||
import unittest.mock
|
import unittest.mock
|
||||||
import requests
|
|
||||||
import json
|
|
||||||
|
|
||||||
from nixprstatus.pr import commit_in_branch, pr_merge_status, commits_since
|
from nixprstatus.pr import commit_in_branch, pr_merge_status, commits_since
|
||||||
|
from tests.helpers.mocks import mocked_requests_get
|
||||||
|
|
||||||
def mocked_requests_get(*args, **kwargs):
|
|
||||||
class MockedResponse:
|
|
||||||
def __init__(self, json_data, status_code):
|
|
||||||
self.json_data = json_data
|
|
||||||
self.status_code = status_code
|
|
||||||
|
|
||||||
def json(self):
|
|
||||||
return json.loads(self.json_data)
|
|
||||||
|
|
||||||
def raise_for_status(self):
|
|
||||||
if self.status_code not in [200, 201]:
|
|
||||||
raise requests.exceptions.HTTPError()
|
|
||||||
|
|
||||||
if "pulls" in args[0]:
|
|
||||||
pr = args[0].split("/")[-1]
|
|
||||||
with open(f"tests/fixtures/pulls_{pr}.json") as f:
|
|
||||||
data = f.read()
|
|
||||||
return MockedResponse(data, 200)
|
|
||||||
elif "compare" in args[0]:
|
|
||||||
branch, commit_sha = args[0].split("/")[-1].split("...")
|
|
||||||
with open(f"tests/fixtures/compare_{branch}_{commit_sha}.json") as f:
|
|
||||||
data = f.read()
|
|
||||||
return MockedResponse(data, 200)
|
|
||||||
elif "comments" in args[0]:
|
|
||||||
pr = args[0].split("/")[-2]
|
|
||||||
with open(f"tests/fixtures/comments_{pr}.json") as f:
|
|
||||||
data = f.read()
|
|
||||||
return MockedResponse(data, 200)
|
|
||||||
|
|
||||||
|
|
||||||
class TestPRMergeStatus(unittest.TestCase):
|
class TestPRMergeStatus(unittest.TestCase):
|
||||||
@@ -57,6 +26,28 @@ class TestPRMergeStatus(unittest.TestCase):
|
|||||||
self.assertTrue(res.merged)
|
self.assertTrue(res.merged)
|
||||||
self.assertTrue(res.branches["nixos-24.05 (#346022)"])
|
self.assertTrue(res.branches["nixos-24.05 (#346022)"])
|
||||||
|
|
||||||
|
@unittest.mock.patch("requests.get", side_effect=mocked_requests_get)
|
||||||
|
def test_pr_merge_status_title_345769(self, mock_get):
|
||||||
|
pr = 345769
|
||||||
|
branches = ["nixos-24.05"]
|
||||||
|
expected_title = "Firefox: 130.0.1 -> 131.0; 128.2.0esr -> 128.3.0esr; 115.15.0esr -> 115.16.0esr"
|
||||||
|
|
||||||
|
res = pr_merge_status(pr, branches, check_backport=True)
|
||||||
|
self.assertEqual(res.title, expected_title)
|
||||||
|
|
||||||
|
@unittest.mock.patch("requests.get", side_effect=mocked_requests_get)
|
||||||
|
def test_pr_merge_status_no_check_master_345583(self, mock_get):
|
||||||
|
pr = 345583
|
||||||
|
branches = ["master", "nixos-unstable", "nixos-24.05"]
|
||||||
|
master_compare_url = "https://api.github.com/repos/NixOS/nixpkgs/compare/master...2c5fac3edf2d00d948253e392ec1604b29b38f14"
|
||||||
|
|
||||||
|
res = pr_merge_status(pr, branches, check_backport=False)
|
||||||
|
self.assertTrue(res.merged)
|
||||||
|
self.assertTrue(res.branches["master"])
|
||||||
|
|
||||||
|
urls_called = [call[0][0] for call in mock_get.call_args_list]
|
||||||
|
self.assertFalse(master_compare_url in urls_called)
|
||||||
|
|
||||||
|
|
||||||
class TestCommitInBranch(unittest.TestCase):
|
class TestCommitInBranch(unittest.TestCase):
|
||||||
@unittest.mock.patch("requests.get", side_effect=mocked_requests_get)
|
@unittest.mock.patch("requests.get", side_effect=mocked_requests_get)
|
||||||
|
40
tests/test_watchlist.py
Normal file
40
tests/test_watchlist.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
from nixprstatus.watchlist import Watchlist, PRInfo
|
||||||
|
from tempfile import TemporaryDirectory
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from tests.helpers.mocks import mocked_requests_get
|
||||||
|
|
||||||
|
|
||||||
|
class TestWatchlist(unittest.TestCase):
|
||||||
|
def test_save_load(self):
|
||||||
|
with TemporaryDirectory() as d:
|
||||||
|
filename = f"{d}/test.json"
|
||||||
|
|
||||||
|
watchlist = Watchlist(prs=[PRInfo(pr=1, title="PR 1")])
|
||||||
|
watchlist.to_file(filename)
|
||||||
|
|
||||||
|
# Check that the file was written correctly
|
||||||
|
with open(filename, "r") as f:
|
||||||
|
self.assertEqual(watchlist.model_dump_json(), f.read())
|
||||||
|
|
||||||
|
# Check that the file can be read back
|
||||||
|
loaded = Watchlist.from_file(filename)
|
||||||
|
self.assertEqual(watchlist, loaded)
|
||||||
|
|
||||||
|
@unittest.mock.patch("requests.get", side_effect=mocked_requests_get)
|
||||||
|
def test_add_pr(self, mock_get):
|
||||||
|
w = Watchlist(prs=[])
|
||||||
|
w.add_pr(345583)
|
||||||
|
self.assertEqual(len(w.prs), 1)
|
||||||
|
self.assertEqual(w.prs[0].title, "wireshark: 4.2.6 -> 4.2.7")
|
||||||
|
|
||||||
|
def test_get_pr(self):
|
||||||
|
w = Watchlist(prs=[PRInfo(pr=1, title="PR 1")])
|
||||||
|
self.assertEqual(w.pr(1), PRInfo(pr=1, title="PR 1"))
|
||||||
|
self.assertEqual(w.pr(2), None)
|
||||||
|
|
||||||
|
def test_contains(self):
|
||||||
|
w = Watchlist(prs=[PRInfo(pr=1, title="PR 1")])
|
||||||
|
self.assertIn(PRInfo(pr=1, title="PR 1"), w)
|
||||||
|
self.assertIn(1, w)
|
||||||
|
self.assertNotIn(2, w)
|
Reference in New Issue
Block a user