Compare commits
27 Commits
main
...
wkt/land_b
| Author | SHA1 | Date |
|---|---|---|
|
|
30df6b83cf | |
|
|
6dfc73d0bf | |
|
|
dbcf5228ab | |
|
|
78e7a91a6e | |
|
|
a23e46f4d6 | |
|
|
507c75c669 | |
|
|
1fa45dfa98 | |
|
|
bde2457bdd | |
|
|
1ba9bdbac0 | |
|
|
d86f29d416 | |
|
|
69a6edd6f8 | |
|
|
bbe9deaa62 | |
|
|
70e8d60326 | |
|
|
2c007d3ada | |
|
|
1fde12d3fd | |
|
|
c347ab08ea | |
|
|
c5155ce814 | |
|
|
d7cefa71f3 | |
|
|
20bfbc2380 | |
|
|
d7f956a566 | |
|
|
d26286f6cc | |
|
|
22f166a5c6 | |
|
|
6c8709d309 | |
|
|
23632d2153 | |
|
|
d85e57334c | |
|
|
6c8d17da75 | |
|
|
1976f6a5de |
|
|
@ -0,0 +1,52 @@
|
||||||
|
---
|
||||||
|
created_at: 2026-10-07T16:54:53Z
|
||||||
|
generated_by:
|
||||||
|
harness: opencode
|
||||||
|
provider: openai
|
||||||
|
model: gpt-6.1-sol
|
||||||
|
git_ref: bde2457b
|
||||||
|
scope: code
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20261007T165453Z_bde2457b_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
The user requested fixing all seven local PR94 review findings and
|
||||||
|
exporting the review for human inspection in Tuicr. They asked that a
|
||||||
|
Tractor pin adjustment be considered before adding Piker workarounds.
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Correct the endpoint defaults, Click argument shape, daemon binding and
|
||||||
|
registrar option handling, chart fallback, and stray debugger pause.
|
||||||
|
Keep the absent datad implementation's test outside this landing
|
||||||
|
branch. Add offline startup coverage and export original findings
|
||||||
|
without modifying review states. The checked newer Tractor address
|
||||||
|
branch still rejects mixed transports, so leave the dependency pin.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- `config/conf.toml`: TCP-only default endpoints.
|
||||||
|
- `piker/cli/__init__.py`: repeatable and intact multiaddresses.
|
||||||
|
- `piker/service/_actor_runtime.py`: validate daemon listeners.
|
||||||
|
- `piker/service/_daemon.py`: initialize and consume registrar options.
|
||||||
|
- `piker/ui/cli.py`: fallback to automatic chart binding.
|
||||||
|
- `piker/brokers/binance/feed.py`: remove unconditional debugger entry.
|
||||||
|
- `tests/test_services.py`: defer test requiring missing datad API.
|
||||||
|
- `tests/test_startup.py`: CLI/config and service lifecycle regressions.
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
The human identified that datad tests arrived through the agent's
|
||||||
|
mixed cherry-picks and explicitly requested deferring that test. They
|
||||||
|
requested a chart default for existing configs, expanded the task to
|
||||||
|
all review findings, and directed checking whether a newer Tractor pin
|
||||||
|
could reduce the fix scope. No direct manual source edits were observed
|
||||||
|
during these changes; acceptance remains with the human.
|
||||||
|
|
||||||
|
During the human review pass, the human confirmed removing the Binance
|
||||||
|
pause and correcting CLI endpoint parsing. They requested an explicit
|
||||||
|
template note about this pin's single-transport limitation and detailed
|
||||||
|
comments distinguishing registrar discovery endpoints from daemon bind
|
||||||
|
endpoints. Those explanations were added at the human's direction.
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
---
|
||||||
|
created_at: 2026-10-07T16:54:53Z
|
||||||
|
generated_by:
|
||||||
|
harness: opencode
|
||||||
|
provider: openai
|
||||||
|
model: gpt-6.1-sol
|
||||||
|
git_ref: bde2457b
|
||||||
|
diff_cmd: git diff HEAD~1..HEAD
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
Fix all findings from the local PR94 review, prefer a Tractor pin
|
||||||
|
change if it reduces work, and export the original review for Tuicr.
|
||||||
|
|
||||||
|
## Generated changes
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- config/conf.toml`
|
||||||
|
|
||||||
|
Use TCP-only defaults, retaining commented UDS alternatives. Both
|
||||||
|
checked Tractor address branch tips still reject mixed transports.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- piker/cli/__init__.py`
|
||||||
|
|
||||||
|
Make Click multiaddresses repeatable and normalize single strings.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- piker/service/_actor_runtime.py`
|
||||||
|
|
||||||
|
Validate requested daemon bind addresses instead of remote registrars.
|
||||||
|
Normalize accepted endpoints and allow TCP ephemeral port requests.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- piker/service/_daemon.py`
|
||||||
|
|
||||||
|
Resolve explicit or inherited registrars independently of other daemon
|
||||||
|
options and consume the explicit keyword before forwarding kwargs.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- piker/ui/cli.py`
|
||||||
|
|
||||||
|
Default chart bind endpoints to None when network config is absent.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- piker/brokers/binance/feed.py`
|
||||||
|
|
||||||
|
Remove the unconditional market-info debugger pause.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- tests/test_services.py tests/test_startup.py`
|
||||||
|
|
||||||
|
Remove the prematurely cherry-picked datad test and add offline startup
|
||||||
|
regressions, including a real registrar/child daemon lifecycle check.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
- Startup and logging tests: 13 passed.
|
||||||
|
- Existing runtime boot and tagged registrar tests: 2 passed.
|
||||||
|
- Scoped native Ruff and diff checks pass.
|
||||||
|
- The first new actor test used a removed nursery API; it was corrected
|
||||||
|
to the installed start_actor/Portal.run interface before passing.
|
||||||
|
- Import initially failed without native libraries. Tests use the
|
||||||
|
existing flake's GCC, zlib, Qt and PyQt paths without executing its
|
||||||
|
environment-rebuilding shell hook.
|
||||||
|
- Original seven findings exported locally as Tuicr review-add payloads
|
||||||
|
bound to bde2457b; no session comments or remote PR were changed.
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
---
|
||||||
|
created_at: 2026-10-10T23:28:52Z
|
||||||
|
generated_by:
|
||||||
|
harness: opencode
|
||||||
|
provider: openai
|
||||||
|
model: openai/gpt-6.1-sol
|
||||||
|
git_ref: 1fa45dfa
|
||||||
|
scope: config
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20261010T232852Z_1fa45dfa_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
The human rejected keeping the April Tractor pin as a landing baseline.
|
||||||
|
They requested the reviewed `wkt/addr_unpacking` branch, removal of the
|
||||||
|
new rollback adaptations, reuse of original Piker histories where
|
||||||
|
possible, and a candidate prepared within their gateway relocation
|
||||||
|
window. They asked specifically whether the runtime validation review
|
||||||
|
hunk duplicated older endpoint history.
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Select the reviewed address branch at an immutable locked revision and
|
||||||
|
preserve all committed application/test compatibility code. Verify the
|
||||||
|
minimal dependency boundary offline and preview existing consumer
|
||||||
|
fixes without importing unrelated datad/backfill changes. Distinguish
|
||||||
|
original-source test results from live teardown acceptance, which is
|
||||||
|
not available in this preparation window.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- `pyproject.toml`: select Tractor `wkt/addr_unpacking`.
|
||||||
|
- `uv.lock`: resolve reviewed `a966928d` and setproctitle 1.3.8 while
|
||||||
|
preserving Polars 1.36.0 and the rest of the locked graph.
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
The human redirected the task from an older known-good runtime to a
|
||||||
|
modern landing stack and insisted on reusing original history rather
|
||||||
|
than building new compatibility adapters. They proposed stricter
|
||||||
|
exception-group behavior as a hypothesis and set the live-test/time
|
||||||
|
constraints. Those directions materially changed the dependency
|
||||||
|
boundary. No direct manual edits to this final boundary were observed;
|
||||||
|
runtime acceptance and landing remain human-owned.
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
---
|
||||||
|
created_at: 2026-10-10T23:28:52Z
|
||||||
|
generated_by:
|
||||||
|
harness: opencode
|
||||||
|
provider: openai
|
||||||
|
model: openai/gpt-6.1-sol
|
||||||
|
git_ref: 1fa45dfa
|
||||||
|
diff_cmd: git diff HEAD~1..HEAD
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
Undo the April Tractor rollback and select the reviewed
|
||||||
|
`wkt/addr_unpacking` branch. Prefer original downstream compatibility
|
||||||
|
commits to new adaptations, and prepare an offline-verified candidate
|
||||||
|
while live IB verification is deferred for gateway relocation.
|
||||||
|
|
||||||
|
## Generated changes
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- pyproject.toml uv.lock`
|
||||||
|
|
||||||
|
Change Tractor's source from `piker_pin` to `wkt/addr_unpacking` and
|
||||||
|
lock it at `a966928dead4cbf369ad244834ce9dbe988ac8ca`. Restore application
|
||||||
|
and test sources byte-for-byte to the committed PR94 tree. Keep the
|
||||||
|
rejected rollback journal only in ignored local experiment reports.
|
||||||
|
Preserve Polars 1.36.0 by retaining its exact existing lock blocks;
|
||||||
|
setproctitle re-resolves from 1.3.7 to 1.3.8. `uv sync --locked` accepts
|
||||||
|
the resulting graph. Actual imports confirm the reviewed Tractor pin
|
||||||
|
and Trio 0.32.0, not the hypothesized Trio 0.33.
|
||||||
|
|
||||||
|
## Original-history previews
|
||||||
|
|
||||||
|
The existing MethodProxy stack is retained. Read-only merge previews
|
||||||
|
show original `4af885d9` and `b691422b` can be applied without the datad
|
||||||
|
cutover. Original-source regressions run through temporary in-memory
|
||||||
|
overlays against the real pinned runtime: seven cases pass and one
|
||||||
|
cache-hit case fails because `log.at_least_level('info')` looks up INFO
|
||||||
|
in a custom-level mapping. A separate standard logging correction
|
||||||
|
produces eight passing cases. Its patch and execution handoff are saved
|
||||||
|
under ignored `.ai/code-review/reports/pr94_modern_stack/`; no consumer
|
||||||
|
cherry-picks or source edits are performed by this boundary.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
- Startup and logging: 13 passed.
|
||||||
|
- Runtime boot and tagged registrar normalization: 2 passed.
|
||||||
|
- Locked sync and source whitespace checks pass.
|
||||||
|
- Original application/test trees are unchanged from PR94 HEAD.
|
||||||
|
- Consumer overlay with explicit logging correction: 8 passed.
|
||||||
|
- Correction patch validates against its exact preview tree using a
|
||||||
|
private temporary index; the real index is untouched.
|
||||||
|
- Live IB startup, SIGINT and surviving-pikerd reattachment are pending.
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
model: claude-fable-5[1m]
|
||||||
|
service: claude
|
||||||
|
session: 32d15f9a-b2d3-4c26-bdc9-190219141a25
|
||||||
|
timestamp: 2026-06-10T17:08:59Z
|
||||||
|
git_ref: datad_service
|
||||||
|
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T170859Z_75cefe10_prompt_io.md
|
||||||
|
scope: code
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20260610T170859Z_75cefe10_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
Session-initiating instruction (driving all 7 commits in
|
||||||
|
this series):
|
||||||
|
|
||||||
|
> ok i want you to become the distributed runtime and
|
||||||
|
> concurrency expert for this project - namely acquire
|
||||||
|
> a deep understanding of tractor and how it's used.
|
||||||
|
> then i want you to attempt to factor our current
|
||||||
|
> brokerd service daemon into 2 daemons: a brokerd
|
||||||
|
> which only hosts live/paper trading endpoint tasks
|
||||||
|
> [..] a new `datad` subdaemon which in a separate
|
||||||
|
> subactor serves all the data feed service tasks [..]
|
||||||
|
> give me a mega detailed plan on how to approach this,
|
||||||
|
> and a staged approach for the implementation.
|
||||||
|
|
||||||
|
Proximate driver for THIS commit: during the approved
|
||||||
|
plan's stage-0 test gate the agent discovered test
|
||||||
|
subactors were writing into the user's REAL
|
||||||
|
`~/.config/piker/accounting/` files (a bogus paper fill
|
||||||
|
landed in `account.kraken.paper.toml`) because the old
|
||||||
|
test-dir override in `config.get_app_dir()` was
|
||||||
|
commented out and could never work in spawned
|
||||||
|
subactors anyway. Fix applied autonomously under the
|
||||||
|
approved plan; no explicit per-fix user prompt.
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Restore `pytest` config-dir isolation by resolving the
|
||||||
|
per-test tmp dir lazily (at conf-path access time) from
|
||||||
|
`tractor` runtime-vars, which propagate down the actor
|
||||||
|
tree; route all conf-path derivation through
|
||||||
|
`config.get_conf_dir()` so the override is effective in
|
||||||
|
every (sub)actor.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- `piker/config.py` — add `_maybe_use_test_dir()`;
|
||||||
|
hook in `get_conf_dir()`; route `get_conf_path()` +
|
||||||
|
`load()` mkdir through it
|
||||||
|
- `piker/accounting/_ledger.py` — derive ledger dir
|
||||||
|
via `config.get_conf_dir()` (not the global)
|
||||||
|
- `piker/accounting/_pos.py` — same for account files
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
None — committed as generated.
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
model: claude-fable-5[1m]
|
||||||
|
service: claude
|
||||||
|
timestamp: 2026-06-10T17:08:59Z
|
||||||
|
git_ref: datad_service
|
||||||
|
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T170859Z_75cefe10_prompt_io.md
|
||||||
|
---
|
||||||
|
|
||||||
|
NOTE: diff-ref mode entry (code committed in the same
|
||||||
|
commit as this log); backfilled from the live dev
|
||||||
|
session transcript per the `/prompt-io` skill rules.
|
||||||
|
|
||||||
|
> `git log -1 -p --follow -- piker/config.py`
|
||||||
|
|
||||||
|
Generated: `config._maybe_use_test_dir()` — lazily
|
||||||
|
reads `piker_test_dir` from
|
||||||
|
`tractor.runtime._state._runtime_vars['piker_vars']`
|
||||||
|
(pre-loaded by `open_piker_runtime()` from the
|
||||||
|
`tests.conftest._open_test_pikerd()` overrides) and
|
||||||
|
calls `_override_config_dir()` when set. Hooked at the
|
||||||
|
top of `get_conf_dir()`; `get_conf_path()` and
|
||||||
|
`load()`'s dir-creation rerouted through
|
||||||
|
`get_conf_dir()`.
|
||||||
|
|
||||||
|
> `git log -1 -p --follow -- piker/accounting/_ledger.py`
|
||||||
|
> `git log -1 -p --follow -- piker/accounting/_pos.py`
|
||||||
|
|
||||||
|
Generated: ledger/account dir derivation switched from
|
||||||
|
the `config._config_dir` module global to
|
||||||
|
`config.get_conf_dir()` + `mkdir(parents=True,
|
||||||
|
exist_ok=True)` for nested tmp-dir creation.
|
||||||
|
|
||||||
|
Key diagnostic reasoning (verbatim from session):
|
||||||
|
|
||||||
|
The old (commented-out) `get_app_dir()` override gated
|
||||||
|
on `'pytest' in sys.modules` which can NEVER work in
|
||||||
|
spawned subactors (fresh procs, no pytest import); as
|
||||||
|
a result test `paperboi`/daemon actors were writing
|
||||||
|
into the user's REAL `~/.config/piker/accounting/`
|
||||||
|
files. Evidence: `account.kraken.paper.toml` gained a
|
||||||
|
single 0.001 xbtusdt clear stamped 2026-06-09T18:47Z
|
||||||
|
(a test fill), and `trades_kraken_paper.toml` (252B)
|
||||||
|
contained only that fill. The resolution must be
|
||||||
|
checked lazily at config-path access time (NOT import
|
||||||
|
time) since sub-actors only receive runtime-vars once
|
||||||
|
their `tractor` runtime has fully booted.
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
---
|
||||||
|
model: claude-fable-5[1m]
|
||||||
|
service: claude
|
||||||
|
session: 32d15f9a-b2d3-4c26-bdc9-190219141a25
|
||||||
|
timestamp: 2026-06-10T17:10:22Z
|
||||||
|
git_ref: datad_service
|
||||||
|
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171022Z_4485f2b9_prompt_io.md
|
||||||
|
scope: code
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20260610T171022Z_4485f2b9_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
Same session-initiating `brokerd`-split instruction (see
|
||||||
|
`20260610T170859Z_75cefe10_prompt_io.md`). Proximate
|
||||||
|
driver: the approved plan's per-stage test gates could
|
||||||
|
not run AT ALL — the branch base was broken vs.
|
||||||
|
`tractor` git `main` (`AttributeError: 'tuple' object
|
||||||
|
has no attribute 'unwrap'` at `pikerd` boot, stale
|
||||||
|
`arbiter_sockaddr`/`.type`/`.size` API refs). The agent
|
||||||
|
fixed forward autonomously to (re)establish the gate
|
||||||
|
baseline, continuing the `repair_tests` branch lineage
|
||||||
|
(verified already merged in ancestry via `git cherry`
|
||||||
|
during a user-requested branch-overlap survey).
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Port the service layer + test suites to current
|
||||||
|
`tractor` APIs: addr-type normalization in
|
||||||
|
`open_pikerd()`, `query_actor()`/`wait_for_actor()`
|
||||||
|
kwarg renames, modern self-cancel absorption semantics
|
||||||
|
in the cancel-method test harness, exc/position attr
|
||||||
|
renames, a paper-EMS startup-budget bump and a syntax
|
||||||
|
fix in `.deribit.api`.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- `piker/service/_actor_runtime.py` — `wrap_address()`
|
||||||
|
normalize before `.unwrap()` in `open_pikerd()`
|
||||||
|
- `piker/service/_registry.py` — `check_for_service()`
|
||||||
|
-> `query_actor(regaddr=)` + 2-tuple yield +
|
||||||
|
`open_registry(addrs=)`
|
||||||
|
- `piker/brokers/deribit/api.py` — missing comma in
|
||||||
|
`tractor.trionics` import tuple
|
||||||
|
- `tests/test_services.py` — `registry_addr=` kwarg,
|
||||||
|
raddr unwraps, cancel-semantics harness rewrite,
|
||||||
|
`fail_after` 9 -> 19s
|
||||||
|
- `tests/test_ems.py` — `.boxed_type`, `pp.cumsize`
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
None — committed as generated.
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
---
|
||||||
|
model: claude-fable-5[1m]
|
||||||
|
service: claude
|
||||||
|
timestamp: 2026-06-10T17:10:22Z
|
||||||
|
git_ref: datad_service
|
||||||
|
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171022Z_4485f2b9_prompt_io.md
|
||||||
|
---
|
||||||
|
|
||||||
|
NOTE: diff-ref mode entry (code committed in the same
|
||||||
|
commit as this log); backfilled from the live dev
|
||||||
|
session transcript per the `/prompt-io` skill rules.
|
||||||
|
|
||||||
|
> `git log -1 -p --follow -- piker/service/_actor_runtime.py`
|
||||||
|
|
||||||
|
Generated: normalize each registry addr via
|
||||||
|
`tractor.discovery._addr.wrap_address()` before
|
||||||
|
`.unwrap()`-ing for the `accept_addrs` bind check —
|
||||||
|
entries may be raw `tuple`s when passed in from (test)
|
||||||
|
client code. Import-path precedent taken from
|
||||||
|
`piker/cli/__init__.py:336`.
|
||||||
|
|
||||||
|
> `git log -1 -p --follow -- piker/service/_registry.py`
|
||||||
|
|
||||||
|
Generated: `check_for_service()` ported to
|
||||||
|
`tractor.query_actor(name, regaddr=...)` (kwarg was
|
||||||
|
`arbiter_sockaddr=`), unpacking the new
|
||||||
|
`(sockaddr, portal)` yield, and passing the
|
||||||
|
now-required `open_registry(addrs=Registry.addrs)`.
|
||||||
|
|
||||||
|
> `git log -1 -p --follow -- tests/test_services.py`
|
||||||
|
> `git log -1 -p --follow -- tests/test_ems.py`
|
||||||
|
> `git log -1 -p --follow -- piker/brokers/deribit/api.py`
|
||||||
|
|
||||||
|
Key diagnostic reasoning (verbatim from session):
|
||||||
|
|
||||||
|
- the "DID NOT RAISE ContextCancelled" failure: in this
|
||||||
|
test the client actor IS pikerd (in-proc), and
|
||||||
|
current `tractor` main absorbs a `ContextCancelled`
|
||||||
|
whose canceller is your own actor — self-requested
|
||||||
|
cancels now exit cleanly instead of raising; the
|
||||||
|
'sigint' variant propagates a bare collapsed
|
||||||
|
`KeyboardInterrupt` rather than a
|
||||||
|
`BaseExceptionGroup`.
|
||||||
|
- the hard-coded `trio.fail_after(9)` startup budget is
|
||||||
|
marginal — full stack boot (pikerd -> emsd ->
|
||||||
|
brokerd.kraken -> paperboi + live kraken symbology
|
||||||
|
fetch) occasionally exceeds 9s -> bumped to 19s.
|
||||||
|
- `RemoteActorError.type` -> `.boxed_type`;
|
||||||
|
`Position.size` -> `.cumsize` (the paper engine
|
||||||
|
populates `BrokerdPosition.size` from `pp.cumsize`).
|
||||||
|
- overlap survey (user-requested): all of the
|
||||||
|
`repair_tests` branch commits are already in this
|
||||||
|
stack's ancestry; this commit finishes that branch's
|
||||||
|
port mission (its f4c4f1e2 fixed `conftest.py`'s
|
||||||
|
`arbiter_sockaddr` usage; this fixes the remaining
|
||||||
|
`test_services.py` + `check_for_service()` sites).
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
# AI Prompt I/O Log — claude
|
||||||
|
|
||||||
|
This directory tracks prompt inputs and model
|
||||||
|
outputs for AI-assisted development using
|
||||||
|
`claude` (claude-code CLI).
|
||||||
|
|
||||||
|
## Policy
|
||||||
|
|
||||||
|
Prompt logging follows the
|
||||||
|
[NLNet generative AI policy][nlnet-ai].
|
||||||
|
All substantive AI contributions are logged
|
||||||
|
with:
|
||||||
|
- Model name and version
|
||||||
|
- Timestamps
|
||||||
|
- The prompts that produced the output
|
||||||
|
- Unedited model output (`.raw.md` files)
|
||||||
|
|
||||||
|
[nlnet-ai]: https://nlnet.nl/foundation/policies/generativeAI/
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Entries are created by the `/prompt-io` skill
|
||||||
|
or automatically via `/commit-msg` integration.
|
||||||
|
|
||||||
|
Each commit carrying AI-generated changes links
|
||||||
|
to its provenance entry via a `Prompt-IO:`
|
||||||
|
commit-msg trailer; entries use "diff-ref mode"
|
||||||
|
(pointers into `git log -p` instead of verbatim
|
||||||
|
code copies) to avoid duplicating committed
|
||||||
|
code.
|
||||||
|
|
||||||
|
Human contributors remain accountable for all
|
||||||
|
code decisions. AI-generated content is never
|
||||||
|
presented as human-authored work.
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
session: ses_0799212ebffe42arY96czXn89F
|
||||||
|
timestamp: 2026-08-11T20:58:26Z
|
||||||
|
git_ref: 06d5ea5d
|
||||||
|
scope: code
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20260811T205826Z_06d5ea5d_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
Diagnose and fix an IB live-order failure where lazy NVDA contract
|
||||||
|
qualification raised `tractor.trionics.Lagged` after the order reached
|
||||||
|
`brokerd.ib`. Determine whether recent history changes or cancelled symbol
|
||||||
|
searches caused the stale state.
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Traced the failure to competing consumers of a one-slot Trio broadcast, not
|
||||||
|
the recent SHM change or stale asyncio client state. Replaced broadcast
|
||||||
|
fan-out with one response/status demultiplexer, retained request-ID
|
||||||
|
correlation, handled cancellation and teardown, documented the task/channel
|
||||||
|
ownership model, warned on diagnostic metadata eviction, and added
|
||||||
|
deterministic proxy regressions.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- `piker/brokers/ib/api.py` - sole-reader IB proxy response routing.
|
||||||
|
- `tests/test_ib_method_proxy.py` - status, concurrency, cancellation and EOF regressions.
|
||||||
|
- `.claude/skills/run-tests/test-harness-reference.md` - proxy test mapping.
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
None - generated output follows the user's live failure diagnosis.
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
timestamp: 2026-08-11T20:58:26Z
|
||||||
|
git_ref: 06d5ea5d
|
||||||
|
diff_cmd: git diff HEAD~1..HEAD
|
||||||
|
---
|
||||||
|
|
||||||
|
The user reported that certain IB order entries might have broken and
|
||||||
|
provided a live failure for a first NVDA sell order. EMS delivered the
|
||||||
|
request to `brokerd.ib`, but lazy `get_mkt_info('nvda.nasdaq')` contract
|
||||||
|
qualification failed in `MethodProxy._run_method()` with:
|
||||||
|
|
||||||
|
```text
|
||||||
|
tractor.trionics._broadcast.Lagged:
|
||||||
|
Task `piker.brokers.ib.broker.handle_order_requests` overrun and
|
||||||
|
dropped `0` values
|
||||||
|
```
|
||||||
|
|
||||||
|
The user suspected a cancelled symbol-search task might have left stale
|
||||||
|
asyncio state. Cancellation can leave an orphaned method response, but the
|
||||||
|
observed failure was stale Trio broadcast state. `open_client_proxy()`
|
||||||
|
broadcast a one-slot `LinkedTaskChannel` to an always-running IB status relay
|
||||||
|
and an idle method receiver. Status traffic advanced only the relay, so the
|
||||||
|
first method call for an uncached symbol entered an already-lagged receiver.
|
||||||
|
Orders for eagerly cached contracts bypassed this path.
|
||||||
|
|
||||||
|
The immediately preceding sparse-history commit did not modify IB order,
|
||||||
|
symbol, or proxy code; it exposed no direct dependency on this failure.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- piker/brokers/ib/api.py`
|
||||||
|
|
||||||
|
Generated a sole-reader message demultiplexer for each IB client proxy.
|
||||||
|
`relay_client_proxy_messages()` owns every asyncio-to-Trio receive, handles
|
||||||
|
status/error traffic, and dispatches `mid`-tagged responses into per-call
|
||||||
|
`MethodProxy` wait slots. Cancelled calls remove their pending slot, causing
|
||||||
|
late responses to be logged and dropped without skewing later calls. Clean
|
||||||
|
channel EOF is accepted during normal proxy teardown.
|
||||||
|
|
||||||
|
Follow-up review restored the masked reconnect TODO and per-message case
|
||||||
|
rationale, documented the one-reader/many-writer task hierarchy and separate
|
||||||
|
per-proxy channels, and added a warning with request method metadata when the
|
||||||
|
bounded unresolved-request diagnostic table evicts its oldest entry.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- tests/test_ib_method_proxy.py`
|
||||||
|
|
||||||
|
Generated deterministic regressions for idle status traffic before first
|
||||||
|
qualification, two concurrent calls with reverse-order responses, cancelled
|
||||||
|
calls with late responses followed by a successful call, and graceful
|
||||||
|
channel EOF. Every synchronization wait is timeout-bounded.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- .claude/skills/run-tests/test-harness-reference.md`
|
||||||
|
|
||||||
|
Registered the deterministic IB method-proxy target and source mapping.
|
||||||
|
|
||||||
|
Verification output:
|
||||||
|
|
||||||
|
```text
|
||||||
|
........................ [100%]
|
||||||
|
25 passed, 4 warnings in 3.44s
|
||||||
|
```
|
||||||
|
|
||||||
|
The warnings are existing Tractor/Trio deprecations from the EMS test.
|
||||||
|
Adversarial review drove a clean-EOF guard and bounded polling. Final review
|
||||||
|
found no actionable issues. Live IB order validation remains pending and
|
||||||
|
requires restarting `brokerd.ib`.
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
session: unavailable
|
||||||
|
timestamp: 2026-08-13T20:24:02Z
|
||||||
|
git_ref: 12b0d66e
|
||||||
|
scope: code
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20260813T202402Z_12b0d66e_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
Continue the paired piker broadcast-consumer work after Tractor PR 490
|
||||||
|
stabilization. Stop cached feed callers from mutating or consuming shared
|
||||||
|
quote-stream roots, then review, verify and prepare a commit boundary.
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Made provider root streams private to the cached `Feed`, gave every caller a
|
||||||
|
local subscribed view, corrected feed cache identity, and made multi-provider
|
||||||
|
relays own synchronized child subscriptions and independent send-channel
|
||||||
|
clones.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- `piker/data/feed.py` - caller-local feed views, complete cache keys, and
|
||||||
|
subscribed multi-provider relays with independent channel lifetimes.
|
||||||
|
- `tests/test_feed_broadcast.py` - real broadcast ownership, lifecycle and
|
||||||
|
cache-identity regressions, including sibling survival after provider EOC.
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
None - generated output follows the requested cached-feed ownership item.
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
timestamp: 2026-08-13T20:24:02Z
|
||||||
|
git_ref: 12b0d66e
|
||||||
|
diff_cmd: git diff HEAD~1..HEAD
|
||||||
|
---
|
||||||
|
|
||||||
|
The user asked to continue the paired piker broadcast-consumer work after
|
||||||
|
Tractor PR 490 stabilization. The next item was to stop cached feed callers
|
||||||
|
from mutating or consuming shared `Feed`/`Flume` quote-stream roots, then
|
||||||
|
review, verify and prepare a commit boundary.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- piker/data/feed.py`
|
||||||
|
|
||||||
|
Changed `maybe_open_feed()` so the cached `Feed` exclusively owns provider
|
||||||
|
root streams and every caller, including the first cache owner, receives a
|
||||||
|
caller-local `Feed`/`Flume` view backed by one child subscription per provider.
|
||||||
|
The cache identity now includes normalized full symbol shape and stream policy.
|
||||||
|
|
||||||
|
Changed `Feed.open_multi_stream()` so every provider relay subscribes instead
|
||||||
|
of directly consuming a shared stream, and synchronizes relay startup before
|
||||||
|
yielding the merged channel. Each relay owns a cloned send channel so one
|
||||||
|
provider EOC cannot terminate its siblings. The module-level relay returns its
|
||||||
|
live child receiver through `TaskStatus` for typed retention and introspection.
|
||||||
|
Documented `Feed.pause()`/`Feed.resume()` as provider-context-wide controls
|
||||||
|
shared by local cache users.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- tests/test_feed_broadcast.py`
|
||||||
|
|
||||||
|
Added real `Feed`, `Flume`, and Tractor broadcast regressions covering both
|
||||||
|
cache-miss owner and cache-hit paths, one-provider-many-market mapping,
|
||||||
|
multi-provider relay fan-out and startup, duplex controls, lexical child
|
||||||
|
closure, sibling survival after provider EOC, cached-root immutability, and
|
||||||
|
full cache-key differentiation.
|
||||||
|
|
||||||
|
Verification output:
|
||||||
|
|
||||||
|
```text
|
||||||
|
... [100%]
|
||||||
|
3 passed in 0.02s
|
||||||
|
|
||||||
|
. [100%]
|
||||||
|
1 passed in 0.01s
|
||||||
|
```
|
||||||
|
|
||||||
|
The second result is the existing EMS broadcast ownership regression. Ruff,
|
||||||
|
E501, compilation and whitespace checks passed. Repeated adversarial review
|
||||||
|
found and resolved shared `Feed.streams`, incomplete cache-key, fake-lifecycle,
|
||||||
|
relay-startup and first-owner asymmetry issues; final review reported no
|
||||||
|
findings.
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
session: unavailable
|
||||||
|
timestamp: 2026-08-13T23:07:44Z
|
||||||
|
git_ref: ddac3553
|
||||||
|
scope: code
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20260813T230744Z_ddac3553_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
Continue the piker broadcast-consumer audit after the Deribit ownership commit
|
||||||
|
and prepare the next smallest ownership fix.
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Replaced IB's manual raw quote-channel registry with a symbol-keyed cached
|
||||||
|
context and gave every caller a lexical child from one retained
|
||||||
|
`LinkedTaskChannel` broadcaster root.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- `piker/brokers/ib/feed.py` - cached raw-channel lifetime and lexical child
|
||||||
|
ownership.
|
||||||
|
- `tests/test_ib_broadcast.py` - concurrent fan-out, cache-key and child
|
||||||
|
lifetime regression.
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
None - generated output follows the requested broadcast-consumer audit.
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
timestamp: 2026-08-13T23:07:44Z
|
||||||
|
git_ref: ddac3553
|
||||||
|
diff_cmd: git diff HEAD~1..HEAD
|
||||||
|
---
|
||||||
|
|
||||||
|
The user asked to continue the piker broadcast-consumer audit after committing
|
||||||
|
the Deribit ownership fix. The next isolated item was IB's actor-local
|
||||||
|
`_quote_streams` cache, which retained a raw channel owned by its first caller
|
||||||
|
and constructed competing broadcaster roots for later callers.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- piker/brokers/ib/feed.py`
|
||||||
|
|
||||||
|
Factored `_open_aio_quote_channel()` as the raw asyncio-channel context and
|
||||||
|
made `open_aio_quote_stream()` cache that context by symbol through
|
||||||
|
`maybe_open_context()`. Every caller now receives a lexical child from the
|
||||||
|
retained `LinkedTaskChannel` broadcaster, while the raw source remains alive
|
||||||
|
until its final cache user exits. Removed the manual `_quote_streams` registry
|
||||||
|
and teardown mutation.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- tests/test_ib_broadcast.py`
|
||||||
|
|
||||||
|
Added a concurrent ownership regression using real Tractor broadcast state.
|
||||||
|
It proves miss and hit callers use the same symbol/context factory, receive the
|
||||||
|
same quote through distinct children, close independently, and leave the owner
|
||||||
|
live after the hit exits.
|
||||||
|
|
||||||
|
Verification output:
|
||||||
|
|
||||||
|
```text
|
||||||
|
. [100%]
|
||||||
|
1 passed in 0.01s
|
||||||
|
```
|
||||||
|
|
||||||
|
The new test passes through a source-isolated IB feed import. Test Ruff, E501,
|
||||||
|
Python compilation and whitespace checks pass. Normal package collection
|
||||||
|
remains blocked by the existing Qt environment mismatch.
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
---
|
||||||
|
model: gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
session: tractor-addr-unpacking
|
||||||
|
timestamp: 2026-08-20T16:35:19Z
|
||||||
|
git_ref: 5f631e19
|
||||||
|
scope: code
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20260820T163519Z_5f631e19_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
The human asked to implement the Piker compatibility work caused by
|
||||||
|
tractor's canonical tagged-address migration, run the previously
|
||||||
|
deferred tractor verification, and keep runtime-managed WireGuard
|
||||||
|
bindspaces in a later separate PR.
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Made Piker normalize legacy and tagged registry inputs before semantic
|
||||||
|
comparison and process-global storage. Updated runtime address typing and
|
||||||
|
test assertions for canonical output, retained legacy caller input, and
|
||||||
|
removed a duplicate pytest log-level option that blocked downstream test
|
||||||
|
collection with current tractor.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- `piker/service/_registry.py` - canonical registry normalization and
|
||||||
|
shared address typing.
|
||||||
|
- `piker/service/_actor_runtime.py` - tagged-compatible runtime API
|
||||||
|
annotations.
|
||||||
|
- `tests/conftest.py` - canonical fixture comparison and shared pytest
|
||||||
|
option ownership.
|
||||||
|
- `tests/test_services.py` - registry regression and canonical runtime
|
||||||
|
assertions.
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
The human explicitly requested the downstream implementation and chose
|
||||||
|
to keep WireGuard bindspace lifecycle work in a separate future tractor
|
||||||
|
PR. The agent implemented and tested those directions; no direct manual
|
||||||
|
source edits were observed.
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
model: gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
timestamp: 2026-08-20T16:35:19Z
|
||||||
|
git_ref: 5f631e19
|
||||||
|
diff_cmd: git diff HEAD~1..HEAD
|
||||||
|
---
|
||||||
|
|
||||||
|
# Raw output - tractor tagged-address compatibility
|
||||||
|
|
||||||
|
The human requested downstream Piker qualification after tractor PR
|
||||||
|
#505 switched transport address emission to canonical tagged tuples.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- piker/service/_registry.py piker/service/_actor_runtime.py tests/conftest.py tests/test_services.py`
|
||||||
|
|
||||||
|
Normalized legacy and tagged registry addresses through tractor's
|
||||||
|
address codec before Piker stores or compares them. Extended service
|
||||||
|
runtime annotations to cover both tuple shapes, updated runtime tests to
|
||||||
|
compare canonical serialized values, and removed Piker's duplicate
|
||||||
|
registration of tractor's shared `--ll` pytest option.
|
||||||
|
|
||||||
|
Ruff passed. The focused normalization regression and Piker runtime boot
|
||||||
|
passed against the local tractor checkout at `5d92595f`. The wider
|
||||||
|
service module reached an unrelated pre-existing logger-name assertion
|
||||||
|
in `maybe_spawn_daemon()` after both address-focused tests passed.
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
---
|
||||||
|
model: gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
session: tractor-addr-unpacking
|
||||||
|
timestamp: 2026-08-21T04:20:58Z
|
||||||
|
git_ref: b7aca4c0
|
||||||
|
scope: code
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20260821T042058Z_b7aca4c0_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
The human approved refining Piker's logger-name handling after the
|
||||||
|
wider service test exposed a stale parent-logger assertion during the
|
||||||
|
tractor tagged-address compatibility work.
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Changed Piker's logger helpers to remove only an exact `piker.` prefix,
|
||||||
|
preserving complete requested submodule names. Removed daemon startup
|
||||||
|
assertions that incorrectly required parent logger names and added a
|
||||||
|
regression covering both logger factories and names that the old
|
||||||
|
character-set stripping silently corrupted.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- `piker/log.py` - exact relative logger-name derivation.
|
||||||
|
- `piker/service/_daemon.py` - remove stale parent-name assertion.
|
||||||
|
- `piker/data/_daemon.py` - remove stale parent-name assertion.
|
||||||
|
- `piker/brokers/_daemon.py` - remove stale parent-name assertion.
|
||||||
|
- `piker/clearing/_ems.py` - remove redundant logger assertion.
|
||||||
|
- `tests/test_logging.py` - package logger namespace regressions.
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
The human explicitly approved this follow-up after reviewing the
|
||||||
|
residual Piker service-suite gap. The agent implemented and verified
|
||||||
|
the refinement; no direct manual source edits were observed.
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
---
|
||||||
|
model: gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
timestamp: 2026-08-21T04:20:58Z
|
||||||
|
git_ref: b7aca4c0
|
||||||
|
diff_cmd: git diff HEAD~1..HEAD
|
||||||
|
---
|
||||||
|
|
||||||
|
# Raw output - preserve Piker logger namespaces
|
||||||
|
|
||||||
|
The human approved a follow-up refinement after the full Piker service
|
||||||
|
module exposed a stale logger-name assertion while qualifying tractor
|
||||||
|
PR #505.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- piker/log.py piker/service/_daemon.py piker/data/_daemon.py piker/brokers/_daemon.py piker/clearing/_ems.py tests/test_logging.py`
|
||||||
|
|
||||||
|
Replaced character-set `str.lstrip()` calls with exact package-prefix
|
||||||
|
removal, removed assertion-only parent-logger expectations from daemon
|
||||||
|
startup paths, and added regression coverage for both logger factories
|
||||||
|
and prefix-sensitive submodule names.
|
||||||
|
|
||||||
|
Ruff passed after removing newly unused logger assignments. All four
|
||||||
|
logger regressions and all six service integration tests passed against
|
||||||
|
the local tractor PR #505 checkout.
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
session: 3e2eb8c9-6cfb-49a5-bf1a-1c0c2c2a4ddd
|
||||||
|
timestamp: 2026-08-28T20:03:52Z
|
||||||
|
git_ref: dd676857
|
||||||
|
scope: config
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20260828T200352Z_dd676857_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
Update the xonsh version used by the repository dev shell before stacking
|
||||||
|
the Binance work, while retaining the dotrc compatibility shim as an
|
||||||
|
immediate workaround for older shells.
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Raises the xonsh dependency floor to `0.24.2` and refreshes its lock entry.
|
||||||
|
The new release supports Python 3.13, handles Git alias completion natively,
|
||||||
|
and works in the updated Nix development shell.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- `pyproject.toml` - require xonsh `0.24.2` or newer.
|
||||||
|
- `uv.lock` - lock xonsh `0.24.2` wheels and source metadata.
|
||||||
|
- `ai/prompt-io/opencode/20260828T200352Z_dd676857_prompt_io.raw.md` - retain
|
||||||
|
the triggering prompt, generated configuration summary, and checks.
|
||||||
|
- `ai/prompt-io/opencode/20260828T200352Z_dd676857_prompt_io.md` - record
|
||||||
|
structured provenance for the dependency update.
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
The user identified old xonsh behavior as the root cause, reported the
|
||||||
|
separate dotrc compatibility shim, and directed that the repository update
|
||||||
|
remain a distinct flake-layer change before the Binance stack continues.
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
timestamp: 2026-08-28T20:03:52Z
|
||||||
|
git_ref: dd676857
|
||||||
|
diff_cmd: git diff HEAD~1..HEAD
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
The user traced broken multiline conflict-resolution pastes to the old
|
||||||
|
xonsh release installed by the repository dev shell. A separate dotrc
|
||||||
|
agent added a compatibility shim, and the user directed that xonsh still
|
||||||
|
be updated alongside the flake work before continuing the Binance stack.
|
||||||
|
|
||||||
|
## Generated configuration
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- pyproject.toml uv.lock`
|
||||||
|
|
||||||
|
Raises the repository's xonsh requirement from `0.22.2` to `0.24.2` and
|
||||||
|
refreshes only xonsh's locked distribution metadata. The selected release
|
||||||
|
supports Python 3.13, includes native Git-config alias completion, and fixes
|
||||||
|
Nix metadata checks.
|
||||||
|
|
||||||
|
## Verification output
|
||||||
|
|
||||||
|
- `uv lock --upgrade-package xonsh` resolves 111 packages and updates only
|
||||||
|
xonsh from `0.22.4` to `0.24.2`.
|
||||||
|
- Fresh `nix develop` replaces the worktree-local xonsh installation.
|
||||||
|
- `xonsh --version` reports `0.24.2`.
|
||||||
|
- A multi-command xonsh invocation executes Git commands successfully.
|
||||||
|
- `nix flake check --no-build` passes for `x86_64-linux`.
|
||||||
|
- `git diff --check` passes.
|
||||||
|
|
||||||
|
The existing Polars `1.36.0` lock remains unchanged despite uv reporting
|
||||||
|
that its distributions are yanked for an `unpivot` regression.
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
session: 4dc920cf-e82e-4c1e-83db-75a0a9efe82b
|
||||||
|
timestamp: 2026-09-01T23:00:43Z
|
||||||
|
git_ref: e91f41a6
|
||||||
|
scope: config
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20260901T230043Z_e91f41a6_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
Update `wkt/land_flake_update` to Tractor's restored `piker_pin` after
|
||||||
|
reusing the existing runtime compatibility commits. Keep stale
|
||||||
|
historical lock snapshots out of the final dependency state.
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Updates piker's Python and `msgspec` requirements for current Tractor,
|
||||||
|
then generates one fresh lock at Tractor `piker_pin@0d95a9e6`. The
|
||||||
|
dependency commit completes the compatibility stack already
|
||||||
|
cherry-picked onto the flake branch.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- `pyproject.toml` - require Python 3.13 and `msgspec>=0.20.0`.
|
||||||
|
- `uv.lock` - resolve Tractor `piker_pin@0d95a9e6`, `msgspec 0.21.1`,
|
||||||
|
and current transport dependencies.
|
||||||
|
- `ai/prompt-io/opencode/20260901T230043Z_e91f41a6_prompt_io.raw.md`
|
||||||
|
- preserve the prompt, generated-change summary, and resolution notes.
|
||||||
|
- `ai/prompt-io/opencode/20260901T230043Z_e91f41a6_prompt_io.md` - record
|
||||||
|
structured provenance for the dependency update.
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
The user identified that Tractor compatibility should land with the
|
||||||
|
flake update rather than the Binance patch, supplied four known source
|
||||||
|
commits, required a broader local-history audit for missing ports, and
|
||||||
|
directed a fresh lock from the restored `piker_pin` instead of replaying
|
||||||
|
historical pins.
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
timestamp: 2026-09-01T23:00:43Z
|
||||||
|
git_ref: e91f41a6
|
||||||
|
diff_cmd: git diff HEAD~1..HEAD
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
The user requested that the flake-update branch absorb the Tractor
|
||||||
|
runtime compatibility work before the Binance branch lands. They
|
||||||
|
directed reuse of existing compatibility commits, exclusion of stale
|
||||||
|
historical lock pins, and a fresh update to Tractor's restored
|
||||||
|
`piker_pin`.
|
||||||
|
|
||||||
|
## Generated changes
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- pyproject.toml`
|
||||||
|
|
||||||
|
Narrows piker support to Python 3.13 and raises the direct `msgspec`
|
||||||
|
requirement to the version family required by current Tractor.
|
||||||
|
|
||||||
|
> `git diff --cached -- uv.lock`
|
||||||
|
|
||||||
|
Relocks against Tractor `piker_pin@0d95a9e6`, `msgspec 0.21.1`, and the
|
||||||
|
current transport dependency graph while retaining the existing Xonsh
|
||||||
|
update.
|
||||||
|
|
||||||
|
## Resolution notes
|
||||||
|
|
||||||
|
- Historical lock hunks from reused commits were intentionally omitted.
|
||||||
|
- Tractor runtime compatibility remains represented by the preceding
|
||||||
|
individually preserved commits on `wkt/land_flake_update`.
|
||||||
|
- Project checks are rendered in the commit plan for human execution.
|
||||||
|
|
@ -1,8 +1,29 @@
|
||||||
[network]
|
[network]
|
||||||
|
# This Tractor pin supports one transport per actor, not mixed TCP/UDS.
|
||||||
|
# Use the single TCP endpoint shown in each list for this version.
|
||||||
|
# Mixed-transport configs need a future Tractor pin with that support.
|
||||||
pikerd = [
|
pikerd = [
|
||||||
'/ipv4/127.0.0.1/tcp/6116', # std localhost daemon-actor tree
|
# TCP localhost loopback
|
||||||
# '/uds/6116', # TODO std uds socket file
|
'/ip4/127.0.0.1/tcp/6116',
|
||||||
|
|
||||||
|
# UDS alternative: replace TCP and select the UDS transport.
|
||||||
|
# '/unix/run/user/1000/piker/pikerd.sock',
|
||||||
]
|
]
|
||||||
|
chart = [
|
||||||
|
'/ip4/127.0.0.1/tcp/3003',
|
||||||
|
# '/unix/run/user/1000/piker/chart.sock',
|
||||||
|
]
|
||||||
|
# the service-actor registry endpoint;
|
||||||
|
# other pikerd trees contact this to discover
|
||||||
|
# actors.
|
||||||
|
# XXX if absent, pikerd binds the registry
|
||||||
|
# on its own tpt_bind_addrs.
|
||||||
|
# regd = ['/ip4/127.0.0.1/tcp/6116']
|
||||||
|
|
||||||
|
# chart = [
|
||||||
|
# '/ip4/127.0.0.1/tcp/3333',
|
||||||
|
# '/unix/run/user/1000/piker/chart@3333.sock',
|
||||||
|
# ]
|
||||||
|
|
||||||
|
|
||||||
[ui]
|
[ui]
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1765779637,
|
"lastModified": 1784497964,
|
||||||
"narHash": "sha256-KJ2wa/BLSrTqDjbfyNx70ov/HdgNBCBBSQP3BIzKnv4=",
|
"narHash": "sha256-vlHUuqAcbcH2RKmHbPiuQzbv1pnzzavXnI62RD0bqCU=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "1306659b587dc277866c7b69eb97e5f07864d8c4",
|
"rev": "241313f4e8e508cb9b13278c2b0fa25b9ca27163",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
||||||
23
flake.nix
23
flake.nix
|
|
@ -22,12 +22,14 @@
|
||||||
|
|
||||||
# do store-path extractions
|
# do store-path extractions
|
||||||
qt6baseStorePath = lib.getLib pkgs.qt6.qtbase;
|
qt6baseStorePath = lib.getLib pkgs.qt6.qtbase;
|
||||||
|
zlibStorePath = lib.getLib pkgs.zlib;
|
||||||
# ?TODO? can remove below since manual linking not needed?
|
# ?TODO? can remove below since manual linking not needed?
|
||||||
# qt6QtWaylandStorePath = lib.getLib pkgs.qt6.qtwayland;
|
# qt6QtWaylandStorePath = lib.getLib pkgs.qt6.qtwayland;
|
||||||
|
|
||||||
# XXX NOTE XXX, for now we overlay specific pkgs via
|
# XXX NOTE XXX, for now we overlay specific pkgs via
|
||||||
# a major-version-pinned-`cpython`
|
# a major-version-pinned-`cpython`
|
||||||
cpython = "python313";
|
cpython = "python313";
|
||||||
|
python = pkgs.${cpython};
|
||||||
pypkgs = pkgs."${cpython}Packages";
|
pypkgs = pkgs."${cpython}Packages";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
@ -46,7 +48,7 @@
|
||||||
qt6.qtbase
|
qt6.qtbase
|
||||||
|
|
||||||
uv
|
uv
|
||||||
python313 # ?TODO^ how to set from `cpython` above?
|
python
|
||||||
pypkgs.pyqt6
|
pypkgs.pyqt6
|
||||||
pypkgs.pyqt6-sip
|
pypkgs.pyqt6-sip
|
||||||
pypkgs.qtpy
|
pypkgs.qtpy
|
||||||
|
|
@ -70,6 +72,7 @@
|
||||||
|
|
||||||
# link-in c++ stdlib for various AOT-ext-pkgs (numpy, etc.)
|
# link-in c++ stdlib for various AOT-ext-pkgs (numpy, etc.)
|
||||||
LD_LIBRARY_PATH="${pkgs.stdenv.cc.cc.lib}/lib:$LD_LIBRARY_PATH"
|
LD_LIBRARY_PATH="${pkgs.stdenv.cc.cc.lib}/lib:$LD_LIBRARY_PATH"
|
||||||
|
LD_LIBRARY_PATH="${zlibStorePath}/lib:$LD_LIBRARY_PATH"
|
||||||
|
|
||||||
export LD_LIBRARY_PATH
|
export LD_LIBRARY_PATH
|
||||||
|
|
||||||
|
|
@ -86,15 +89,31 @@
|
||||||
export QT_WAYLAND_SHELL_INTEGRATION="xdg-shell"
|
export QT_WAYLAND_SHELL_INTEGRATION="xdg-shell"
|
||||||
|
|
||||||
# ------ uv ------
|
# ------ uv ------
|
||||||
|
# ignore any venv inherited from an outer checkout
|
||||||
|
unset VIRTUAL_ENV
|
||||||
# - always use the ./py313/ venv-subdir
|
# - always use the ./py313/ venv-subdir
|
||||||
export UV_PROJECT_ENVIRONMENT="py313"
|
export UV_PROJECT_ENVIRONMENT="py313"
|
||||||
|
|
||||||
|
# Rebuild after a flake update changes the Nix Python closure.
|
||||||
|
venv_python="$UV_PROJECT_ENVIRONMENT/bin/python"
|
||||||
|
nix_python="$(readlink -f "${python}/bin/python3")"
|
||||||
|
if test -e "$venv_python" \
|
||||||
|
&& test "$(readlink -f "$venv_python")" != "$nix_python"
|
||||||
|
then
|
||||||
|
uv venv \
|
||||||
|
--clear \
|
||||||
|
--python "$nix_python" \
|
||||||
|
"$UV_PROJECT_ENVIRONMENT"
|
||||||
|
fi
|
||||||
|
|
||||||
# sync project-env with all extras
|
# sync project-env with all extras
|
||||||
uv sync --dev --all-extras --no-group lint
|
uv sync --dev --all-extras --no-group lint
|
||||||
|
source "$UV_PROJECT_ENVIRONMENT/bin/activate"
|
||||||
|
|
||||||
# ------ TIPS ------
|
# ------ TIPS ------
|
||||||
# NOTE, to launch the py-venv installed `xonsh` (like @goodboy)
|
# NOTE, to launch the py-venv installed `xonsh` (like @goodboy)
|
||||||
# run the `nix develop` cmd with,
|
# run the `nix develop` cmd with,
|
||||||
# >> nix develop -c uv run xonsh
|
# >> nix develop -c xonsh
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -324,10 +324,13 @@ def load_ledger(
|
||||||
ldir: Path = (
|
ldir: Path = (
|
||||||
dirpath
|
dirpath
|
||||||
or
|
or
|
||||||
config._config_dir / 'accounting' / 'ledgers'
|
config.get_conf_dir() / 'accounting' / 'ledgers'
|
||||||
)
|
)
|
||||||
if not ldir.is_dir():
|
if not ldir.is_dir():
|
||||||
ldir.mkdir()
|
ldir.mkdir(
|
||||||
|
parents=True,
|
||||||
|
exist_ok=True,
|
||||||
|
)
|
||||||
|
|
||||||
fname = f'trades_{brokername}_{acctid}.toml'
|
fname = f'trades_{brokername}_{acctid}.toml'
|
||||||
fpath: Path = ldir / fname
|
fpath: Path = ldir / fname
|
||||||
|
|
|
||||||
|
|
@ -785,9 +785,16 @@ def load_account(
|
||||||
legacy_fn: str = f'pps.{brokername}.{acctid}.toml'
|
legacy_fn: str = f'pps.{brokername}.{acctid}.toml'
|
||||||
fn: str = f'account.{brokername}.{acctid}.toml'
|
fn: str = f'account.{brokername}.{acctid}.toml'
|
||||||
|
|
||||||
dirpath: Path = dirpath or (config._config_dir / 'accounting')
|
dirpath: Path = (
|
||||||
|
dirpath
|
||||||
|
or
|
||||||
|
(config.get_conf_dir() / 'accounting')
|
||||||
|
)
|
||||||
if not dirpath.is_dir():
|
if not dirpath.is_dir():
|
||||||
dirpath.mkdir()
|
dirpath.mkdir(
|
||||||
|
parents=True,
|
||||||
|
exist_ok=True,
|
||||||
|
)
|
||||||
|
|
||||||
conf, path = config.load(
|
conf, path = config.load(
|
||||||
path=dirpath / fn,
|
path=dirpath / fn,
|
||||||
|
|
|
||||||
|
|
@ -80,12 +80,11 @@ async def _setup_persistent_brokerd(
|
||||||
# any further (level) configuration on their own B)
|
# any further (level) configuration on their own B)
|
||||||
actor: tractor.Actor = tractor.current_actor()
|
actor: tractor.Actor = tractor.current_actor()
|
||||||
tll: str = actor.loglevel
|
tll: str = actor.loglevel
|
||||||
log = get_console_log(
|
get_console_log(
|
||||||
level=loglevel or tll,
|
level=loglevel or tll,
|
||||||
name=f'{_util.subsys}.{brokername}',
|
name=f'{_util.subsys}.{brokername}',
|
||||||
with_tractor_log=bool(tll),
|
with_tractor_log=bool(tll),
|
||||||
)
|
)
|
||||||
assert log.name == _util.subsys
|
|
||||||
|
|
||||||
# further, set the log level on any broker broker specific
|
# further, set the log level on any broker broker specific
|
||||||
# logger instance.
|
# logger instance.
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,17 @@ Handy cross-broker utils.
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
# from functools import partial
|
# from functools import partial
|
||||||
|
from typing import (
|
||||||
|
Type,
|
||||||
|
)
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import httpx
|
import httpx
|
||||||
import logging
|
import logging
|
||||||
|
from msgspec import Struct
|
||||||
|
from tractor._exceptions import (
|
||||||
|
reg_err_types,
|
||||||
|
)
|
||||||
|
|
||||||
from piker.log import (
|
from piker.log import (
|
||||||
colorize_json,
|
colorize_json,
|
||||||
|
|
@ -97,6 +104,19 @@ class DataThrottle(BrokerError):
|
||||||
'''
|
'''
|
||||||
# TODO: add in throttle metrics/feedback
|
# TODO: add in throttle metrics/feedback
|
||||||
|
|
||||||
|
class SchemaMismatch(BrokerError):
|
||||||
|
'''
|
||||||
|
Market `Pair` fields mismatch, likely due to provider API update.
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
# auto-register all `BrokerError` subtypes for
|
||||||
|
# tractor IPC exc-marshalling.
|
||||||
|
reg_err_types([
|
||||||
|
BrokerError,
|
||||||
|
*BrokerError.__subclasses__(),
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
def resproc(
|
def resproc(
|
||||||
resp: httpx.Response,
|
resp: httpx.Response,
|
||||||
|
|
@ -123,3 +143,45 @@ def resproc(
|
||||||
log.debug(f"Received json contents:\n{colorize_json(msg)}")
|
log.debug(f"Received json contents:\n{colorize_json(msg)}")
|
||||||
|
|
||||||
return msg if return_json else resp
|
return msg if return_json else resp
|
||||||
|
|
||||||
|
|
||||||
|
def get_or_raise_on_pair_schema_mismatch(
|
||||||
|
pair_type: Type[Struct],
|
||||||
|
fields_data: dict,
|
||||||
|
provider_name: str,
|
||||||
|
api_url: str|None = None,
|
||||||
|
) -> Struct:
|
||||||
|
'''
|
||||||
|
Boilerplate helper around assset-`Pair` field schema mismatches,
|
||||||
|
normally due to provider API updates.
|
||||||
|
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
pair: Struct = pair_type(**fields_data)
|
||||||
|
return pair
|
||||||
|
except TypeError as err:
|
||||||
|
|
||||||
|
from tractor.devx.pformat import ppfmt
|
||||||
|
repr_data: str = ppfmt(fields_data)
|
||||||
|
report: str = (
|
||||||
|
f'Field mismatch we need to codify!\n'
|
||||||
|
f'\n'
|
||||||
|
f'{pair_type!r}({repr_data})'
|
||||||
|
f'\n'
|
||||||
|
f'^^^ {err.args[0]!r} ^^^\n'
|
||||||
|
f'\n'
|
||||||
|
f"Don't panic, prolly {provider_name!r} "
|
||||||
|
f"changed their symbology schema..\n"
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
api_url
|
||||||
|
or
|
||||||
|
(api_url := pair_type._api_url)
|
||||||
|
):
|
||||||
|
report += (
|
||||||
|
f'\n'
|
||||||
|
f'Check out their API docs here:\n'
|
||||||
|
f'{api_url}\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
raise SchemaMismatch(report) from err
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,9 @@ from piker import config
|
||||||
from piker.clearing._messages import (
|
from piker.clearing._messages import (
|
||||||
Order,
|
Order,
|
||||||
)
|
)
|
||||||
|
from piker.brokers._util import (
|
||||||
|
get_or_raise_on_pair_schema_mismatch,
|
||||||
|
)
|
||||||
from piker.accounting import (
|
from piker.accounting import (
|
||||||
Asset,
|
Asset,
|
||||||
digits_to_dec,
|
digits_to_dec,
|
||||||
|
|
@ -370,20 +373,12 @@ class Client:
|
||||||
item['filters'] = filters
|
item['filters'] = filters
|
||||||
|
|
||||||
pair_type: Type = PAIRTYPES[venue]
|
pair_type: Type = PAIRTYPES[venue]
|
||||||
try:
|
pair: Pair = get_or_raise_on_pair_schema_mismatch(
|
||||||
pair: Pair = pair_type(**item)
|
pair_type=pair_type,
|
||||||
except Exception as e:
|
fields_data=item,
|
||||||
e.add_note(
|
provider_name='binance',
|
||||||
f'\n'
|
api_url='https://binance-docs.github.io/apidocs/spot/en/#exchange-information',
|
||||||
f'New or removed field we need to codify!\n'
|
)
|
||||||
f'pair-type: {pair_type!r}\n'
|
|
||||||
f'\n'
|
|
||||||
f"Don't panic, prolly stupid binance changed their symbology schema again..\n"
|
|
||||||
f'Check out their API docs here:\n'
|
|
||||||
f'\n'
|
|
||||||
f'https://binance-docs.github.io/apidocs/spot/en/#exchange-information\n'
|
|
||||||
)
|
|
||||||
raise
|
|
||||||
pair_table[pair.symbol.upper()] = pair
|
pair_table[pair.symbol.upper()] = pair
|
||||||
|
|
||||||
# update an additional top-level-cross-venue-table
|
# update an additional top-level-cross-venue-table
|
||||||
|
|
@ -581,8 +576,8 @@ class Client:
|
||||||
self,
|
self,
|
||||||
mkt: MktPair,
|
mkt: MktPair,
|
||||||
|
|
||||||
start_dt: datetime | None = None,
|
start_dt: datetime|None = None,
|
||||||
end_dt: datetime | None = None,
|
end_dt: datetime|None = None,
|
||||||
|
|
||||||
as_np: bool = True,
|
as_np: bool = True,
|
||||||
|
|
||||||
|
|
@ -609,7 +604,11 @@ class Client:
|
||||||
start_time = binance_timestamp(start_dt)
|
start_time = binance_timestamp(start_dt)
|
||||||
end_time = binance_timestamp(end_dt)
|
end_time = binance_timestamp(end_dt)
|
||||||
|
|
||||||
bs_pair: Pair = self._pairs[mkt.bs_fqme.upper()]
|
import tractor
|
||||||
|
with tractor.devx.maybe_open_crash_handler():
|
||||||
|
bs_pair: Pair = self._pairs[
|
||||||
|
mkt.bs_fqme.upper()
|
||||||
|
]
|
||||||
|
|
||||||
# https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
|
# https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
|
||||||
bars = await self._api(
|
bars = await self._api(
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ import tractor
|
||||||
from piker.brokers import (
|
from piker.brokers import (
|
||||||
open_cached_client,
|
open_cached_client,
|
||||||
NoData,
|
NoData,
|
||||||
|
SymbolNotFound,
|
||||||
)
|
)
|
||||||
from piker._cacheables import (
|
from piker._cacheables import (
|
||||||
async_lifo_cache,
|
async_lifo_cache,
|
||||||
|
|
@ -301,6 +302,10 @@ async def get_mkt_info(
|
||||||
|
|
||||||
# uppercase since kraken bs_mktid is always upper
|
# uppercase since kraken bs_mktid is always upper
|
||||||
if 'binance' not in fqme.lower():
|
if 'binance' not in fqme.lower():
|
||||||
|
log.warning(
|
||||||
|
f'Missing `.<provider>` part in fqme ??\n'
|
||||||
|
f'fqme: {fqme!r}\n'
|
||||||
|
)
|
||||||
fqme += '.binance'
|
fqme += '.binance'
|
||||||
|
|
||||||
mkt_mode: str = ''
|
mkt_mode: str = ''
|
||||||
|
|
@ -315,6 +320,12 @@ async def get_mkt_info(
|
||||||
venue: str = venue.upper()
|
venue: str = venue.upper()
|
||||||
venue_lower: str = venue.lower()
|
venue_lower: str = venue.lower()
|
||||||
|
|
||||||
|
if not venue:
|
||||||
|
raise SymbolNotFound(
|
||||||
|
f'Invalid or missing .<venue> part in fqme?\n'
|
||||||
|
f'fqme: {fqme!r}\n'
|
||||||
|
)
|
||||||
|
|
||||||
# XXX TODO: we should change the usdtm_futes name to just
|
# XXX TODO: we should change the usdtm_futes name to just
|
||||||
# usdm_futes (dropping the tether part) since it turns out that
|
# usdm_futes (dropping the tether part) since it turns out that
|
||||||
# there are indeed USD-tokens OTHER THEN tether being used as
|
# there are indeed USD-tokens OTHER THEN tether being used as
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ Per market data-type definitions and schemas types.
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from typing import (
|
from typing import (
|
||||||
|
ClassVar,
|
||||||
Literal,
|
Literal,
|
||||||
)
|
)
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
@ -203,6 +204,8 @@ class FutesPair(Pair):
|
||||||
# NOTE: see `.data._symcache.SymbologyCache.load()` for why
|
# NOTE: see `.data._symcache.SymbologyCache.load()` for why
|
||||||
ns_path: str = 'piker.brokers.binance:FutesPair'
|
ns_path: str = 'piker.brokers.binance:FutesPair'
|
||||||
|
|
||||||
|
_api_url: ClassVar[str] = 'https://binance-docs.github.io/apidocs/spot/en/#exchange-information'
|
||||||
|
|
||||||
# NOTE: for compat with spot pairs and `MktPair.src: Asset`
|
# NOTE: for compat with spot pairs and `MktPair.src: Asset`
|
||||||
# processing..
|
# processing..
|
||||||
@property
|
@property
|
||||||
|
|
|
||||||
|
|
@ -425,7 +425,7 @@ class DataFeed:
|
||||||
async def stream_to_file(
|
async def stream_to_file(
|
||||||
watchlist_name: str,
|
watchlist_name: str,
|
||||||
filename: str,
|
filename: str,
|
||||||
portal: tractor._portal.Portal,
|
portal: tractor.Portal,
|
||||||
tickers: List[str],
|
tickers: List[str],
|
||||||
brokermod: ModuleType,
|
brokermod: ModuleType,
|
||||||
rate: int,
|
rate: int,
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ from contextlib import (
|
||||||
asynccontextmanager as acm,
|
asynccontextmanager as acm,
|
||||||
)
|
)
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from functools import partial
|
|
||||||
import time
|
import time
|
||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
|
|
@ -38,7 +37,7 @@ from rapidfuzz import process as fuzzy
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from tractor.trionics import (
|
from tractor.trionics import (
|
||||||
broadcast_receiver,
|
broadcast_receiver,
|
||||||
maybe_open_context
|
maybe_open_context,
|
||||||
collapse_eg,
|
collapse_eg,
|
||||||
)
|
)
|
||||||
from tractor import to_asyncio
|
from tractor import to_asyncio
|
||||||
|
|
@ -524,13 +523,12 @@ async def maybe_open_feed_handler() -> trio.abc.ReceiveStream:
|
||||||
|
|
||||||
|
|
||||||
async def aio_price_feed_relay(
|
async def aio_price_feed_relay(
|
||||||
|
chan: to_asyncio.LinkedTaskChannel,
|
||||||
fh: FeedHandler,
|
fh: FeedHandler,
|
||||||
instrument: Symbol,
|
instrument: Symbol,
|
||||||
from_trio: asyncio.Queue,
|
|
||||||
to_trio: trio.abc.SendChannel,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
async def _trade(data: dict, receipt_timestamp):
|
async def _trade(data: dict, receipt_timestamp):
|
||||||
to_trio.send_nowait(('trade', {
|
chan.send_nowait(('trade', {
|
||||||
'symbol': cb_sym_to_deribit_inst(
|
'symbol': cb_sym_to_deribit_inst(
|
||||||
str_to_cb_sym(data.symbol)).lower(),
|
str_to_cb_sym(data.symbol)).lower(),
|
||||||
'last': data,
|
'last': data,
|
||||||
|
|
@ -540,7 +538,7 @@ async def aio_price_feed_relay(
|
||||||
}))
|
}))
|
||||||
|
|
||||||
async def _l1(data: dict, receipt_timestamp):
|
async def _l1(data: dict, receipt_timestamp):
|
||||||
to_trio.send_nowait(('l1', {
|
chan.send_nowait(('l1', {
|
||||||
'symbol': cb_sym_to_deribit_inst(
|
'symbol': cb_sym_to_deribit_inst(
|
||||||
str_to_cb_sym(data.symbol)).lower(),
|
str_to_cb_sym(data.symbol)).lower(),
|
||||||
'ticks': [
|
'ticks': [
|
||||||
|
|
@ -570,7 +568,7 @@ async def aio_price_feed_relay(
|
||||||
install_signal_handlers=False)
|
install_signal_handlers=False)
|
||||||
|
|
||||||
# sync with trio
|
# sync with trio
|
||||||
to_trio.send_nowait(None)
|
chan.started_nowait(None)
|
||||||
|
|
||||||
await asyncio.sleep(float('inf'))
|
await asyncio.sleep(float('inf'))
|
||||||
|
|
||||||
|
|
@ -581,11 +579,9 @@ async def open_price_feed(
|
||||||
) -> trio.abc.ReceiveStream:
|
) -> trio.abc.ReceiveStream:
|
||||||
async with maybe_open_feed_handler() as fh:
|
async with maybe_open_feed_handler() as fh:
|
||||||
async with to_asyncio.open_channel_from(
|
async with to_asyncio.open_channel_from(
|
||||||
partial(
|
aio_price_feed_relay,
|
||||||
aio_price_feed_relay,
|
fh=fh,
|
||||||
fh,
|
instrument=instrument,
|
||||||
instrument
|
|
||||||
)
|
|
||||||
) as (chan, first):
|
) as (chan, first):
|
||||||
yield chan
|
yield chan
|
||||||
|
|
||||||
|
|
@ -611,10 +607,9 @@ async def maybe_open_price_feed(
|
||||||
|
|
||||||
|
|
||||||
async def aio_order_feed_relay(
|
async def aio_order_feed_relay(
|
||||||
|
chan: to_asyncio.LinkedTaskChannel,
|
||||||
fh: FeedHandler,
|
fh: FeedHandler,
|
||||||
instrument: Symbol,
|
instrument: Symbol,
|
||||||
from_trio: asyncio.Queue,
|
|
||||||
to_trio: trio.abc.SendChannel,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
async def _fill(data: dict, receipt_timestamp):
|
async def _fill(data: dict, receipt_timestamp):
|
||||||
breakpoint()
|
breakpoint()
|
||||||
|
|
@ -637,7 +632,7 @@ async def aio_order_feed_relay(
|
||||||
install_signal_handlers=False)
|
install_signal_handlers=False)
|
||||||
|
|
||||||
# sync with trio
|
# sync with trio
|
||||||
to_trio.send_nowait(None)
|
chan.started_nowait(None)
|
||||||
|
|
||||||
await asyncio.sleep(float('inf'))
|
await asyncio.sleep(float('inf'))
|
||||||
|
|
||||||
|
|
@ -648,11 +643,9 @@ async def open_order_feed(
|
||||||
) -> trio.abc.ReceiveStream:
|
) -> trio.abc.ReceiveStream:
|
||||||
async with maybe_open_feed_handler() as fh:
|
async with maybe_open_feed_handler() as fh:
|
||||||
async with to_asyncio.open_channel_from(
|
async with to_asyncio.open_channel_from(
|
||||||
partial(
|
aio_order_feed_relay,
|
||||||
aio_order_feed_relay,
|
fh=fh,
|
||||||
fh,
|
instrument=instrument,
|
||||||
instrument
|
|
||||||
)
|
|
||||||
) as (chan, first):
|
) as (chan, first):
|
||||||
yield chan
|
yield chan
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1584,6 +1584,72 @@ class MethodProxy:
|
||||||
self.event_table = event_table
|
self.event_table = event_table
|
||||||
self._aio_ns = asyncio_ns
|
self._aio_ns = asyncio_ns
|
||||||
|
|
||||||
|
# request-id counter for correlating each method
|
||||||
|
# call to its (eventual) response; necessary since
|
||||||
|
# the (single, shared) chan has NO other ordering
|
||||||
|
# guarantee whenever a caller task is CANCELLED
|
||||||
|
# (eg. by a search-req timeout) after sending its
|
||||||
|
# request but before consuming the response: the
|
||||||
|
# "orphaned" response otherwise gets mis-delivered
|
||||||
|
# to the next caller causing an off-by-one skew of
|
||||||
|
# every result thereafter!
|
||||||
|
self._mids = itertools.count()
|
||||||
|
self._pending: dict[
|
||||||
|
int,
|
||||||
|
tuple[trio.Event, list[dict]],
|
||||||
|
] = {}
|
||||||
|
self._request_methods: dict[int, str|None] = {}
|
||||||
|
|
||||||
|
def _deliver_method_response(
|
||||||
|
self,
|
||||||
|
msg: dict,
|
||||||
|
|
||||||
|
) -> bool:
|
||||||
|
'''
|
||||||
|
Deliver one correlated response to its waiting caller.
|
||||||
|
|
||||||
|
'''
|
||||||
|
mid: int = msg['mid']
|
||||||
|
meth: str|None = self._request_methods.pop(mid, None)
|
||||||
|
pending = self._pending.get(mid)
|
||||||
|
if pending is None:
|
||||||
|
log.warning(
|
||||||
|
f'Dropping stale method-resp,\n'
|
||||||
|
f'mid: {mid}\n'
|
||||||
|
f'meth: {meth!r}\n'
|
||||||
|
f'(caller prolly got cancelled '
|
||||||
|
f'before its resp?)\n'
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
event, slot = pending
|
||||||
|
slot.append(msg)
|
||||||
|
event.set()
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _track_request_method(
|
||||||
|
self,
|
||||||
|
mid: int,
|
||||||
|
meth: str|None,
|
||||||
|
|
||||||
|
) -> None:
|
||||||
|
'''
|
||||||
|
Retain bounded request metadata for stale-response logs.
|
||||||
|
|
||||||
|
'''
|
||||||
|
self._request_methods[mid] = meth
|
||||||
|
if len(self._request_methods) > 256:
|
||||||
|
oldest_mid: int = next(iter(self._request_methods))
|
||||||
|
oldest_meth: str|None = self._request_methods.pop(
|
||||||
|
oldest_mid
|
||||||
|
)
|
||||||
|
log.warning(
|
||||||
|
f'Evicting unresolved method-request metadata,\n'
|
||||||
|
f'mid: {oldest_mid}\n'
|
||||||
|
f'meth: {oldest_meth!r}\n'
|
||||||
|
f'pending metadata limit: 256\n'
|
||||||
|
)
|
||||||
|
|
||||||
async def _run_method(
|
async def _run_method(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|
@ -1596,38 +1662,30 @@ class MethodProxy:
|
||||||
``tractor.to_asyncio`` layer.
|
``tractor.to_asyncio`` layer.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
chan = self.chan
|
mid: int = next(self._mids)
|
||||||
await chan.send((meth, kwargs))
|
event = trio.Event()
|
||||||
|
slot: list[dict] = []
|
||||||
|
self._pending[mid] = event, slot
|
||||||
|
self._track_request_method(mid, meth)
|
||||||
|
try:
|
||||||
|
await self.chan.send((meth, kwargs, mid))
|
||||||
|
await event.wait()
|
||||||
|
finally:
|
||||||
|
self._pending.pop(mid, None)
|
||||||
|
|
||||||
while not chan.closed():
|
msg: dict = slot[0]
|
||||||
# send through method + ``kwargs: dict`` as pair
|
match msg:
|
||||||
msg = await chan.receive()
|
# OUR method-call response B)
|
||||||
|
case {'result': res}:
|
||||||
# TODO: implement reconnect functionality like
|
|
||||||
# in our `.data._web_bs.NoBsWs`
|
|
||||||
# try:
|
|
||||||
# msg = await chan.receive()
|
|
||||||
# except ConnectionError:
|
|
||||||
# self.reset()
|
|
||||||
|
|
||||||
# print(f'NEXT MSG: {msg}')
|
|
||||||
|
|
||||||
# TODO: py3.10 ``match:`` syntax B)
|
|
||||||
if 'result' in msg:
|
|
||||||
res = msg.get('result')
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
elif 'exception' in msg:
|
case {'exception': err}:
|
||||||
err = msg.get('exception')
|
|
||||||
raise err
|
raise err
|
||||||
|
|
||||||
elif 'error' in msg:
|
case _:
|
||||||
etype, emsg = msg
|
raise RuntimeError(
|
||||||
log.warning(f'IB error relay: {emsg}')
|
f'Invalid method response for mid={mid}: {msg!r}'
|
||||||
continue
|
)
|
||||||
|
|
||||||
else:
|
|
||||||
log.warning(f'UNKNOWN IB MSG: {msg}')
|
|
||||||
|
|
||||||
def status_event(
|
def status_event(
|
||||||
self,
|
self,
|
||||||
|
|
@ -1680,22 +1738,31 @@ async def open_aio_client_method_relay(
|
||||||
log.info('asyncio `Client` method-proxy SHUTDOWN!')
|
log.info('asyncio `Client` method-proxy SHUTDOWN!')
|
||||||
break
|
break
|
||||||
|
|
||||||
case (meth_name, kwargs):
|
case (meth_name, kwargs, mid):
|
||||||
meth_name, kwargs = msg
|
|
||||||
meth = getattr(client, meth_name)
|
meth = getattr(client, meth_name)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
resp = await meth(**kwargs)
|
resp = await meth(**kwargs)
|
||||||
# echo the msg back
|
# echo the msg back tagged with the
|
||||||
chan.send_nowait({'result': resp})
|
# req-id for caller-side correlation.
|
||||||
|
chan.send_nowait({
|
||||||
|
'mid': mid,
|
||||||
|
'result': resp,
|
||||||
|
})
|
||||||
|
|
||||||
except (
|
# XXX: relay ALL (non-cancel) errors to the
|
||||||
RequestError,
|
# `trio`-side caller (which re-raises in the
|
||||||
|
# `MethodProxy._run_method()` frame) instead
|
||||||
# TODO: relay all errors to trio?
|
# of crashing this relay task and thus the
|
||||||
# BaseException,
|
# whole proxy/dialog; critical post the
|
||||||
) as err:
|
# (datad|brokerd)-split where eg. contract
|
||||||
chan.send_nowait({'exception': err})
|
# qualification failures are expected to be
|
||||||
|
# caught per-request by order/warmup code!
|
||||||
|
except Exception as err:
|
||||||
|
chan.send_nowait({
|
||||||
|
'mid': mid,
|
||||||
|
'exception': err,
|
||||||
|
})
|
||||||
|
|
||||||
case {'error': content}:
|
case {'error': content}:
|
||||||
chan.send_nowait({'exception': content})
|
chan.send_nowait({'exception': content})
|
||||||
|
|
@ -1704,6 +1771,73 @@ async def open_aio_client_method_relay(
|
||||||
raise ValueError(f'Unhandled msg {msg}')
|
raise ValueError(f'Unhandled msg {msg}')
|
||||||
|
|
||||||
|
|
||||||
|
async def relay_client_proxy_messages(
|
||||||
|
chan: tractor.to_asyncio.LinkedTaskChannel,
|
||||||
|
proxy: MethodProxy,
|
||||||
|
|
||||||
|
) -> None:
|
||||||
|
'''
|
||||||
|
Route one proxy's asyncio-client msgs from a single reader.
|
||||||
|
|
||||||
|
Each `open_client_proxy()` allocates its own linked channel and
|
||||||
|
starts this task in its relay nursery. Any number of Trio caller
|
||||||
|
tasks may concurrently write tagged requests through
|
||||||
|
`MethodProxy._run_method()` and wait on their per-`mid` slots.
|
||||||
|
This task alone reads the channel and dispatches each response to
|
||||||
|
its waiting caller.
|
||||||
|
|
||||||
|
Separate proxy contexts own separate channels and reader tasks;
|
||||||
|
no cross-proxy response broadcast is intended. IB status events
|
||||||
|
still reach each proxy through its own `Client.inline_errors()`
|
||||||
|
handler.
|
||||||
|
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
while not chan.closed():
|
||||||
|
# TODO: implement reconnect functionality like
|
||||||
|
# in our `.data._web_bs.NoBsWs`
|
||||||
|
# try:
|
||||||
|
msg = await chan.receive()
|
||||||
|
# except ConnectionError:
|
||||||
|
# proxy.reset()
|
||||||
|
|
||||||
|
match msg:
|
||||||
|
# Correlated response from a method call.
|
||||||
|
case {'mid': _}:
|
||||||
|
proxy._deliver_method_response(msg)
|
||||||
|
|
||||||
|
# routine (api-farm conn) status events
|
||||||
|
# relayed inline by `Client.inline_errors()`;
|
||||||
|
# not a response to a method call so just
|
||||||
|
# log at info and keep waiting.
|
||||||
|
case ('event', status_msg):
|
||||||
|
reason = status_msg['reason']
|
||||||
|
event = proxy.event_table.pop(reason, None)
|
||||||
|
if (
|
||||||
|
event
|
||||||
|
and
|
||||||
|
event.statistics().tasks_waiting
|
||||||
|
):
|
||||||
|
log.info(f'Relaying ib status message: {msg}')
|
||||||
|
event.set()
|
||||||
|
|
||||||
|
# Inline API error with no request correlation.
|
||||||
|
case ('error', emsg):
|
||||||
|
log.warning(f'IB error relay: {emsg}')
|
||||||
|
|
||||||
|
# Out-of-band client error with no method `mid`.
|
||||||
|
case {'exception': err}:
|
||||||
|
log.error(
|
||||||
|
f'Uncorrelated IB client error: {err!r}'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Preserve visibility into unexpected relay traffic.
|
||||||
|
case _:
|
||||||
|
log.warning(f'UNKNOWN IB MSG: {msg}')
|
||||||
|
except trio.EndOfChannel:
|
||||||
|
log.info('IB client proxy relay closed')
|
||||||
|
|
||||||
|
|
||||||
@acm
|
@acm
|
||||||
async def open_client_proxy(
|
async def open_client_proxy(
|
||||||
client: Client,
|
client: Client,
|
||||||
|
|
@ -1740,28 +1874,11 @@ async def open_client_proxy(
|
||||||
continue
|
continue
|
||||||
setattr(proxy, name, partial(proxy._run_method, meth=name))
|
setattr(proxy, name, partial(proxy._run_method, meth=name))
|
||||||
|
|
||||||
async def relay_events():
|
relay_tn.start_soon(
|
||||||
|
relay_client_proxy_messages,
|
||||||
async with chan.subscribe() as msg_stream:
|
chan,
|
||||||
|
proxy,
|
||||||
async for msg in msg_stream:
|
)
|
||||||
if 'event' not in msg:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# if 'event' in msg:
|
|
||||||
# wake up any system event waiters.
|
|
||||||
etype, status_msg = msg
|
|
||||||
reason = status_msg['reason']
|
|
||||||
|
|
||||||
ev = proxy.event_table.pop(reason, None)
|
|
||||||
|
|
||||||
if ev and ev.statistics().tasks_waiting:
|
|
||||||
log.info(f'Relaying ib status message: {msg}')
|
|
||||||
ev.set()
|
|
||||||
|
|
||||||
continue
|
|
||||||
|
|
||||||
relay_tn.start_soon(relay_events)
|
|
||||||
|
|
||||||
yield proxy
|
yield proxy
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -231,20 +231,21 @@ async def handle_order_requests(
|
||||||
|
|
||||||
async def recv_trade_updates(
|
async def recv_trade_updates(
|
||||||
|
|
||||||
|
chan: tractor.to_asyncio.LinkedTaskChannel,
|
||||||
client: Client,
|
client: Client,
|
||||||
to_trio: trio.abc.SendChannel,
|
|
||||||
|
|
||||||
) -> None:
|
) -> None:
|
||||||
'''
|
'''
|
||||||
Receive and relay order control and positioning related events
|
Receive and relay order control and positioning
|
||||||
from `ib_async`, pack as tuples and push over mem-chan to our
|
related events from `ib_async`, pack as tuples and
|
||||||
trio relay task for processing and relay to EMS.
|
push over mem-chan to our trio relay task for
|
||||||
|
processing and relay to EMS.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
client.inline_errors(to_trio)
|
client.inline_errors(chan)
|
||||||
|
|
||||||
# sync with trio task
|
# sync with trio task
|
||||||
to_trio.send_nowait(client.ib)
|
chan.started_nowait(client.ib)
|
||||||
|
|
||||||
def push_tradesies(
|
def push_tradesies(
|
||||||
eventkit_obj,
|
eventkit_obj,
|
||||||
|
|
@ -282,7 +283,7 @@ async def recv_trade_updates(
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# emit event name + relevant ibis internal objects
|
# emit event name + relevant ibis internal objects
|
||||||
to_trio.send_nowait((event_name, emit))
|
chan.send_nowait((event_name, emit))
|
||||||
except trio.BrokenResourceError:
|
except trio.BrokenResourceError:
|
||||||
log.exception(f'Disconnected from {eventkit_obj} updates')
|
log.exception(f'Disconnected from {eventkit_obj} updates')
|
||||||
eventkit_obj.disconnect(push_tradesies)
|
eventkit_obj.disconnect(push_tradesies)
|
||||||
|
|
|
||||||
|
|
@ -738,10 +738,6 @@ async def get_bars(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# per-actor cache of inter-eventloop-chans
|
|
||||||
_quote_streams: dict[str, trio.abc.ReceiveStream] = {}
|
|
||||||
|
|
||||||
|
|
||||||
async def _setup_quote_stream(
|
async def _setup_quote_stream(
|
||||||
chan: tractor.to_asyncio.LinkedTaskChannel,
|
chan: tractor.to_asyncio.LinkedTaskChannel,
|
||||||
symbol: str,
|
symbol: str,
|
||||||
|
|
@ -770,8 +766,6 @@ async def _setup_quote_stream(
|
||||||
and is thus run via `tractor.to_asyncio.open_channel_from()`.
|
and is thus run via `tractor.to_asyncio.open_channel_from()`.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
global _quote_streams
|
|
||||||
|
|
||||||
async with load_aio_clients(
|
async with load_aio_clients(
|
||||||
disconnect_on_exit=False,
|
disconnect_on_exit=False,
|
||||||
) as accts2clients:
|
) as accts2clients:
|
||||||
|
|
@ -834,9 +828,6 @@ async def _setup_quote_stream(
|
||||||
|
|
||||||
client.ib.cancelMktData(contract)
|
client.ib.cancelMktData(contract)
|
||||||
|
|
||||||
# decouple broadcast mem chan
|
|
||||||
_quote_streams.pop(symbol, None)
|
|
||||||
|
|
||||||
def push(
|
def push(
|
||||||
t: Ticker,
|
t: Ticker,
|
||||||
tries_before_raise: int = 6,
|
tries_before_raise: int = 6,
|
||||||
|
|
@ -953,54 +944,52 @@ async def _setup_quote_stream(
|
||||||
|
|
||||||
|
|
||||||
@acm
|
@acm
|
||||||
async def open_aio_quote_stream(
|
async def _open_aio_quote_channel(
|
||||||
symbol: str,
|
symbol: str,
|
||||||
contract: Contract|None = None,
|
contract: Contract|None = None,
|
||||||
|
|
||||||
) -> (
|
) -> tractor.to_asyncio.LinkedTaskChannel:
|
||||||
trio.abc.Channel| # iface
|
|
||||||
tractor.to_asyncio.LinkedTaskChannel # actually
|
|
||||||
):
|
|
||||||
'''
|
'''
|
||||||
Open a real-time `Ticker` quote stream from an `asyncio.Task`
|
Open one raw inter-event-loop quote channel for `symbol`.
|
||||||
spawned via `tractor.to_asyncio.open_channel_from()`, deliver the
|
|
||||||
inter-event-loop channel to the `trio.Task` caller and cache it
|
|
||||||
globally for re-use.
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
from tractor.trionics import broadcast_receiver
|
chan: tractor.to_asyncio.LinkedTaskChannel
|
||||||
global _quote_streams
|
started_contract: Contract
|
||||||
|
|
||||||
from_aio = _quote_streams.get(symbol)
|
|
||||||
if from_aio:
|
|
||||||
|
|
||||||
# if we already have a cached feed deliver a rx side clone
|
|
||||||
# to consumer
|
|
||||||
async with broadcast_receiver(
|
|
||||||
from_aio,
|
|
||||||
2**6,
|
|
||||||
) as from_aio:
|
|
||||||
yield from_aio
|
|
||||||
return
|
|
||||||
|
|
||||||
from_aio: tractor.to_asyncio.LinkedTaskChannel
|
|
||||||
async with tractor.to_asyncio.open_channel_from(
|
async with tractor.to_asyncio.open_channel_from(
|
||||||
_setup_quote_stream,
|
_setup_quote_stream,
|
||||||
symbol=symbol,
|
symbol=symbol,
|
||||||
contract=contract,
|
contract=contract,
|
||||||
|
|
||||||
) as (from_aio, contract):
|
) as (chan, started_contract):
|
||||||
|
assert started_contract
|
||||||
|
yield chan
|
||||||
|
|
||||||
assert contract
|
|
||||||
|
|
||||||
# TODO? de-reg on teardown of last consumer task?
|
@acm
|
||||||
# -> why aren't we using `.trionics.maybe_open_context()`
|
async def open_aio_quote_stream(
|
||||||
# here again?? (we are in `open_client_proxies()` tho?)
|
symbol: str,
|
||||||
#
|
contract: Contract|None = None,
|
||||||
# cache feed for later consumers
|
|
||||||
_quote_streams[symbol] = from_aio
|
|
||||||
|
|
||||||
yield from_aio
|
) -> tractor.trionics.BroadcastReceiver:
|
||||||
|
'''
|
||||||
|
Open a caller-owned child of the cached quote channel for `symbol`.
|
||||||
|
|
||||||
|
Keep the raw `LinkedTaskChannel` alive until its last cache user
|
||||||
|
exits, and retain exactly one broadcaster root on that channel.
|
||||||
|
|
||||||
|
'''
|
||||||
|
chan: tractor.to_asyncio.LinkedTaskChannel
|
||||||
|
async with tractor.trionics.maybe_open_context(
|
||||||
|
acm_func=_open_aio_quote_channel,
|
||||||
|
kwargs={
|
||||||
|
'symbol': symbol,
|
||||||
|
'contract': contract,
|
||||||
|
},
|
||||||
|
key=symbol,
|
||||||
|
) as (_, chan):
|
||||||
|
bstream: tractor.trionics.BroadcastReceiver
|
||||||
|
async with chan.subscribe() as bstream:
|
||||||
|
yield bstream
|
||||||
|
|
||||||
|
|
||||||
# TODO: cython/mypyc/numba this!
|
# TODO: cython/mypyc/numba this!
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ from piker.brokers._util import (
|
||||||
SymbolNotFound,
|
SymbolNotFound,
|
||||||
BrokerError,
|
BrokerError,
|
||||||
DataThrottle,
|
DataThrottle,
|
||||||
|
get_or_raise_on_pair_schema_mismatch,
|
||||||
)
|
)
|
||||||
from piker.accounting import Transaction
|
from piker.accounting import Transaction
|
||||||
from piker.log import get_logger
|
from piker.log import get_logger
|
||||||
|
|
@ -117,6 +118,9 @@ class InvalidKey(ValueError):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
from tractor._exceptions import reg_err_types
|
||||||
|
reg_err_types([InvalidKey])
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
|
|
||||||
|
|
@ -502,7 +506,16 @@ class Client:
|
||||||
|
|
||||||
# NOTE: always cache in pairs tables for faster lookup
|
# NOTE: always cache in pairs tables for faster lookup
|
||||||
with tractor.devx.maybe_open_crash_handler(): # as bxerr:
|
with tractor.devx.maybe_open_crash_handler(): # as bxerr:
|
||||||
pair = Pair(xname=xkey, **data)
|
# pair = Pair(xname=xkey, **data)
|
||||||
|
pair: Pair = get_or_raise_on_pair_schema_mismatch(
|
||||||
|
pair_type=Pair,
|
||||||
|
fields_data=dict(
|
||||||
|
xname=xkey,
|
||||||
|
**data,
|
||||||
|
),
|
||||||
|
provider_name='kraken',
|
||||||
|
# api_url='https://binance-docs.github.io/apidocs/spot/en/#exchange-information',
|
||||||
|
)
|
||||||
|
|
||||||
# register the above `Pair` structs for all
|
# register the above `Pair` structs for all
|
||||||
# key-sets/monikers: a set of 4 (frickin) tables
|
# key-sets/monikers: a set of 4 (frickin) tables
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,9 @@ MsgUnion = Union[
|
||||||
class TooFastEdit(Exception):
|
class TooFastEdit(Exception):
|
||||||
'Edit requests faster then api submissions'
|
'Edit requests faster then api submissions'
|
||||||
|
|
||||||
|
from tractor._exceptions import reg_err_types
|
||||||
|
reg_err_types([TooFastEdit])
|
||||||
|
|
||||||
|
|
||||||
# TODO: make this wrap the `Client` and `ws` instances
|
# TODO: make this wrap the `Client` and `ws` instances
|
||||||
# and give it methods to submit cancel vs. add vs. edit
|
# and give it methods to submit cancel vs. add vs. edit
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@ Symbology defs and search.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
from typing import (
|
||||||
|
ClassVar,
|
||||||
|
)
|
||||||
|
|
||||||
import tractor
|
import tractor
|
||||||
|
|
||||||
|
|
@ -86,9 +89,14 @@ class Pair(Struct):
|
||||||
short_position_limit: float = 0
|
short_position_limit: float = 0
|
||||||
long_position_limit: float = float('inf')
|
long_position_limit: float = float('inf')
|
||||||
|
|
||||||
|
# TODO, add API note when this was added!
|
||||||
|
execution_venue: str|None = None
|
||||||
|
|
||||||
# TODO: should we make this a literal NamespacePath ref?
|
# TODO: should we make this a literal NamespacePath ref?
|
||||||
ns_path: str = 'piker.brokers.kraken:Pair'
|
ns_path: str = 'piker.brokers.kraken:Pair'
|
||||||
|
|
||||||
|
_api_url: ClassVar[str] = 'https://docs.kraken.com/api/docs/rest-api/get-tradable-asset-pairs'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def bs_mktid(self) -> str:
|
def bs_mktid(self) -> str:
|
||||||
'''
|
'''
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,9 @@ _time_frames = {
|
||||||
class QuestradeError(Exception):
|
class QuestradeError(Exception):
|
||||||
"Non-200 OK response code"
|
"Non-200 OK response code"
|
||||||
|
|
||||||
|
from tractor._exceptions import reg_err_types
|
||||||
|
reg_err_types([QuestradeError])
|
||||||
|
|
||||||
|
|
||||||
class ContractsKey(NamedTuple):
|
class ContractsKey(NamedTuple):
|
||||||
symbol: str
|
symbol: str
|
||||||
|
|
|
||||||
|
|
@ -785,11 +785,10 @@ async def _setup_persistent_emsd(
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
if loglevel:
|
if loglevel:
|
||||||
_log = get_console_log(
|
get_console_log(
|
||||||
level=loglevel,
|
level=loglevel,
|
||||||
name=subsys,
|
name=subsys,
|
||||||
)
|
)
|
||||||
assert _log.name == 'piker.clearing'
|
|
||||||
|
|
||||||
global _router
|
global _router
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ from types import ModuleType
|
||||||
import click
|
import click
|
||||||
import trio
|
import trio
|
||||||
import tractor
|
import tractor
|
||||||
from tractor._multiaddr import parse_maddr
|
from tractor.discovery import parse_endpoints
|
||||||
|
|
||||||
from ..log import (
|
from ..log import (
|
||||||
get_console_log,
|
get_console_log,
|
||||||
|
|
@ -46,48 +46,27 @@ log = get_logger('piker.cli')
|
||||||
|
|
||||||
|
|
||||||
def load_trans_eps(
|
def load_trans_eps(
|
||||||
network: dict | None = None,
|
network: dict|None = None,
|
||||||
maddrs: list[tuple] | None = None,
|
maddrs: str|tuple[str, ...]|list[str]|None = None,
|
||||||
|
|
||||||
) -> dict[str, dict[str, dict]]:
|
) -> dict[str, list]:
|
||||||
|
'''
|
||||||
|
Load transport endpoints from a `[network]` config
|
||||||
|
table or CLI-provided multiaddr strings, delegating
|
||||||
|
to `tractor.discovery.parse_endpoints()`.
|
||||||
|
|
||||||
# transport-oriented endpoint multi-addresses
|
'''
|
||||||
eps: dict[
|
if network and not maddrs:
|
||||||
str, # service name, eg. `pikerd`, `emsd`..
|
return parse_endpoints(network)
|
||||||
|
|
||||||
# libp2p style multi-addresses parsed into prot layers
|
|
||||||
list[dict[str, str | int]]
|
|
||||||
] = {}
|
|
||||||
|
|
||||||
if (
|
|
||||||
network
|
|
||||||
and
|
|
||||||
not maddrs
|
|
||||||
):
|
|
||||||
# load network section and (attempt to) connect all endpoints
|
|
||||||
# which are reachable B)
|
|
||||||
for key, maddrs in network.items():
|
|
||||||
match key:
|
|
||||||
|
|
||||||
# TODO: resolve table across multiple discov
|
|
||||||
# prots Bo
|
|
||||||
case 'resolv':
|
|
||||||
pass
|
|
||||||
|
|
||||||
case 'pikerd':
|
|
||||||
dname: str = key
|
|
||||||
for maddr in maddrs:
|
|
||||||
layers: dict = parse_maddr(maddr)
|
|
||||||
eps.setdefault(
|
|
||||||
dname,
|
|
||||||
[],
|
|
||||||
).append(layers)
|
|
||||||
|
|
||||||
elif maddrs:
|
elif maddrs:
|
||||||
# presume user is manually specifying the root actor ep.
|
if isinstance(maddrs, str):
|
||||||
eps['pikerd'] = [parse_maddr(maddr)]
|
maddrs = [maddrs]
|
||||||
|
return parse_endpoints(
|
||||||
|
{'pikerd': list(maddrs)}
|
||||||
|
)
|
||||||
|
|
||||||
return eps
|
return {}
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
|
|
@ -108,13 +87,13 @@ def load_trans_eps(
|
||||||
help='Enable tractor debug mode',
|
help='Enable tractor debug mode',
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
'--maddr',
|
'--maddrs',
|
||||||
'-m',
|
'-m',
|
||||||
default=None,
|
multiple=True,
|
||||||
help='Multiaddrs to bind or contact',
|
help='Multiaddrs to bind or contact',
|
||||||
)
|
)
|
||||||
def pikerd(
|
def pikerd(
|
||||||
maddr: list[str] | None,
|
maddrs: tuple[str, ...],
|
||||||
loglevel: str,
|
loglevel: str,
|
||||||
tl: bool,
|
tl: bool,
|
||||||
pdb: bool,
|
pdb: bool,
|
||||||
|
|
@ -145,7 +124,8 @@ def pikerd(
|
||||||
))
|
))
|
||||||
|
|
||||||
# service-actor registry endpoint socket-address set
|
# service-actor registry endpoint socket-address set
|
||||||
regaddrs: list[tuple[str, int]] = []
|
regaddrs: list = []
|
||||||
|
tpt_bind_addrs: list|None = None
|
||||||
|
|
||||||
conf, _ = config.load(
|
conf, _ = config.load(
|
||||||
conf_name='conf',
|
conf_name='conf',
|
||||||
|
|
@ -153,7 +133,8 @@ def pikerd(
|
||||||
network: dict = conf.get('network')
|
network: dict = conf.get('network')
|
||||||
if (
|
if (
|
||||||
network is None
|
network is None
|
||||||
and not maddr
|
and
|
||||||
|
not maddrs
|
||||||
):
|
):
|
||||||
regaddrs = [(
|
regaddrs = [(
|
||||||
_default_registry_host,
|
_default_registry_host,
|
||||||
|
|
@ -161,15 +142,23 @@ def pikerd(
|
||||||
)]
|
)]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
eps: dict = load_trans_eps(
|
from tractor.devx import maybe_open_crash_handler
|
||||||
network,
|
with maybe_open_crash_handler(pdb=pdb):
|
||||||
maddr,
|
eps: dict[str, list] = load_trans_eps(
|
||||||
)
|
network,
|
||||||
for layers in eps['pikerd']:
|
maddrs,
|
||||||
regaddrs.append((
|
)
|
||||||
layers['ipv4']['addr'],
|
|
||||||
layers['tcp']['port'],
|
# pikerd bind addresses (may differ from
|
||||||
))
|
# registry if regd is separate)
|
||||||
|
tpt_bind_addrs = eps.get('pikerd')
|
||||||
|
|
||||||
|
# registry: dedicated `regd` key, or fall
|
||||||
|
# back to pikerd addrs (pikerd IS the registry)
|
||||||
|
regaddrs = eps.get(
|
||||||
|
'regd',
|
||||||
|
tpt_bind_addrs,
|
||||||
|
)
|
||||||
|
|
||||||
from .. import service
|
from .. import service
|
||||||
|
|
||||||
|
|
@ -178,6 +167,7 @@ def pikerd(
|
||||||
async with (
|
async with (
|
||||||
service.open_pikerd(
|
service.open_pikerd(
|
||||||
registry_addrs=regaddrs,
|
registry_addrs=regaddrs,
|
||||||
|
tpt_bind_addrs=tpt_bind_addrs,
|
||||||
loglevel=loglevel,
|
loglevel=loglevel,
|
||||||
debug_mode=pdb,
|
debug_mode=pdb,
|
||||||
# enable_transports=['uds'],
|
# enable_transports=['uds'],
|
||||||
|
|
@ -345,7 +335,7 @@ def services(
|
||||||
if not ports:
|
if not ports:
|
||||||
ports: list[int] = [_default_registry_port]
|
ports: list[int] = [_default_registry_port]
|
||||||
|
|
||||||
addr = tractor._addr.wrap_address(
|
addr = tractor.discovery._addr.wrap_address(
|
||||||
addr=(host, ports[0])
|
addr=(host, ports[0])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ except ModuleNotFoundError:
|
||||||
import tomli as tomllib
|
import tomli as tomllib
|
||||||
|
|
||||||
|
|
||||||
|
from tractor._exceptions import reg_err_types
|
||||||
from .log import get_logger
|
from .log import get_logger
|
||||||
|
|
||||||
log = get_logger('broker-config')
|
log = get_logger('broker-config')
|
||||||
|
|
@ -172,6 +173,12 @@ class ConfigurationError(Exception):
|
||||||
class NoSignature(ConfigurationError):
|
class NoSignature(ConfigurationError):
|
||||||
'No credentials setup for broker backend!'
|
'No credentials setup for broker backend!'
|
||||||
|
|
||||||
|
# auto-register for tractor IPC exc-marshalling.
|
||||||
|
reg_err_types([
|
||||||
|
ConfigurationError,
|
||||||
|
*ConfigurationError.__subclasses__(),
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
def _override_config_dir(
|
def _override_config_dir(
|
||||||
path: str
|
path: str
|
||||||
|
|
@ -180,6 +187,48 @@ def _override_config_dir(
|
||||||
_config_dir = path
|
_config_dir = path
|
||||||
|
|
||||||
|
|
||||||
|
def _maybe_use_test_dir() -> None:
|
||||||
|
'''
|
||||||
|
When running under the `pytest` harness, override
|
||||||
|
the config dir to the per-test-tmp dir "passed down"
|
||||||
|
the actor tree via `tractor`'s runtime-vars
|
||||||
|
inheritance mechanism.
|
||||||
|
|
||||||
|
See the `tractor_runtime_overrides` usage in our
|
||||||
|
`tests.conftest._open_test_pikerd()` as well as
|
||||||
|
`.service._actor_runtime.open_piker_runtime()` for
|
||||||
|
the root-actor's pre-loading of the var state.
|
||||||
|
|
||||||
|
NOTE: this must be checked lazily at config-path
|
||||||
|
access time (NOT import time) since sub-actors only
|
||||||
|
receive runtime-vars once their `tractor` runtime
|
||||||
|
has fully booted.
|
||||||
|
|
||||||
|
'''
|
||||||
|
global _config_dir
|
||||||
|
import tractor
|
||||||
|
actor = tractor.current_actor(
|
||||||
|
err_on_no_runtime=False,
|
||||||
|
)
|
||||||
|
if actor is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
rvs: dict = tractor.runtime._state._runtime_vars
|
||||||
|
pvars: dict|None = rvs.get('piker_vars')
|
||||||
|
if (
|
||||||
|
pvars
|
||||||
|
and
|
||||||
|
(testdir := pvars.get('piker_test_dir'))
|
||||||
|
):
|
||||||
|
testdirpath = Path(testdir)
|
||||||
|
assert testdirpath.exists(), (
|
||||||
|
f'piker test harness might be borked!?\n'
|
||||||
|
f'testdirpath: {testdirpath!r}\n'
|
||||||
|
)
|
||||||
|
if _config_dir != testdirpath:
|
||||||
|
_override_config_dir(testdirpath)
|
||||||
|
|
||||||
|
|
||||||
def _conf_fn_w_ext(
|
def _conf_fn_w_ext(
|
||||||
name: str,
|
name: str,
|
||||||
) -> str:
|
) -> str:
|
||||||
|
|
@ -193,6 +242,7 @@ def get_conf_dir() -> Path:
|
||||||
on the local filesystem.
|
on the local filesystem.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
_maybe_use_test_dir()
|
||||||
return _config_dir
|
return _config_dir
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -218,7 +268,7 @@ def get_conf_path(
|
||||||
assert str(conf_name) in _conf_names
|
assert str(conf_name) in _conf_names
|
||||||
|
|
||||||
fn = _conf_fn_w_ext(conf_name)
|
fn = _conf_fn_w_ext(conf_name)
|
||||||
return _config_dir / Path(fn)
|
return get_conf_dir() / Path(fn)
|
||||||
|
|
||||||
|
|
||||||
def repodir() -> Path:
|
def repodir() -> Path:
|
||||||
|
|
@ -263,8 +313,9 @@ def load(
|
||||||
|
|
||||||
'''
|
'''
|
||||||
# create the $HOME/.config/piker dir if dne
|
# create the $HOME/.config/piker dir if dne
|
||||||
if not _config_dir.is_dir():
|
conf_dir: Path = get_conf_dir()
|
||||||
_config_dir.mkdir(
|
if not conf_dir.is_dir():
|
||||||
|
conf_dir.mkdir(
|
||||||
parents=True,
|
parents=True,
|
||||||
exist_ok=True,
|
exist_ok=True,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ from collections import (
|
||||||
defaultdict,
|
defaultdict,
|
||||||
abc,
|
abc,
|
||||||
)
|
)
|
||||||
|
from copy import copy
|
||||||
from contextlib import asynccontextmanager as acm
|
from contextlib import asynccontextmanager as acm
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import time
|
import time
|
||||||
|
|
@ -77,7 +78,7 @@ from ._sampling import (
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .flows import Flume
|
from .flows import Flume
|
||||||
from tractor._addr import Address
|
from tractor.discovery._addr import Address
|
||||||
from tractor.msg.types import Aid
|
from tractor.msg.types import Aid
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -674,6 +675,36 @@ async def open_feed_bus(
|
||||||
bus.remove_subs(bs_fqme, subs)
|
bus.remove_subs(bs_fqme, subs)
|
||||||
|
|
||||||
|
|
||||||
|
async def relay_to_common_memchan(
|
||||||
|
stream: (
|
||||||
|
tractor.MsgStream
|
||||||
|
|trionics.BroadcastReceiver
|
||||||
|
),
|
||||||
|
tx: trio.MemorySendChannel[dict[str, Any]],
|
||||||
|
task_status: TaskStatus[
|
||||||
|
trionics.BroadcastReceiver,
|
||||||
|
] = trio.TASK_STATUS_IGNORED,
|
||||||
|
|
||||||
|
) -> None:
|
||||||
|
'''
|
||||||
|
Relay one provider subscription into a common memory channel.
|
||||||
|
|
||||||
|
Deliver the live child receiver through `task_status` so the
|
||||||
|
caller can retain and inspect each provider relay's cursor.
|
||||||
|
|
||||||
|
'''
|
||||||
|
bstream: trionics.BroadcastReceiver
|
||||||
|
async with (
|
||||||
|
stream.subscribe() as bstream,
|
||||||
|
tx,
|
||||||
|
):
|
||||||
|
task_status.started(bstream)
|
||||||
|
|
||||||
|
msg: dict[str, Any]
|
||||||
|
async for msg in bstream:
|
||||||
|
await tx.send(msg)
|
||||||
|
|
||||||
|
|
||||||
class Feed(Struct):
|
class Feed(Struct):
|
||||||
'''
|
'''
|
||||||
A per-provider API for client-side consumption from real-time data
|
A per-provider API for client-side consumption from real-time data
|
||||||
|
|
@ -723,29 +754,51 @@ class Feed(Struct):
|
||||||
if len(mods) == 1:
|
if len(mods) == 1:
|
||||||
# just pass the brokerd stream directly if only one provider
|
# just pass the brokerd stream directly if only one provider
|
||||||
# was detected.
|
# was detected.
|
||||||
stream = self.streams[list(brokers)[0]]
|
stream: (
|
||||||
|
tractor.MsgStream
|
||||||
|
|trionics.BroadcastReceiver
|
||||||
|
) = self.streams[list(brokers)[0]]
|
||||||
|
bstream: trionics.BroadcastReceiver
|
||||||
async with stream.subscribe() as bstream:
|
async with stream.subscribe() as bstream:
|
||||||
yield bstream
|
yield bstream
|
||||||
return
|
return
|
||||||
|
|
||||||
# start multiplexing task tree
|
# start multiplexing task tree
|
||||||
|
tx: trio.MemorySendChannel[dict[str, Any]]
|
||||||
|
rx: trio.MemoryReceiveChannel[dict[str, Any]]
|
||||||
tx, rx = trio.open_memory_channel(616)
|
tx, rx = trio.open_memory_channel(616)
|
||||||
|
|
||||||
async def relay_to_common_memchan(stream: tractor.MsgStream):
|
|
||||||
async with tx:
|
|
||||||
async for msg in stream:
|
|
||||||
await tx.send(msg)
|
|
||||||
|
|
||||||
async with (
|
async with (
|
||||||
tractor.trionics.collapse_eg(),
|
tractor.trionics.collapse_eg(),
|
||||||
trio.open_nursery() as nurse
|
trio.open_nursery() as nurse
|
||||||
):
|
):
|
||||||
# spawn a relay task for each stream so that they all
|
# spawn a relay task for each stream so that they all
|
||||||
# multiplex to a common channel.
|
# multiplex to a common channel.
|
||||||
for brokername in mods:
|
broker2bstreams: dict[
|
||||||
stream = self.streams[brokername]
|
str,
|
||||||
nurse.start_soon(relay_to_common_memchan, stream)
|
trionics.BroadcastReceiver,
|
||||||
|
] = {}
|
||||||
|
broker: str
|
||||||
|
for broker in mods:
|
||||||
|
stream: (
|
||||||
|
tractor.MsgStream
|
||||||
|
|trionics.BroadcastReceiver
|
||||||
|
) = self.streams[broker]
|
||||||
|
|
||||||
|
relay_tx: trio.MemorySendChannel[
|
||||||
|
dict[str, Any]
|
||||||
|
] = tx.clone()
|
||||||
|
|
||||||
|
bstream: trionics.BroadcastReceiver = await nurse.start(
|
||||||
|
relay_to_common_memchan,
|
||||||
|
stream,
|
||||||
|
relay_tx,
|
||||||
|
)
|
||||||
|
broker2bstreams[broker] = bstream
|
||||||
|
|
||||||
|
# Each relay now owns one `tx` clone. Closing the original
|
||||||
|
# lets `rx` reach EOC only after every provider relay exits.
|
||||||
|
await tx.aclose()
|
||||||
try:
|
try:
|
||||||
yield rx
|
yield rx
|
||||||
finally:
|
finally:
|
||||||
|
|
@ -754,10 +807,23 @@ class Feed(Struct):
|
||||||
_max_sample_rate: int = 1
|
_max_sample_rate: int = 1
|
||||||
|
|
||||||
async def pause(self) -> None:
|
async def pause(self) -> None:
|
||||||
|
'''
|
||||||
|
Pause the shared remote provider context for this cached feed.
|
||||||
|
|
||||||
|
This controls provider publication for every local cache user;
|
||||||
|
it does not pause only this caller's receive cursor.
|
||||||
|
|
||||||
|
'''
|
||||||
|
stream: tractor.MsgStream|trionics.BroadcastReceiver
|
||||||
for stream in set(self.streams.values()):
|
for stream in set(self.streams.values()):
|
||||||
await stream.send('pause')
|
await stream.send('pause')
|
||||||
|
|
||||||
async def resume(self) -> None:
|
async def resume(self) -> None:
|
||||||
|
'''
|
||||||
|
Resume the shared remote provider context for this cached feed.
|
||||||
|
|
||||||
|
'''
|
||||||
|
stream: tractor.MsgStream|trionics.BroadcastReceiver
|
||||||
for stream in set(self.streams.values()):
|
for stream in set(self.streams.values()):
|
||||||
await stream.send('resume')
|
await stream.send('resume')
|
||||||
|
|
||||||
|
|
@ -817,7 +883,17 @@ async def maybe_open_feed(
|
||||||
in a tractor broadcast receiver.
|
in a tractor broadcast receiver.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
fqme = fqmes[0]
|
cache_key: tuple[
|
||||||
|
tuple[str, ...],
|
||||||
|
float|None,
|
||||||
|
bool,
|
||||||
|
bool,
|
||||||
|
] = (
|
||||||
|
tuple(sorted(fqmes)),
|
||||||
|
kwargs.get('tick_throttle'),
|
||||||
|
kwargs.get('allow_overruns', True),
|
||||||
|
kwargs.get('start_stream', True),
|
||||||
|
)
|
||||||
|
|
||||||
async with trionics.maybe_open_context(
|
async with trionics.maybe_open_context(
|
||||||
acm_func=open_feed,
|
acm_func=open_feed,
|
||||||
|
|
@ -830,27 +906,73 @@ async def maybe_open_feed(
|
||||||
'allow_overruns': kwargs.get('allow_overruns', True),
|
'allow_overruns': kwargs.get('allow_overruns', True),
|
||||||
'start_stream': kwargs.get('start_stream', True),
|
'start_stream': kwargs.get('start_stream', True),
|
||||||
},
|
},
|
||||||
key=fqme,
|
key=cache_key,
|
||||||
|
|
||||||
) as (cache_hit, feed):
|
) as (cache_hit, feed):
|
||||||
|
feed: Feed
|
||||||
|
|
||||||
if cache_hit:
|
if (
|
||||||
log.info(f'Using cached feed for {fqme}')
|
cache_hit
|
||||||
# add a new broadcast subscription for the quote stream
|
and
|
||||||
# if this feed is likely already in use
|
log.at_least_level('info')
|
||||||
|
):
|
||||||
|
log.info(
|
||||||
|
f'Using cached feed for key:\n'
|
||||||
|
f'{cache_key!r}'
|
||||||
|
)
|
||||||
|
|
||||||
async with trionics.gather_contexts(
|
# The cached `Feed` exclusively owns provider root streams.
|
||||||
mngrs=[stream.subscribe() for stream in feed.streams.values()]
|
# Every caller, including the first cache owner, gets a local
|
||||||
) as bstreams:
|
# child cursor and copied descriptors for its lexical lifetime.
|
||||||
for bstream, flume in zip(bstreams, feed.flumes.values()):
|
broker_names: tuple[str, ...] = tuple(feed.streams)
|
||||||
# XXX: TODO: horrible hackery that needs fixing..
|
bstreams: tuple[
|
||||||
# i guess we have to create context proxies?
|
trionics.BroadcastReceiver,
|
||||||
bstream._ctx = flume.stream._ctx
|
...,
|
||||||
flume.stream = bstream
|
]
|
||||||
|
async with trionics.gather_contexts(
|
||||||
|
mngrs=[
|
||||||
|
feed.streams[broker].subscribe()
|
||||||
|
for broker in broker_names
|
||||||
|
]
|
||||||
|
) as bstreams:
|
||||||
|
broker2bstreams: dict[
|
||||||
|
str,
|
||||||
|
trionics.BroadcastReceiver,
|
||||||
|
] = dict(zip(
|
||||||
|
broker_names,
|
||||||
|
bstreams,
|
||||||
|
strict=True,
|
||||||
|
))
|
||||||
|
flumes: dict[str, Flume] = {}
|
||||||
|
fqme: str
|
||||||
|
flume: Flume
|
||||||
|
for fqme, flume in feed.flumes.items():
|
||||||
|
broker: str = flume.mkt.broker
|
||||||
|
|
||||||
yield feed
|
bstream: trionics.BroadcastReceiver = (
|
||||||
else:
|
broker2bstreams[broker]
|
||||||
yield feed
|
)
|
||||||
|
|
||||||
|
# XXX: TODO: horrible hackery that needs fixing..
|
||||||
|
# i guess we have to create context proxies?
|
||||||
|
root_stream: tractor.MsgStream = feed.streams[broker]
|
||||||
|
|
||||||
|
ctx: tractor.Context = root_stream.ctx
|
||||||
|
bstream._ctx = ctx
|
||||||
|
|
||||||
|
local_flume: Flume = copy(flume)
|
||||||
|
local_flume.stream = bstream
|
||||||
|
flumes[fqme] = local_flume
|
||||||
|
|
||||||
|
# `feed` is the cache-owned resource and must retain only
|
||||||
|
# provider root streams. A shallow `Feed` copy gives this
|
||||||
|
# caller its own descriptor mappings while intentionally
|
||||||
|
# sharing immutable market metadata, SHM handles and
|
||||||
|
# provider controls for the cache resource's lifetime.
|
||||||
|
local_feed: Feed = copy(feed)
|
||||||
|
local_feed.flumes = flumes
|
||||||
|
local_feed.streams = broker2bstreams
|
||||||
|
yield local_feed
|
||||||
|
|
||||||
|
|
||||||
@acm
|
@acm
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ from piker.accounting import (
|
||||||
Asset,
|
Asset,
|
||||||
MktPair,
|
MktPair,
|
||||||
)
|
)
|
||||||
|
from tractor._exceptions import reg_err_types
|
||||||
from ._util import log
|
from ._util import log
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -43,6 +44,8 @@ class FeedInitializationError(ValueError):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
reg_err_types([FeedInitializationError])
|
||||||
|
|
||||||
|
|
||||||
class FeedInit(Struct, frozen=True):
|
class FeedInit(Struct, frozen=True):
|
||||||
'''
|
'''
|
||||||
|
|
|
||||||
33
piker/log.py
33
piker/log.py
|
|
@ -36,6 +36,15 @@ from pygments import (
|
||||||
_proj_name: str = 'piker'
|
_proj_name: str = 'piker'
|
||||||
|
|
||||||
|
|
||||||
|
def _relative_name(
|
||||||
|
name: str|None,
|
||||||
|
) -> str|None:
|
||||||
|
if name:
|
||||||
|
return name.removeprefix(f'{_proj_name}.')
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_logger(
|
def get_logger(
|
||||||
name: str|None = None,
|
name: str|None = None,
|
||||||
**tractor_log_kwargs,
|
**tractor_log_kwargs,
|
||||||
|
|
@ -47,17 +56,9 @@ def get_logger(
|
||||||
See `tractor.log.get_logger()` for details.
|
See `tractor.log.get_logger()` for details.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
pkg_name: str = _proj_name
|
|
||||||
if (
|
|
||||||
name
|
|
||||||
and
|
|
||||||
pkg_name in name
|
|
||||||
):
|
|
||||||
name: str = name.lstrip(f'{_proj_name}.')
|
|
||||||
|
|
||||||
return tractor.log.get_logger(
|
return tractor.log.get_logger(
|
||||||
name=name,
|
name=_relative_name(name),
|
||||||
pkg_name=pkg_name,
|
pkg_name=_proj_name,
|
||||||
**tractor_log_kwargs,
|
**tractor_log_kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -81,14 +82,6 @@ def get_console_log(
|
||||||
You do it.. Bp
|
You do it.. Bp
|
||||||
|
|
||||||
'''
|
'''
|
||||||
pkg_name: str = _proj_name
|
|
||||||
if (
|
|
||||||
name
|
|
||||||
and
|
|
||||||
pkg_name in name
|
|
||||||
):
|
|
||||||
name: str = name.lstrip(f'{_proj_name}.')
|
|
||||||
|
|
||||||
tll: str|None = None
|
tll: str|None = None
|
||||||
if (
|
if (
|
||||||
with_tractor_log is not False
|
with_tractor_log is not False
|
||||||
|
|
@ -111,8 +104,8 @@ def get_console_log(
|
||||||
|
|
||||||
return tractor.log.get_console_log(
|
return tractor.log.get_console_log(
|
||||||
level=level,
|
level=level,
|
||||||
name=name,
|
name=_relative_name(name),
|
||||||
pkg_name=pkg_name,
|
pkg_name=_proj_name,
|
||||||
**tractor_log_kwargs,
|
**tractor_log_kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ from ._registry import ( # noqa
|
||||||
_tractor_kwargs,
|
_tractor_kwargs,
|
||||||
_default_reg_addr,
|
_default_reg_addr,
|
||||||
open_registry,
|
open_registry,
|
||||||
|
RegistryAddress,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -58,7 +59,8 @@ def get_runtime_vars() -> dict[str, Any]:
|
||||||
@acm
|
@acm
|
||||||
async def open_piker_runtime(
|
async def open_piker_runtime(
|
||||||
name: str,
|
name: str,
|
||||||
registry_addrs: list[tuple[str, int]] = [],
|
registry_addrs: list[RegistryAddress] = [],
|
||||||
|
tpt_bind_addrs: list|None = None,
|
||||||
|
|
||||||
enable_modules: list[str] = [],
|
enable_modules: list[str] = [],
|
||||||
loglevel: str|None = None,
|
loglevel: str|None = None,
|
||||||
|
|
@ -76,7 +78,7 @@ async def open_piker_runtime(
|
||||||
|
|
||||||
) -> tuple[
|
) -> tuple[
|
||||||
tractor.Actor,
|
tractor.Actor,
|
||||||
list[tuple[str, int]],
|
list[RegistryAddress],
|
||||||
]:
|
]:
|
||||||
'''
|
'''
|
||||||
Start a piker actor who's runtime will automatically sync with
|
Start a piker actor who's runtime will automatically sync with
|
||||||
|
|
@ -91,7 +93,7 @@ async def open_piker_runtime(
|
||||||
try:
|
try:
|
||||||
actor = tractor.current_actor()
|
actor = tractor.current_actor()
|
||||||
except tractor._exceptions.NoRuntime:
|
except tractor._exceptions.NoRuntime:
|
||||||
tractor._state._runtime_vars[
|
tractor.runtime._state._runtime_vars[
|
||||||
'piker_vars'
|
'piker_vars'
|
||||||
] = tractor_runtime_overrides
|
] = tractor_runtime_overrides
|
||||||
|
|
||||||
|
|
@ -112,6 +114,7 @@ async def open_piker_runtime(
|
||||||
|
|
||||||
# passed through to `open_root_actor`
|
# passed through to `open_root_actor`
|
||||||
registry_addrs=registry_addrs,
|
registry_addrs=registry_addrs,
|
||||||
|
tpt_bind_addrs=tpt_bind_addrs,
|
||||||
name=name,
|
name=name,
|
||||||
start_method=start_method,
|
start_method=start_method,
|
||||||
loglevel=loglevel,
|
loglevel=loglevel,
|
||||||
|
|
@ -165,7 +168,8 @@ _root_modules: list[str] = [
|
||||||
|
|
||||||
@acm
|
@acm
|
||||||
async def open_pikerd(
|
async def open_pikerd(
|
||||||
registry_addrs: list[tuple[str, int]],
|
registry_addrs: list[RegistryAddress],
|
||||||
|
tpt_bind_addrs: list|None = None,
|
||||||
loglevel: str|None = None,
|
loglevel: str|None = None,
|
||||||
|
|
||||||
# XXX: you should pretty much never want debug mode
|
# XXX: you should pretty much never want debug mode
|
||||||
|
|
@ -198,6 +202,7 @@ async def open_pikerd(
|
||||||
loglevel=loglevel,
|
loglevel=loglevel,
|
||||||
debug_mode=debug_mode,
|
debug_mode=debug_mode,
|
||||||
registry_addrs=registry_addrs,
|
registry_addrs=registry_addrs,
|
||||||
|
tpt_bind_addrs=tpt_bind_addrs,
|
||||||
|
|
||||||
**kwargs,
|
**kwargs,
|
||||||
|
|
||||||
|
|
@ -209,8 +214,44 @@ async def open_pikerd(
|
||||||
tractor.trionics.collapse_eg(),
|
tractor.trionics.collapse_eg(),
|
||||||
trio.open_nursery() as service_tn,
|
trio.open_nursery() as service_tn,
|
||||||
):
|
):
|
||||||
for addr in reg_addrs:
|
# `reg_addrs` locates the registrar used for actor discovery;
|
||||||
if addr not in root_actor.accept_addrs:
|
# `tpt_bind_addrs` requests this daemon's own IPC listeners.
|
||||||
|
# An existing registrar can live elsewhere, so its endpoints
|
||||||
|
# must not be checked against `root_actor.accept_addrs`.
|
||||||
|
bind_addrs = tpt_bind_addrs
|
||||||
|
if bind_addrs is None:
|
||||||
|
# Only a registrar actor owns the discovery endpoints.
|
||||||
|
# A client with no explicit bind request lets Tractor pick
|
||||||
|
# its listener; there is no caller-specified bind to check.
|
||||||
|
bind_addrs = (
|
||||||
|
reg_addrs if root_actor.is_registrar else []
|
||||||
|
)
|
||||||
|
|
||||||
|
# `root_actor.accept_addrs` contains the actual bound endpoints.
|
||||||
|
# Normalize both sides with Tractor's address API so legacy
|
||||||
|
# pairs and tagged transport tuples compare in the same form.
|
||||||
|
accept_addrs = [
|
||||||
|
tractor.discovery._addr.wrap_address(addr).unwrap()
|
||||||
|
for addr in root_actor.accept_addrs
|
||||||
|
]
|
||||||
|
for addr in bind_addrs:
|
||||||
|
# normalize to a wrapped `tractor` addr-type;
|
||||||
|
# entries may be raw `tuple`s when passed in
|
||||||
|
# from (test) client code.
|
||||||
|
wladdr = tractor.discovery._addr.wrap_address(
|
||||||
|
addr,
|
||||||
|
)
|
||||||
|
uaddr: tuple = wladdr.unwrap()
|
||||||
|
bound = uaddr in accept_addrs
|
||||||
|
if wladdr.proto_key == 'tcp' and uaddr[-1] == 0:
|
||||||
|
# TCP port zero asks the OS for an ephemeral listener.
|
||||||
|
# Its actual port differs from the request, but the
|
||||||
|
# tagged transport and host must still match exactly.
|
||||||
|
bound = any(
|
||||||
|
actual[:-1] == uaddr[:-1]
|
||||||
|
for actual in accept_addrs
|
||||||
|
)
|
||||||
|
if not bound:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f'`pikerd` failed to bind on {addr}!\n'
|
f'`pikerd` failed to bind on {addr}!\n'
|
||||||
'Maybe you have another daemon already running?'
|
'Maybe you have another daemon already running?'
|
||||||
|
|
@ -258,13 +299,13 @@ async def open_pikerd(
|
||||||
|
|
||||||
@acm
|
@acm
|
||||||
async def maybe_open_pikerd(
|
async def maybe_open_pikerd(
|
||||||
registry_addrs: list[tuple[str, int]] | None = None,
|
registry_addrs: list[RegistryAddress] | None = None,
|
||||||
|
|
||||||
loglevel: str | None = None,
|
loglevel: str | None = None,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
|
|
||||||
) -> (
|
) -> (
|
||||||
tractor._portal.Portal
|
tractor.Portal
|
||||||
|ClassVar[Services]
|
|ClassVar[Services]
|
||||||
):
|
):
|
||||||
'''
|
'''
|
||||||
|
|
@ -292,7 +333,7 @@ async def maybe_open_pikerd(
|
||||||
# async with open_portal(chan) as arb_portal:
|
# async with open_portal(chan) as arb_portal:
|
||||||
# yield arb_portal
|
# yield arb_portal
|
||||||
|
|
||||||
registry_addrs: list[tuple[str, int]] = (
|
registry_addrs: list[RegistryAddress] = (
|
||||||
registry_addrs
|
registry_addrs
|
||||||
or
|
or
|
||||||
[_default_reg_addr]
|
[_default_reg_addr]
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ from requests.exceptions import (
|
||||||
ReadTimeout,
|
ReadTimeout,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from tractor._exceptions import reg_err_types
|
||||||
from piker.log import (
|
from piker.log import (
|
||||||
get_console_log,
|
get_console_log,
|
||||||
get_logger,
|
get_logger,
|
||||||
|
|
@ -66,6 +67,11 @@ class DockerNotStarted(Exception):
|
||||||
class ApplicationLogError(Exception):
|
class ApplicationLogError(Exception):
|
||||||
'App in container reported an error in logs'
|
'App in container reported an error in logs'
|
||||||
|
|
||||||
|
reg_err_types([
|
||||||
|
DockerNotStarted,
|
||||||
|
ApplicationLogError,
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
@acm
|
@acm
|
||||||
async def open_docker(
|
async def open_docker(
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,6 @@ async def maybe_spawn_daemon(
|
||||||
level=loglevel,
|
level=loglevel,
|
||||||
name=__name__,
|
name=__name__,
|
||||||
)
|
)
|
||||||
assert log.name == 'piker.service'
|
|
||||||
|
|
||||||
# serialize access to this section to avoid
|
# serialize access to this section to avoid
|
||||||
# 2 or more tasks racing to create a daemon
|
# 2 or more tasks racing to create a daemon
|
||||||
|
|
@ -80,9 +79,21 @@ async def maybe_spawn_daemon(
|
||||||
await lock.acquire()
|
await lock.acquire()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Discovery and `maybe_open_pikerd()` must use the same
|
||||||
|
# registrar list, independently of other runtime options.
|
||||||
|
# Consume an override here: startup forwards it explicitly
|
||||||
|
# below, so leaving it in `pikerd_kwargs` duplicates the keyword.
|
||||||
|
registry_addrs = pikerd_kwargs.pop('registry_addrs', None)
|
||||||
|
if registry_addrs is None:
|
||||||
|
# Use the registrar addresses inherited by this actor.
|
||||||
|
rtvs: dict = tractor.get_runtime_vars()
|
||||||
|
registry_addrs: list[tuple] = list(
|
||||||
|
map(tuple, rtvs['_registry_addrs'])
|
||||||
|
)
|
||||||
|
|
||||||
async with find_service(
|
async with find_service(
|
||||||
service_name,
|
service_name,
|
||||||
registry_addrs=[('127.0.0.1', 6116)],
|
registry_addrs=registry_addrs,
|
||||||
) as portal:
|
) as portal:
|
||||||
if portal is not None:
|
if portal is not None:
|
||||||
lock.release()
|
lock.release()
|
||||||
|
|
@ -99,6 +110,7 @@ async def maybe_spawn_daemon(
|
||||||
# process tree
|
# process tree
|
||||||
async with maybe_open_pikerd(
|
async with maybe_open_pikerd(
|
||||||
loglevel=loglevel,
|
loglevel=loglevel,
|
||||||
|
registry_addrs=registry_addrs,
|
||||||
**pikerd_kwargs,
|
**pikerd_kwargs,
|
||||||
|
|
||||||
) as pikerd_portal:
|
) as pikerd_portal:
|
||||||
|
|
@ -142,7 +154,65 @@ async def maybe_spawn_daemon(
|
||||||
async with tractor.wait_for_actor(service_name) as portal:
|
async with tractor.wait_for_actor(service_name) as portal:
|
||||||
lock.release()
|
lock.release()
|
||||||
yield portal
|
yield portal
|
||||||
await portal.cancel_actor()
|
# --- ---- ---
|
||||||
|
# XXX NOTE XXX
|
||||||
|
# --- ---- ---
|
||||||
|
# DO NOT PUT A `portal.cancel_actor()` here (as was prior)!
|
||||||
|
#
|
||||||
|
# Doing so will cause an "out-of-band" ctxc
|
||||||
|
# (`tractor.ContextCancelled`) to be raised inside the
|
||||||
|
# `ServiceMngr.open_context_in_task()`'s call to
|
||||||
|
# `ctx.wait_for_result()` AND the internal self-ctxc
|
||||||
|
# "graceful capture" WILL NOT CATCH IT!
|
||||||
|
#
|
||||||
|
# This can cause certain types of operations to raise
|
||||||
|
# that ctxc BEFORE THEY `return`, resulting in
|
||||||
|
# a "false-negative" ctxc being raised when really
|
||||||
|
# nothing actually failed, other then our semantic
|
||||||
|
# "failure" to suppress an expected, graceful,
|
||||||
|
# self-cancel scenario..
|
||||||
|
#
|
||||||
|
# bUt wHy duZ It WorK lIKe dis..
|
||||||
|
# ------------------------------
|
||||||
|
# from the perspective of the `tractor.Context` this
|
||||||
|
# cancel request was conducted "out of band" since
|
||||||
|
# `Context.cancel()` was never called and thus the
|
||||||
|
# `._cancel_called: bool` was never set. Despite the
|
||||||
|
# remote `.canceller` being set to `pikerd` (i.e. the
|
||||||
|
# same `Actor.uid` of the raising service-mngr task) the
|
||||||
|
# service-task's ctx itself was never marked as having
|
||||||
|
# requested cancellation and thus still raises the ctxc
|
||||||
|
# bc it was unaware of any such request.
|
||||||
|
#
|
||||||
|
# How to make grokin these cases easier tho?
|
||||||
|
# ------------------------------------------
|
||||||
|
# Because `Portal.cancel_actor()` was called it requests
|
||||||
|
# "full-`Actor`-runtime-cancellation" of it's peer
|
||||||
|
# process which IS NOT THE SAME as a single inter-actor
|
||||||
|
# RPC task cancelling its local context with a remote
|
||||||
|
# peer `Task` in that same peer process.
|
||||||
|
#
|
||||||
|
# ?TODO? It might be better if we do one (or all) of the
|
||||||
|
# following:
|
||||||
|
#
|
||||||
|
# -[ ] at least set a special message for the
|
||||||
|
# `ContextCancelled` when raised locally by the
|
||||||
|
# unaware ctx task such that we check for the
|
||||||
|
# `.canceller` being *our `Actor`* and in the case
|
||||||
|
# where `Context._cancel_called == False` we specially
|
||||||
|
# note that this is likely an "out-of-band"
|
||||||
|
# runtime-cancel request triggered by some call to
|
||||||
|
# `Portal.cancel_actor()`, possibly even reporting the
|
||||||
|
# exact LOC of that caller by tracking it inside our
|
||||||
|
# portal-type?
|
||||||
|
# -[ ] possibly add another field `ContextCancelled` like
|
||||||
|
# maybe a,
|
||||||
|
# `.request_type: Literal['os', 'proc', 'actor',
|
||||||
|
# 'ctx']` type thing which would allow immediately
|
||||||
|
# being able to tell what kind of cancellation caused
|
||||||
|
# the unexpected ctxc?
|
||||||
|
# -[ ] REMOVE THIS COMMENT, once we've settled on how to
|
||||||
|
# better augment `tractor` to be more explicit on this!
|
||||||
|
|
||||||
except BaseException as _err:
|
except BaseException as _err:
|
||||||
err = _err
|
err = _err
|
||||||
|
|
@ -152,11 +222,13 @@ async def maybe_spawn_daemon(
|
||||||
lock.statistics().owner is current_task()
|
lock.statistics().owner is current_task()
|
||||||
):
|
):
|
||||||
log.exception(
|
log.exception(
|
||||||
f'Releasing stale lock after crash..?'
|
f'Releasing stale lock after crash..?\n'
|
||||||
|
f'\n'
|
||||||
f'{err!r}\n'
|
f'{err!r}\n'
|
||||||
)
|
)
|
||||||
lock.release()
|
lock.release()
|
||||||
raise err
|
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
async def spawn_emsd(
|
async def spawn_emsd(
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ log = get_logger(name=__name__)
|
||||||
# new actors and supervises them to completion?
|
# new actors and supervises them to completion?
|
||||||
class Services:
|
class Services:
|
||||||
|
|
||||||
actor_n: tractor._supervise.ActorNursery
|
actor_n: tractor.ActorNursery
|
||||||
service_n: trio.Nursery
|
service_n: trio.Nursery
|
||||||
debug_mode: bool # tractor sub-actor debug mode flag
|
debug_mode: bool # tractor sub-actor debug mode flag
|
||||||
service_tasks: dict[
|
service_tasks: dict[
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ from contextlib import (
|
||||||
)
|
)
|
||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
|
TypeAlias,
|
||||||
)
|
)
|
||||||
|
|
||||||
import tractor
|
import tractor
|
||||||
|
|
@ -32,11 +33,23 @@ from tractor import (
|
||||||
Actor,
|
Actor,
|
||||||
Portal,
|
Portal,
|
||||||
)
|
)
|
||||||
|
from tractor.discovery._addr import (
|
||||||
|
LegacyUnwrappedAddress,
|
||||||
|
UnwrappedAddress,
|
||||||
|
wrap_address,
|
||||||
|
)
|
||||||
|
|
||||||
from piker.log import get_logger
|
from piker.log import get_logger
|
||||||
|
|
||||||
log = get_logger(name=__name__)
|
log = get_logger(name=__name__)
|
||||||
|
|
||||||
|
# Piker config still accepts legacy socket pairs while tractor now
|
||||||
|
# emits tagged `UnwrappedAddress` values.
|
||||||
|
RegistryAddress: TypeAlias = (
|
||||||
|
LegacyUnwrappedAddress
|
||||||
|
|UnwrappedAddress
|
||||||
|
)
|
||||||
|
|
||||||
# TODO? default path-space for UDS registry?
|
# TODO? default path-space for UDS registry?
|
||||||
# [ ] needs to be Xplatform tho!
|
# [ ] needs to be Xplatform tho!
|
||||||
# _default_registry_path: Path = (
|
# _default_registry_path: Path = (
|
||||||
|
|
@ -46,10 +59,7 @@ log = get_logger(name=__name__)
|
||||||
|
|
||||||
_default_registry_host: str = '127.0.0.1'
|
_default_registry_host: str = '127.0.0.1'
|
||||||
_default_registry_port: int = 6116
|
_default_registry_port: int = 6116
|
||||||
_default_reg_addr: tuple[
|
_default_reg_addr: RegistryAddress = (
|
||||||
str,
|
|
||||||
int, # |str TODO, once we support UDS, see above.
|
|
||||||
] = (
|
|
||||||
_default_registry_host,
|
_default_registry_host,
|
||||||
_default_registry_port,
|
_default_registry_port,
|
||||||
)
|
)
|
||||||
|
|
@ -63,24 +73,37 @@ _registry: Registry | None = None
|
||||||
class Registry:
|
class Registry:
|
||||||
# TODO: should this be a set or should we complain
|
# TODO: should this be a set or should we complain
|
||||||
# on duplicates?
|
# on duplicates?
|
||||||
addrs: list[tuple[str, int]] = []
|
addrs: list[RegistryAddress] = []
|
||||||
|
|
||||||
# TODO: table of uids to sockaddrs
|
# TODO: table of uids to sockaddrs
|
||||||
peers: dict[
|
peers: dict[
|
||||||
tuple[str, str],
|
tuple[str, str],
|
||||||
tuple[str, int],
|
RegistryAddress,
|
||||||
] = {}
|
] = {}
|
||||||
|
|
||||||
|
|
||||||
_tractor_kwargs: dict[str, Any] = {}
|
_tractor_kwargs: dict[str, Any] = {}
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_addresses(
|
||||||
|
addrs: list[RegistryAddress],
|
||||||
|
) -> list[RegistryAddress]:
|
||||||
|
'''
|
||||||
|
Normalize legacy and tagged addresses through tractor's codec.
|
||||||
|
|
||||||
|
'''
|
||||||
|
return [
|
||||||
|
wrap_address(addr).unwrap()
|
||||||
|
for addr in addrs
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@acm
|
@acm
|
||||||
async def open_registry(
|
async def open_registry(
|
||||||
addrs: list[tuple[str, int]],
|
addrs: list[RegistryAddress],
|
||||||
ensure_exists: bool = True,
|
ensure_exists: bool = True,
|
||||||
|
|
||||||
) -> list[tuple[str, int]]:
|
) -> list[RegistryAddress]:
|
||||||
'''
|
'''
|
||||||
Open the service-actor-discovery registry by returning a set of
|
Open the service-actor-discovery registry by returning a set of
|
||||||
tranport socket-addrs to registrar actors which may be
|
tranport socket-addrs to registrar actors which may be
|
||||||
|
|
@ -92,9 +115,12 @@ async def open_registry(
|
||||||
actor: Actor = tractor.current_actor()
|
actor: Actor = tractor.current_actor()
|
||||||
aid: msg.Aid = actor.aid
|
aid: msg.Aid = actor.aid
|
||||||
uid: tuple[str, str] = aid.uid
|
uid: tuple[str, str] = aid.uid
|
||||||
preset_reg_addrs: list[
|
addrs = _normalize_addresses(addrs)
|
||||||
tuple[str, int]
|
preset_reg_addrs: list[RegistryAddress] = (
|
||||||
] = Registry.addrs
|
_normalize_addresses(Registry.addrs)
|
||||||
|
)
|
||||||
|
if preset_reg_addrs:
|
||||||
|
Registry.addrs = preset_reg_addrs
|
||||||
if (
|
if (
|
||||||
preset_reg_addrs
|
preset_reg_addrs
|
||||||
and
|
and
|
||||||
|
|
@ -102,9 +128,10 @@ async def open_registry(
|
||||||
):
|
):
|
||||||
if preset_reg_addrs != addrs:
|
if preset_reg_addrs != addrs:
|
||||||
# if any(addr in preset_reg_addrs for addr in addrs):
|
# if any(addr in preset_reg_addrs for addr in addrs):
|
||||||
diff: set[
|
diff: set[RegistryAddress] = (
|
||||||
tuple[str, int]
|
set(preset_reg_addrs)
|
||||||
] = set(preset_reg_addrs) - set(addrs)
|
-set(addrs)
|
||||||
|
)
|
||||||
if diff:
|
if diff:
|
||||||
log.warning(
|
log.warning(
|
||||||
f'`{uid}` requested only subset of registrars: {addrs}\n'
|
f'`{uid}` requested only subset of registrars: {addrs}\n'
|
||||||
|
|
@ -123,7 +150,9 @@ async def open_registry(
|
||||||
and
|
and
|
||||||
not Registry.addrs
|
not Registry.addrs
|
||||||
):
|
):
|
||||||
Registry.addrs.extend(actor.reg_addrs)
|
Registry.addrs.extend(
|
||||||
|
_normalize_addresses(actor.reg_addrs)
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
ensure_exists
|
ensure_exists
|
||||||
|
|
@ -139,13 +168,13 @@ async def open_registry(
|
||||||
Registry.addrs = (
|
Registry.addrs = (
|
||||||
addrs
|
addrs
|
||||||
or
|
or
|
||||||
[_default_reg_addr]
|
_normalize_addresses([_default_reg_addr])
|
||||||
)
|
)
|
||||||
|
|
||||||
# NOTE: only spot this seems currently used is inside
|
# NOTE: only spot this seems currently used is inside
|
||||||
# `.ui._exec` which is the (eventual qtloops) bootstrapping
|
# `.ui._exec` which is the (eventual qtloops) bootstrapping
|
||||||
# with guest mode.
|
# with guest mode.
|
||||||
reg_addrs: list[tuple[str, str|int]] = Registry.addrs
|
reg_addrs: list[RegistryAddress] = Registry.addrs
|
||||||
# !TODO, a struct-API to stringently allow this only in special
|
# !TODO, a struct-API to stringently allow this only in special
|
||||||
# cases?
|
# cases?
|
||||||
# -> better would be to have some way to (atomically) rewrite
|
# -> better would be to have some way to (atomically) rewrite
|
||||||
|
|
@ -159,13 +188,13 @@ async def open_registry(
|
||||||
# next (set of) calls will apply whatever new one is passed
|
# next (set of) calls will apply whatever new one is passed
|
||||||
# in.
|
# in.
|
||||||
if was_set:
|
if was_set:
|
||||||
Registry.addrs = None
|
Registry.addrs = []
|
||||||
|
|
||||||
|
|
||||||
@acm
|
@acm
|
||||||
async def find_service(
|
async def find_service(
|
||||||
service_name: str,
|
service_name: str,
|
||||||
registry_addrs: list[tuple[str, int]] | None = None,
|
registry_addrs: list[RegistryAddress] | None = None,
|
||||||
|
|
||||||
first_only: bool = True,
|
first_only: bool = True,
|
||||||
|
|
||||||
|
|
@ -175,7 +204,7 @@ async def find_service(
|
||||||
| None
|
| None
|
||||||
):
|
):
|
||||||
# try:
|
# try:
|
||||||
reg_addrs: list[tuple[str, int|str]]
|
reg_addrs: list[RegistryAddress]
|
||||||
async with open_registry(
|
async with open_registry(
|
||||||
addrs=(
|
addrs=(
|
||||||
registry_addrs
|
registry_addrs
|
||||||
|
|
@ -219,16 +248,19 @@ async def find_service(
|
||||||
|
|
||||||
async def check_for_service(
|
async def check_for_service(
|
||||||
service_name: str,
|
service_name: str,
|
||||||
) -> None|tuple[str, int]:
|
) -> None|RegistryAddress:
|
||||||
'''
|
'''
|
||||||
Service daemon "liveness" predicate.
|
Service daemon "liveness" predicate.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
async with (
|
async with (
|
||||||
open_registry(ensure_exists=False) as reg_addr,
|
open_registry(
|
||||||
|
addrs=Registry.addrs,
|
||||||
|
ensure_exists=False,
|
||||||
|
) as reg_addrs,
|
||||||
tractor.query_actor(
|
tractor.query_actor(
|
||||||
service_name,
|
service_name,
|
||||||
arbiter_sockaddr=reg_addr,
|
regaddr=reg_addrs[0],
|
||||||
) as sockaddr,
|
) as (sockaddr, _),
|
||||||
):
|
):
|
||||||
return sockaddr
|
return sockaddr
|
||||||
|
|
|
||||||
|
|
@ -382,6 +382,9 @@ def quote_to_marketstore_structarray(
|
||||||
class MarketStoreError(Exception):
|
class MarketStoreError(Exception):
|
||||||
"Generic marketstore client error"
|
"Generic marketstore client error"
|
||||||
|
|
||||||
|
from tractor._exceptions import reg_err_types
|
||||||
|
reg_err_types([MarketStoreError])
|
||||||
|
|
||||||
|
|
||||||
# def err_on_resp(response: dict) -> None:
|
# def err_on_resp(response: dict) -> None:
|
||||||
# """Raise any errors found in responses from client request.
|
# """Raise any errors found in responses from client request.
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,13 @@ class StorageConnectionError(ConnectionError):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
from tractor._exceptions import reg_err_types
|
||||||
|
reg_err_types([
|
||||||
|
TimeseriesNotFound,
|
||||||
|
StorageConnectionError,
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
def get_storagemod(
|
def get_storagemod(
|
||||||
name: str,
|
name: str,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,7 @@ def ldshm(
|
||||||
# TODO: call null-seg fixer somehow?
|
# TODO: call null-seg fixer somehow?
|
||||||
if null_segs:
|
if null_segs:
|
||||||
|
|
||||||
if tractor._state.is_debug_mode():
|
if tractor.runtime._state.is_debug_mode():
|
||||||
await tractor.pause()
|
await tractor.pause()
|
||||||
# async with (
|
# async with (
|
||||||
# trio.open_nursery() as tn,
|
# trio.open_nursery() as tn,
|
||||||
|
|
|
||||||
|
|
@ -168,7 +168,7 @@ async def markup_gaps(
|
||||||
prev_r: pl.DataFrame = prev_row_by_i
|
prev_r: pl.DataFrame = prev_row_by_i
|
||||||
|
|
||||||
# debug any missing pre-row
|
# debug any missing pre-row
|
||||||
if tractor._state.is_debug_mode():
|
if tractor.runtime._state.is_debug_mode():
|
||||||
await tractor.pause()
|
await tractor.pause()
|
||||||
|
|
||||||
istart: int = prev_r['index'][0]
|
istart: int = prev_r['index'][0]
|
||||||
|
|
|
||||||
118
piker/ui/cli.py
118
piker/ui/cli.py
|
|
@ -22,7 +22,10 @@ import os
|
||||||
import click
|
import click
|
||||||
import tractor
|
import tractor
|
||||||
|
|
||||||
from ..cli import cli
|
from ..cli import (
|
||||||
|
cli,
|
||||||
|
load_trans_eps,
|
||||||
|
)
|
||||||
from .. import watchlists as wl
|
from .. import watchlists as wl
|
||||||
from ..service import maybe_spawn_brokerd
|
from ..service import maybe_spawn_brokerd
|
||||||
|
|
||||||
|
|
@ -159,67 +162,63 @@ def chart(
|
||||||
needed if not discovered via [network] config.
|
needed if not discovered via [network] config.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
# eg. ``--profile 3`` reports profiling for anything slower then 3 ms.
|
|
||||||
if profile is not None:
|
|
||||||
from .. import _profile
|
|
||||||
_profile._pg_profile = True
|
|
||||||
_profile.ms_slower_then = float(profile)
|
|
||||||
|
|
||||||
# Qt UI entrypoint
|
|
||||||
from ._app import _main
|
|
||||||
|
|
||||||
for symbol in symbols:
|
|
||||||
if '.' not in symbol:
|
|
||||||
click.echo(click.style(
|
|
||||||
f'symbol: {symbol} must have a {symbol}.<provider> suffix',
|
|
||||||
fg='red',
|
|
||||||
))
|
|
||||||
return
|
|
||||||
|
|
||||||
# global opts
|
|
||||||
# brokernames: list[str] = config['brokers']
|
|
||||||
brokermods = config['brokermods']
|
|
||||||
assert brokermods
|
|
||||||
tractorloglevel = config['tractorloglevel']
|
|
||||||
pikerloglevel = config['loglevel']
|
|
||||||
|
|
||||||
maddrs: list[tuple[str, int]] = config.get(
|
|
||||||
'maddrs',
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
|
|
||||||
# if maddrs:
|
|
||||||
# from tractor._multiaddr import parse_maddr
|
|
||||||
# for addr in maddrs:
|
|
||||||
# breakpoint()
|
|
||||||
# layers: dict = parse_maddr(addr)
|
|
||||||
|
|
||||||
regaddrs: list[tuple[str, int]] = config.get(
|
|
||||||
'registry_addrs',
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
|
|
||||||
from ..config import load
|
|
||||||
conf, _ = load(
|
|
||||||
conf_name='conf',
|
|
||||||
)
|
|
||||||
network: dict = conf.get('network')
|
|
||||||
if network:
|
|
||||||
from ..cli import load_trans_eps
|
|
||||||
eps: dict = load_trans_eps(
|
|
||||||
network,
|
|
||||||
maddrs,
|
|
||||||
)
|
|
||||||
for layers in eps['pikerd']:
|
|
||||||
regaddrs.append((
|
|
||||||
layers['ipv4']['addr'],
|
|
||||||
layers['tcp']['port'],
|
|
||||||
))
|
|
||||||
|
|
||||||
# breakpoint()
|
|
||||||
from tractor.devx import maybe_open_crash_handler
|
from tractor.devx import maybe_open_crash_handler
|
||||||
pdb: bool = config['pdb']
|
pdb: bool = config['pdb']
|
||||||
with maybe_open_crash_handler(pdb=pdb):
|
with maybe_open_crash_handler(pdb=pdb):
|
||||||
|
# eg. ``--profile 3`` reports profiling for anything slower then 3 ms.
|
||||||
|
if profile is not None:
|
||||||
|
from .. import _profile
|
||||||
|
_profile._pg_profile = True
|
||||||
|
_profile.ms_slower_then = float(profile)
|
||||||
|
|
||||||
|
# Qt UI entrypoint
|
||||||
|
from ._app import _main
|
||||||
|
|
||||||
|
for symbol in symbols:
|
||||||
|
if '.' not in symbol:
|
||||||
|
click.echo(click.style(
|
||||||
|
f'symbol: {symbol} must have a {symbol}.<provider> suffix',
|
||||||
|
fg='red',
|
||||||
|
))
|
||||||
|
return
|
||||||
|
|
||||||
|
# global opts
|
||||||
|
# brokernames: list[str] = config['brokers']
|
||||||
|
brokermods = config['brokermods']
|
||||||
|
assert brokermods
|
||||||
|
tractorloglevel = config['tractorloglevel']
|
||||||
|
pikerloglevel = config['loglevel']
|
||||||
|
|
||||||
|
# !TODO, allow declaring bind addr via maddr!
|
||||||
|
from ..config import load
|
||||||
|
conf, _ = load(
|
||||||
|
conf_name='conf',
|
||||||
|
)
|
||||||
|
|
||||||
|
regaddrs: list = config.get(
|
||||||
|
'registry_addrs',
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
chart_eps: list|None = None
|
||||||
|
network: dict = conf.get('network')
|
||||||
|
if network:
|
||||||
|
eps: dict = load_trans_eps(
|
||||||
|
network,
|
||||||
|
maddrs=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
# registry addrs: prefer `regd`, fall back
|
||||||
|
# to `pikerd` eps
|
||||||
|
reg_eps = eps.get(
|
||||||
|
'regd',
|
||||||
|
eps.get('pikerd')
|
||||||
|
)
|
||||||
|
assert reg_eps
|
||||||
|
regaddrs = [
|
||||||
|
addr.unwrap() for addr in reg_eps
|
||||||
|
]
|
||||||
|
chart_eps = eps.get('chart')
|
||||||
|
|
||||||
_main(
|
_main(
|
||||||
syms=symbols,
|
syms=symbols,
|
||||||
brokermods=brokermods,
|
brokermods=brokermods,
|
||||||
|
|
@ -229,6 +228,7 @@ def chart(
|
||||||
'loglevel': tractorloglevel,
|
'loglevel': tractorloglevel,
|
||||||
'name': 'chart',
|
'name': 'chart',
|
||||||
'registry_addrs': list(set(regaddrs)),
|
'registry_addrs': list(set(regaddrs)),
|
||||||
|
'tpt_bind_addrs': chart_eps,
|
||||||
'enable_modules': [
|
'enable_modules': [
|
||||||
|
|
||||||
# remote data-view annotations Bo
|
# remote data-view annotations Bo
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ async def stream_symbol_selection():
|
||||||
|
|
||||||
async def _async_main(
|
async def _async_main(
|
||||||
name: str,
|
name: str,
|
||||||
portal: tractor._portal.Portal,
|
portal: tractor.Portal,
|
||||||
symbols: List[str],
|
symbols: List[str],
|
||||||
brokermod: ModuleType,
|
brokermod: ModuleType,
|
||||||
loglevel: str = 'info',
|
loglevel: str = 'info',
|
||||||
|
|
|
||||||
|
|
@ -436,7 +436,7 @@ class OptionChain(object):
|
||||||
|
|
||||||
|
|
||||||
async def new_chain_ui(
|
async def new_chain_ui(
|
||||||
portal: tractor._portal.Portal,
|
portal: tractor.Portal,
|
||||||
symbol: str,
|
symbol: str,
|
||||||
brokermod: types.ModuleType,
|
brokermod: types.ModuleType,
|
||||||
rate: int = 1,
|
rate: int = 1,
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ name = "piker"
|
||||||
version = "0.1.0a0dev0"
|
version = "0.1.0a0dev0"
|
||||||
description = "trading gear for hackers"
|
description = "trading gear for hackers"
|
||||||
authors = [{ name = "Tyler Goodlet", email = "goodboy_foss@protonmail.com" }]
|
authors = [{ name = "Tyler Goodlet", email = "goodboy_foss@protonmail.com" }]
|
||||||
requires-python = ">=3.12, <3.14"
|
requires-python = ">=3.13, <3.14"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
readme = "README.rst"
|
readme = "README.rst"
|
||||||
keywords = [
|
keywords = [
|
||||||
|
|
@ -39,7 +39,6 @@ classifiers = [
|
||||||
"Operating System :: POSIX :: Linux",
|
"Operating System :: POSIX :: Linux",
|
||||||
"Programming Language :: Python :: Implementation :: CPython",
|
"Programming Language :: Python :: Implementation :: CPython",
|
||||||
"Programming Language :: Python :: 3 :: Only",
|
"Programming Language :: Python :: 3 :: Only",
|
||||||
"Programming Language :: Python :: 3.12",
|
|
||||||
"Programming Language :: Python :: 3.13",
|
"Programming Language :: Python :: 3.13",
|
||||||
"Intended Audience :: Financial and Insurance Industry",
|
"Intended Audience :: Financial and Insurance Industry",
|
||||||
"Intended Audience :: Science/Research",
|
"Intended Audience :: Science/Research",
|
||||||
|
|
@ -68,7 +67,7 @@ dependencies = [
|
||||||
"cryptofeed >=2.4.0, <3.0.0",
|
"cryptofeed >=2.4.0, <3.0.0",
|
||||||
"pyarrow>=18.0.0",
|
"pyarrow>=18.0.0",
|
||||||
"websockets ==12.0",
|
"websockets ==12.0",
|
||||||
"msgspec>=0.19.0,<0.20",
|
"msgspec>=0.20.0",
|
||||||
"tractor",
|
"tractor",
|
||||||
"tomlkit",
|
"tomlkit",
|
||||||
"trio-typing>=0.10.0",
|
"trio-typing>=0.10.0",
|
||||||
|
|
@ -132,7 +131,7 @@ repl = [
|
||||||
"greenback >=1.1.1, <2.0.0",
|
"greenback >=1.1.1, <2.0.0",
|
||||||
|
|
||||||
# @goodboy's preferred console toolz
|
# @goodboy's preferred console toolz
|
||||||
"xonsh>=0.22.2",
|
"xonsh>=0.24.2",
|
||||||
"prompt-toolkit ==3.0.40",
|
"prompt-toolkit ==3.0.40",
|
||||||
"pyperclip>=1.9.0",
|
"pyperclip>=1.9.0",
|
||||||
|
|
||||||
|
|
@ -203,7 +202,7 @@ pyvnc = { git = "https://github.com/regulad/pyvnc.git" }
|
||||||
# xonsh = { git = 'https://github.com/xonsh/xonsh.git', branch = 'main' }
|
# xonsh = { git = 'https://github.com/xonsh/xonsh.git', branch = 'main' }
|
||||||
|
|
||||||
# XXX since, we're like, always hacking new shite all-the-time. Bp
|
# XXX since, we're like, always hacking new shite all-the-time. Bp
|
||||||
tractor = { git = "https://github.com/goodboy/tractor.git", branch ="main" }
|
tractor = { git = "https://github.com/goodboy/tractor.git", branch = "wkt/addr_unpacking" }
|
||||||
# tractor = { git = "https://pikers.dev/goodboy/tractor", branch = "piker_pin" }
|
# tractor = { git = "https://pikers.dev/goodboy/tractor", branch = "piker_pin" }
|
||||||
# ------ goodboy ------
|
# ------ goodboy ------
|
||||||
# hackin dev-envs, usually there's something new he's hackin in..
|
# hackin dev-envs, usually there's something new he's hackin in..
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ pytest_plugins: tuple[str] = (
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
parser.addoption("--ll", action="store", dest='loglevel',
|
|
||||||
default=None, help="logging level to set when testing")
|
|
||||||
parser.addoption("--confdir", default=None,
|
parser.addoption("--confdir", default=None,
|
||||||
help="Use a practice API account")
|
help="Use a practice API account")
|
||||||
|
|
||||||
|
|
@ -92,8 +90,7 @@ def log(
|
||||||
@acm
|
@acm
|
||||||
async def _open_test_pikerd(
|
async def _open_test_pikerd(
|
||||||
tmpconfdir: str,
|
tmpconfdir: str,
|
||||||
|
reg_addr: tuple[str, int|str],
|
||||||
reg_addr: tuple[str, int] | None = None,
|
|
||||||
loglevel: str = 'warning',
|
loglevel: str = 'warning',
|
||||||
debug_mode: bool = False,
|
debug_mode: bool = False,
|
||||||
|
|
||||||
|
|
@ -113,16 +110,10 @@ async def _open_test_pikerd(
|
||||||
to boot the root actor / tractor runtime.
|
to boot the root actor / tractor runtime.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
import random
|
|
||||||
from piker.service import maybe_open_pikerd
|
from piker.service import maybe_open_pikerd
|
||||||
|
|
||||||
if reg_addr is None:
|
|
||||||
port = random.randint(6e3, 7e3)
|
|
||||||
reg_addr = ('127.0.0.1', port)
|
|
||||||
|
|
||||||
async with (
|
async with (
|
||||||
maybe_open_pikerd(
|
maybe_open_pikerd(
|
||||||
registry_addr=reg_addr,
|
registry_addrs=[reg_addr],
|
||||||
loglevel=loglevel,
|
loglevel=loglevel,
|
||||||
|
|
||||||
tractor_runtime_overrides={
|
tractor_runtime_overrides={
|
||||||
|
|
@ -139,13 +130,19 @@ async def _open_test_pikerd(
|
||||||
|
|
||||||
async with tractor.wait_for_actor(
|
async with tractor.wait_for_actor(
|
||||||
'pikerd',
|
'pikerd',
|
||||||
arbiter_sockaddr=reg_addr,
|
registry_addr=reg_addr,
|
||||||
) as portal:
|
) as portal:
|
||||||
raddr = portal.channel.raddr
|
raddr = portal.chan.raddr
|
||||||
assert raddr == reg_addr
|
uw_raddr: tuple = raddr.unwrap()
|
||||||
|
canonical_addr: tuple = (
|
||||||
|
tractor.discovery._addr.wrap_address(
|
||||||
|
reg_addr,
|
||||||
|
).unwrap()
|
||||||
|
)
|
||||||
|
assert uw_raddr == canonical_addr
|
||||||
yield (
|
yield (
|
||||||
raddr[0],
|
raddr._host,
|
||||||
raddr[1],
|
raddr._port,
|
||||||
portal,
|
portal,
|
||||||
service_manager,
|
service_manager,
|
||||||
)
|
)
|
||||||
|
|
@ -202,7 +199,10 @@ def open_test_pikerd(
|
||||||
request: pytest.FixtureRequest,
|
request: pytest.FixtureRequest,
|
||||||
tmp_path: Path,
|
tmp_path: Path,
|
||||||
tmpconfdir: Path,
|
tmpconfdir: Path,
|
||||||
|
|
||||||
|
# XXX from `tractor._testing.pytest` plugin
|
||||||
loglevel: str,
|
loglevel: str,
|
||||||
|
reg_addr: tuple,
|
||||||
):
|
):
|
||||||
|
|
||||||
tmpconfdir_str: str = str(tmpconfdir)
|
tmpconfdir_str: str = str(tmpconfdir)
|
||||||
|
|
@ -236,10 +236,13 @@ def open_test_pikerd(
|
||||||
# bwitout clobbering each other's config state.
|
# bwitout clobbering each other's config state.
|
||||||
tmpconfdir=tmpconfdir_str,
|
tmpconfdir=tmpconfdir_str,
|
||||||
|
|
||||||
# bind in level from fixture, which is itself set by
|
# NOTE these come verbatim from `tractor`'s builtin plugin!
|
||||||
# `--ll <value>` cli flag.
|
#
|
||||||
|
# per-tpt compat registrar address.
|
||||||
|
reg_addr=reg_addr,
|
||||||
|
# bind in level from fixture.
|
||||||
|
# (can be set with `--ll <value>` flag to `pytest`).
|
||||||
loglevel=loglevel,
|
loglevel=loglevel,
|
||||||
|
|
||||||
debug_mode=debug_mode,
|
debug_mode=debug_mode,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ def load_and_check_pos(
|
||||||
# is the same the fqme.
|
# is the same the fqme.
|
||||||
pp: Position = table.pps[ppmsg.symbol]
|
pp: Position = table.pps[ppmsg.symbol]
|
||||||
|
|
||||||
assert ppmsg.size == pp.size
|
assert ppmsg.size == pp.cumsize
|
||||||
assert ppmsg.avg_price == pp.ppu
|
assert ppmsg.avg_price == pp.ppu
|
||||||
|
|
||||||
yield pp
|
yield pp
|
||||||
|
|
@ -179,7 +179,7 @@ def test_ems_err_on_bad_broker(
|
||||||
# NOTE: emsd should error on the actor's enabled modules
|
# NOTE: emsd should error on the actor's enabled modules
|
||||||
# import phase, when looking for a backend named `doggy`.
|
# import phase, when looking for a backend named `doggy`.
|
||||||
except tractor.RemoteActorError as re:
|
except tractor.RemoteActorError as re:
|
||||||
assert re.type is ModuleNotFoundError
|
assert re.boxed_type is ModuleNotFoundError
|
||||||
|
|
||||||
run_and_tollerate_cancels(load_bad_fqme)
|
run_and_tollerate_cancels(load_bad_fqme)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,347 @@
|
||||||
|
'''
|
||||||
|
Cached feed broadcast ownership regressions.
|
||||||
|
|
||||||
|
'''
|
||||||
|
from contextlib import asynccontextmanager as acm
|
||||||
|
from types import SimpleNamespace
|
||||||
|
|
||||||
|
import tractor
|
||||||
|
import trio
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from piker.data import feed as feed_mod
|
||||||
|
from piker.data.flows import Flume
|
||||||
|
|
||||||
|
|
||||||
|
class FakeMsgStream:
|
||||||
|
'''
|
||||||
|
Duplex test stream backed by a real Tractor broadcaster.
|
||||||
|
|
||||||
|
'''
|
||||||
|
def __init__(self, broker: str) -> None:
|
||||||
|
self.broker: str = broker
|
||||||
|
self._ctx: object = object()
|
||||||
|
self._tx, rx = trio.open_memory_channel(8)
|
||||||
|
self._broadcaster = tractor.trionics.broadcast_receiver(
|
||||||
|
rx,
|
||||||
|
8,
|
||||||
|
)
|
||||||
|
self.children: list[
|
||||||
|
tractor.trionics.BroadcastReceiver,
|
||||||
|
] = []
|
||||||
|
self.controls: list[str] = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ctx(self) -> object:
|
||||||
|
'''
|
||||||
|
Expose the public context ref provided by `MsgStream.ctx`.
|
||||||
|
|
||||||
|
'''
|
||||||
|
return self._ctx
|
||||||
|
|
||||||
|
@acm
|
||||||
|
async def subscribe(self):
|
||||||
|
'''
|
||||||
|
Yield a real child receiver with duplex send delegation.
|
||||||
|
|
||||||
|
'''
|
||||||
|
child: tractor.trionics.BroadcastReceiver
|
||||||
|
async with self._broadcaster.subscribe() as child:
|
||||||
|
child.send = self.send
|
||||||
|
self.children.append(child)
|
||||||
|
yield child
|
||||||
|
|
||||||
|
async def send(self, msg: str) -> None:
|
||||||
|
'''
|
||||||
|
Record a pause or resume control sent through a child.
|
||||||
|
|
||||||
|
'''
|
||||||
|
self.controls.append(msg)
|
||||||
|
|
||||||
|
async def push(self, msg: dict) -> None:
|
||||||
|
'''
|
||||||
|
Send one provider quote into the broadcast source.
|
||||||
|
|
||||||
|
'''
|
||||||
|
await self._tx.send(msg)
|
||||||
|
|
||||||
|
async def close_source(self) -> None:
|
||||||
|
'''
|
||||||
|
End this provider without closing sibling relay channels.
|
||||||
|
|
||||||
|
'''
|
||||||
|
await self._tx.aclose()
|
||||||
|
|
||||||
|
|
||||||
|
def make_feed() -> tuple[
|
||||||
|
feed_mod.Feed,
|
||||||
|
dict[str, FakeMsgStream],
|
||||||
|
]:
|
||||||
|
'''
|
||||||
|
Build a real `Feed` and `Flume` graph for two providers.
|
||||||
|
|
||||||
|
'''
|
||||||
|
roots: dict[str, FakeMsgStream] = {
|
||||||
|
broker: FakeMsgStream(broker)
|
||||||
|
for broker in ('ib', 'deribit')
|
||||||
|
}
|
||||||
|
flumes: dict[str, Flume] = {
|
||||||
|
fqme: Flume(
|
||||||
|
mkt=SimpleNamespace(broker=broker),
|
||||||
|
first_quote={},
|
||||||
|
_rt_shm_token=SimpleNamespace(),
|
||||||
|
stream=roots[broker],
|
||||||
|
)
|
||||||
|
for fqme, broker in (
|
||||||
|
('nvda.nasdaq.ib', 'ib'),
|
||||||
|
('aapl.nasdaq.ib', 'ib'),
|
||||||
|
('btc-usd.deribit', 'deribit'),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
feed_mod.Feed(
|
||||||
|
mods={
|
||||||
|
broker: SimpleNamespace(name=broker)
|
||||||
|
for broker in roots
|
||||||
|
},
|
||||||
|
portals={},
|
||||||
|
flumes=flumes,
|
||||||
|
streams=roots,
|
||||||
|
status={},
|
||||||
|
),
|
||||||
|
roots,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('cache_hit', [False, True])
|
||||||
|
def test_cached_feed_returns_local_streams(
|
||||||
|
monkeypatch,
|
||||||
|
cache_hit: bool,
|
||||||
|
) -> None:
|
||||||
|
'''
|
||||||
|
A cached feed caller must not consume or replace shared streams.
|
||||||
|
|
||||||
|
`maybe_open_feed()` previously paired provider subscriptions with
|
||||||
|
`Feed.flumes.values()` using `zip()` and installed each child on the
|
||||||
|
cached `Flume`. One caller therefore exposed its lexical receiver
|
||||||
|
to every holder of the shared `Feed`; after exit those descriptors
|
||||||
|
pointed at closed children. The positional pairing also dropped a
|
||||||
|
market whenever one provider supplied multiple flumes.
|
||||||
|
|
||||||
|
Model two real provider broadcasters with two IB markets and one
|
||||||
|
Deribit market. Enter both first-owner and cache-hit paths, then
|
||||||
|
prove the yielded `Feed`, its `Feed.streams` mapping and all
|
||||||
|
`Flume`s are caller-local views. Exercise provider-context-wide
|
||||||
|
pause/resume and `Feed.open_multi_stream()` to show duplex sends
|
||||||
|
still reach the roots while each relay owns another child. Finally
|
||||||
|
prove every lexical child closes and all cached descriptors still
|
||||||
|
point at live roots.
|
||||||
|
|
||||||
|
'''
|
||||||
|
cached_feed: feed_mod.Feed
|
||||||
|
roots: dict[str, FakeMsgStream]
|
||||||
|
cached_feed, roots = make_feed()
|
||||||
|
cached_flumes: dict[str, Flume] = cached_feed.flumes
|
||||||
|
|
||||||
|
@acm
|
||||||
|
async def maybe_open_context(**kwargs):
|
||||||
|
'''
|
||||||
|
Return the controlled shared feed as a cache hit.
|
||||||
|
|
||||||
|
'''
|
||||||
|
yield cache_hit, cached_feed
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
feed_mod.trionics,
|
||||||
|
'maybe_open_context',
|
||||||
|
maybe_open_context,
|
||||||
|
)
|
||||||
|
|
||||||
|
local_feed: feed_mod.Feed|None = None
|
||||||
|
local_streams: dict[
|
||||||
|
str,
|
||||||
|
tractor.trionics.BroadcastReceiver,
|
||||||
|
]|None = None
|
||||||
|
|
||||||
|
async def main() -> None:
|
||||||
|
nonlocal local_feed, local_streams
|
||||||
|
feed: feed_mod.Feed
|
||||||
|
async with feed_mod.maybe_open_feed(
|
||||||
|
list(cached_flumes),
|
||||||
|
) as feed:
|
||||||
|
local_feed = feed
|
||||||
|
local_streams = feed.streams
|
||||||
|
assert feed is not cached_feed
|
||||||
|
assert feed.streams is not roots
|
||||||
|
assert feed.flumes is not cached_flumes
|
||||||
|
|
||||||
|
broker: str
|
||||||
|
stream: tractor.trionics.BroadcastReceiver
|
||||||
|
for broker, stream in feed.streams.items():
|
||||||
|
assert stream is roots[broker].children[0]
|
||||||
|
assert stream._ctx is roots[broker].ctx
|
||||||
|
|
||||||
|
fqme: str
|
||||||
|
flume: Flume
|
||||||
|
for fqme, flume in feed.flumes.items():
|
||||||
|
cached: Flume = cached_flumes[fqme]
|
||||||
|
|
||||||
|
stream: tractor.trionics.BroadcastReceiver = (
|
||||||
|
feed.streams[flume.mkt.broker]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert flume is not cached
|
||||||
|
assert flume.stream is stream
|
||||||
|
assert cached.stream is roots[flume.mkt.broker]
|
||||||
|
|
||||||
|
assert (
|
||||||
|
feed.flumes['nvda.nasdaq.ib'].stream
|
||||||
|
is feed.flumes['aapl.nasdaq.ib'].stream
|
||||||
|
)
|
||||||
|
|
||||||
|
await feed.pause()
|
||||||
|
await feed.resume()
|
||||||
|
assert all(
|
||||||
|
root.controls == ['pause', 'resume']
|
||||||
|
for root in roots.values()
|
||||||
|
)
|
||||||
|
|
||||||
|
stream: trio.MemoryReceiveChannel
|
||||||
|
async with feed.open_multi_stream() as stream:
|
||||||
|
assert all(
|
||||||
|
len(child._state.subs) == 3
|
||||||
|
for child in feed.streams.values()
|
||||||
|
)
|
||||||
|
await roots['ib'].push({'provider': 'ib'})
|
||||||
|
await roots['deribit'].push({
|
||||||
|
'provider': 'deribit',
|
||||||
|
})
|
||||||
|
with trio.fail_after(1):
|
||||||
|
msgs = {
|
||||||
|
(await stream.receive())['provider'],
|
||||||
|
(await stream.receive())['provider'],
|
||||||
|
}
|
||||||
|
assert msgs == {'ib', 'deribit'}
|
||||||
|
|
||||||
|
# One provider's EOC must close only its `tx` clone;
|
||||||
|
# the sibling relay continues publishing to `stream`.
|
||||||
|
await roots['ib'].close_source()
|
||||||
|
with trio.fail_after(1):
|
||||||
|
while (
|
||||||
|
len(feed.streams['ib']._state.subs)
|
||||||
|
!= 2
|
||||||
|
):
|
||||||
|
await trio.lowlevel.checkpoint()
|
||||||
|
|
||||||
|
await roots['deribit'].push({
|
||||||
|
'provider': 'deribit-after-ib-eoc',
|
||||||
|
})
|
||||||
|
msg: dict
|
||||||
|
msg = await stream.receive()
|
||||||
|
|
||||||
|
assert msg['provider'] == 'deribit-after-ib-eoc'
|
||||||
|
|
||||||
|
assert all(
|
||||||
|
len(child._state.subs) == 2
|
||||||
|
for child in feed.streams.values()
|
||||||
|
)
|
||||||
|
|
||||||
|
trio.run(main)
|
||||||
|
|
||||||
|
assert local_feed is not None
|
||||||
|
assert local_streams is not None
|
||||||
|
assert all(stream._closed for stream in local_streams.values())
|
||||||
|
assert all(
|
||||||
|
flume.stream is roots[flume.mkt.broker]
|
||||||
|
for flume in cached_flumes.values()
|
||||||
|
)
|
||||||
|
assert all(
|
||||||
|
len(root._broadcaster._state.subs) == 1
|
||||||
|
for root in roots.values()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_feed_cache_key_includes_shape_and_policy(
|
||||||
|
monkeypatch,
|
||||||
|
) -> None:
|
||||||
|
'''
|
||||||
|
Feed cache identity must include every resource-defining input.
|
||||||
|
|
||||||
|
The old `fqmes[0]` key aliased `[A]` with `[A, B]` and ignored
|
||||||
|
`tick_throttle`, `allow_overruns` and `start_stream`. Whichever
|
||||||
|
caller entered first silently determined later feed shape and
|
||||||
|
stream behavior, including reuse of a history-only remote feed for
|
||||||
|
a live quote request.
|
||||||
|
|
||||||
|
Capture the key passed to `maybe_open_context()` for reordered and
|
||||||
|
varied requests. Symbol order must normalize to one key, while the
|
||||||
|
full symbol set and each stream policy must produce distinct keys.
|
||||||
|
|
||||||
|
'''
|
||||||
|
feed: feed_mod.Feed = feed_mod.Feed(
|
||||||
|
mods={},
|
||||||
|
portals={},
|
||||||
|
flumes={},
|
||||||
|
streams={},
|
||||||
|
status={},
|
||||||
|
)
|
||||||
|
keys: list[tuple] = []
|
||||||
|
|
||||||
|
@acm
|
||||||
|
async def maybe_open_context(**kwargs):
|
||||||
|
'''
|
||||||
|
Capture cache identity without opening a remote feed.
|
||||||
|
|
||||||
|
'''
|
||||||
|
keys.append(kwargs['key'])
|
||||||
|
yield False, feed
|
||||||
|
|
||||||
|
@acm
|
||||||
|
async def gather_contexts(mngrs):
|
||||||
|
'''
|
||||||
|
Permit the metadata-only empty feed used by this key probe.
|
||||||
|
|
||||||
|
'''
|
||||||
|
assert not mngrs
|
||||||
|
yield ()
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
feed_mod.trionics,
|
||||||
|
'maybe_open_context',
|
||||||
|
maybe_open_context,
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
feed_mod.trionics,
|
||||||
|
'gather_contexts',
|
||||||
|
gather_contexts,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def open_once(
|
||||||
|
fqmes: list[str],
|
||||||
|
**kwargs,
|
||||||
|
) -> None:
|
||||||
|
async with feed_mod.maybe_open_feed(
|
||||||
|
fqmes,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def main() -> None:
|
||||||
|
await open_once(['a.ib', 'b.ib'])
|
||||||
|
await open_once(['b.ib', 'a.ib'])
|
||||||
|
await open_once(['a.ib'])
|
||||||
|
await open_once(['a.ib', 'b.ib'], tick_throttle=10)
|
||||||
|
await open_once(
|
||||||
|
['a.ib', 'b.ib'],
|
||||||
|
allow_overruns=False,
|
||||||
|
)
|
||||||
|
await open_once(
|
||||||
|
['a.ib', 'b.ib'],
|
||||||
|
start_stream=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
trio.run(main)
|
||||||
|
|
||||||
|
assert keys[0] == keys[1]
|
||||||
|
assert len(set(keys[2:])) == 4
|
||||||
|
assert keys[0] not in keys[2:]
|
||||||
|
|
@ -23,13 +23,35 @@ from piker.accounting import (
|
||||||
'fqmes',
|
'fqmes',
|
||||||
[
|
[
|
||||||
# binance
|
# binance
|
||||||
(100, {'btcusdt.binance', 'ethusdt.binance'}, False),
|
(100, {
|
||||||
|
# !TODO, write a suite which validates raising against
|
||||||
|
# bad/legacy fqmes such as this!
|
||||||
|
# 'btcusdt.binance',
|
||||||
|
'btcusdt.spot.binance',
|
||||||
|
'ethusdt.spot.binance',
|
||||||
|
}, False),
|
||||||
|
|
||||||
# kraken
|
# kraken
|
||||||
(20, {'ethusdt.kraken', 'xbtusd.kraken'}, True),
|
(20, {
|
||||||
|
# !TODO, write a suite which validates raising against
|
||||||
|
# bad/legacy fqmes such as this!
|
||||||
|
# 'ethusdt.kraken',
|
||||||
|
# 'xbtusd.kraken',
|
||||||
|
|
||||||
|
'ethusdt.spot.kraken',
|
||||||
|
'xbtusd.spot.kraken',
|
||||||
|
}, True),
|
||||||
|
|
||||||
# binance + kraken
|
# binance + kraken
|
||||||
(100, {'btcusdt.binance', 'xbtusd.kraken'}, False),
|
(100, {
|
||||||
|
# !TODO, write a suite which validates raising against
|
||||||
|
# bad/legacy fqmes such as this!
|
||||||
|
# 'btcusdt.binance',
|
||||||
|
# 'xbtusd.kraken',
|
||||||
|
|
||||||
|
'btcusdt.spot.binance',
|
||||||
|
'xbtusd.spot.kraken',
|
||||||
|
}, False),
|
||||||
],
|
],
|
||||||
ids=lambda param: f'quotes={param[0]}@fqmes={param[1]}',
|
ids=lambda param: f'quotes={param[0]}@fqmes={param[1]}',
|
||||||
)
|
)
|
||||||
|
|
@ -48,12 +70,17 @@ def test_multi_fqsn_feed(
|
||||||
|
|
||||||
if (
|
if (
|
||||||
ci_env
|
ci_env
|
||||||
and not run_in_ci
|
and
|
||||||
|
not run_in_ci
|
||||||
):
|
):
|
||||||
pytest.skip('Skipping CI disabled test due to feed restrictions')
|
pytest.skip(
|
||||||
|
'CI-disabled-test due to live-feed restrictions'
|
||||||
|
)
|
||||||
|
|
||||||
brokers = set()
|
brokers = set()
|
||||||
for fqme in fqmes:
|
for fqme in fqmes:
|
||||||
|
# ?TODO, add this unpack + normalize check to a symbology
|
||||||
|
# helper fn?
|
||||||
brokername, *_ = unpack_fqme(fqme)
|
brokername, *_ = unpack_fqme(fqme)
|
||||||
brokers.add(brokername)
|
brokers.add(brokername)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
'''
|
||||||
|
IB cached quote-channel ownership regressions.
|
||||||
|
|
||||||
|
'''
|
||||||
|
from contextlib import asynccontextmanager as acm
|
||||||
|
|
||||||
|
import tractor
|
||||||
|
import trio
|
||||||
|
|
||||||
|
from piker.brokers.ib import feed
|
||||||
|
|
||||||
|
|
||||||
|
def test_quote_stream_caches_channel_and_owns_child(
|
||||||
|
monkeypatch,
|
||||||
|
) -> None:
|
||||||
|
'''
|
||||||
|
IB quote callers must share one cached channel through child cursors.
|
||||||
|
|
||||||
|
`open_aio_quote_stream()` previously stored the first caller's raw
|
||||||
|
`LinkedTaskChannel` in `_quote_streams`, yielded that root directly,
|
||||||
|
and wrapped the same source in a new broadcaster for each later
|
||||||
|
caller. The first caller therefore owned source lifetime while
|
||||||
|
competing roots split quote receives between concurrent users.
|
||||||
|
|
||||||
|
Stub `maybe_open_context()` with one retained channel and enter a
|
||||||
|
miss owner plus concurrent hit. Prove both receive the same quote
|
||||||
|
through distinct children of one broadcaster, the hit closes
|
||||||
|
independently, and the owner keeps receiving until its own exit.
|
||||||
|
Also verify both calls request the same symbol cache key.
|
||||||
|
|
||||||
|
'''
|
||||||
|
class FakeLinkedTaskChannel:
|
||||||
|
'''
|
||||||
|
Retain one real broadcaster and expose child subscriptions.
|
||||||
|
|
||||||
|
'''
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._tx: trio.MemorySendChannel
|
||||||
|
rx: trio.MemoryReceiveChannel
|
||||||
|
self._tx, rx = trio.open_memory_channel(8)
|
||||||
|
self._broadcaster: (
|
||||||
|
tractor.trionics.BroadcastReceiver
|
||||||
|
) = tractor.trionics.broadcast_receiver(
|
||||||
|
rx,
|
||||||
|
8,
|
||||||
|
)
|
||||||
|
|
||||||
|
@acm
|
||||||
|
async def subscribe(self):
|
||||||
|
'''
|
||||||
|
Yield one caller-owned child from the retained root.
|
||||||
|
|
||||||
|
'''
|
||||||
|
child: tractor.trionics.BroadcastReceiver
|
||||||
|
async with self._broadcaster.subscribe() as child:
|
||||||
|
yield child
|
||||||
|
|
||||||
|
async def push(self, msg: dict) -> None:
|
||||||
|
'''
|
||||||
|
Send one ticker through the retained source channel.
|
||||||
|
|
||||||
|
'''
|
||||||
|
await self._tx.send(msg)
|
||||||
|
|
||||||
|
chan: FakeLinkedTaskChannel = FakeLinkedTaskChannel()
|
||||||
|
context_entries: int = 0
|
||||||
|
keys: list[str] = []
|
||||||
|
acm_funcs: list = []
|
||||||
|
|
||||||
|
@acm
|
||||||
|
async def maybe_open_context(**kwargs):
|
||||||
|
'''
|
||||||
|
Return one retained channel as a miss followed by a hit.
|
||||||
|
|
||||||
|
'''
|
||||||
|
nonlocal context_entries
|
||||||
|
keys.append(kwargs['key'])
|
||||||
|
acm_funcs.append(kwargs['acm_func'])
|
||||||
|
cache_hit: bool = context_entries > 0
|
||||||
|
context_entries += 1
|
||||||
|
yield cache_hit, chan
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
feed.tractor.trionics,
|
||||||
|
'maybe_open_context',
|
||||||
|
maybe_open_context,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def main() -> None:
|
||||||
|
owner: tractor.trionics.BroadcastReceiver
|
||||||
|
async with feed.open_aio_quote_stream(
|
||||||
|
'NVDA',
|
||||||
|
) as owner:
|
||||||
|
hit: tractor.trionics.BroadcastReceiver
|
||||||
|
async with feed.open_aio_quote_stream(
|
||||||
|
'NVDA',
|
||||||
|
) as hit:
|
||||||
|
assert hit is not owner
|
||||||
|
assert len(chan._broadcaster._state.subs) == 3
|
||||||
|
|
||||||
|
await chan.push({'value': 1})
|
||||||
|
assert await owner.receive() == {'value': 1}
|
||||||
|
assert await hit.receive() == {'value': 1}
|
||||||
|
|
||||||
|
assert hit._closed
|
||||||
|
assert not owner._closed
|
||||||
|
assert len(chan._broadcaster._state.subs) == 2
|
||||||
|
|
||||||
|
await chan.push({'value': 2})
|
||||||
|
assert await owner.receive() == {'value': 2}
|
||||||
|
|
||||||
|
assert owner._closed
|
||||||
|
assert len(chan._broadcaster._state.subs) == 1
|
||||||
|
assert keys == ['NVDA', 'NVDA']
|
||||||
|
assert acm_funcs == [
|
||||||
|
feed._open_aio_quote_channel,
|
||||||
|
feed._open_aio_quote_channel,
|
||||||
|
]
|
||||||
|
|
||||||
|
trio.run(main)
|
||||||
|
|
@ -0,0 +1,271 @@
|
||||||
|
'''
|
||||||
|
IB asyncio method-proxy regressions.
|
||||||
|
|
||||||
|
'''
|
||||||
|
from types import SimpleNamespace
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import trio
|
||||||
|
|
||||||
|
from piker.brokers.ib import api as ib_api
|
||||||
|
from piker.brokers.ib.api import (
|
||||||
|
MethodProxy,
|
||||||
|
relay_client_proxy_messages,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class FakeChannel:
|
||||||
|
'''
|
||||||
|
Model the Trio side of an asyncio linked-task channel.
|
||||||
|
|
||||||
|
'''
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.requests: list[tuple] = []
|
||||||
|
(
|
||||||
|
self._tx,
|
||||||
|
self._rx,
|
||||||
|
) = trio.open_memory_channel[Any](10)
|
||||||
|
|
||||||
|
async def send(self, msg: tuple) -> None:
|
||||||
|
'''
|
||||||
|
Capture one Trio-to-asyncio method request.
|
||||||
|
|
||||||
|
'''
|
||||||
|
self.requests.append(msg)
|
||||||
|
|
||||||
|
async def receive(self) -> Any:
|
||||||
|
'''
|
||||||
|
Receive one simulated asyncio-to-Trio response.
|
||||||
|
|
||||||
|
'''
|
||||||
|
return await self._rx.receive()
|
||||||
|
|
||||||
|
def closed(self) -> bool:
|
||||||
|
'''
|
||||||
|
Report an open channel for the lifetime of each test.
|
||||||
|
|
||||||
|
'''
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def respond(self, msg: Any) -> None:
|
||||||
|
'''
|
||||||
|
Send one response or status event to the proxy relay.
|
||||||
|
|
||||||
|
'''
|
||||||
|
await self._tx.send(msg)
|
||||||
|
|
||||||
|
async def close_responses(self) -> None:
|
||||||
|
'''
|
||||||
|
Close the simulated asyncio-to-Trio response channel.
|
||||||
|
|
||||||
|
'''
|
||||||
|
await self._tx.aclose()
|
||||||
|
|
||||||
|
|
||||||
|
def test_method_proxy_routes_after_idle_status_events() -> None:
|
||||||
|
'''
|
||||||
|
Idle IB status traffic must not break first-symbol qualification.
|
||||||
|
|
||||||
|
``open_client_proxy()`` previously broadcast a one-slot channel
|
||||||
|
to an always-running status relay and an idle method receiver.
|
||||||
|
Status events advanced only the relay, so a first order for an
|
||||||
|
uncached symbol raised ``Lagged`` before receiving
|
||||||
|
``get_sym_details()``. Feed several idle events through the
|
||||||
|
sole-reader relay, then start two method calls and return their
|
||||||
|
responses in reverse order. Both exact results prove status
|
||||||
|
traffic cannot overrun a dormant caller and concurrent responses
|
||||||
|
remain correlated by request ID.
|
||||||
|
|
||||||
|
'''
|
||||||
|
async def main() -> None:
|
||||||
|
chan = FakeChannel()
|
||||||
|
proxy = MethodProxy(
|
||||||
|
chan,
|
||||||
|
event_table={},
|
||||||
|
asyncio_ns=SimpleNamespace(),
|
||||||
|
)
|
||||||
|
results: dict[str, str] = {}
|
||||||
|
|
||||||
|
async def call(name: str) -> None:
|
||||||
|
results[name] = await proxy._run_method(meth=name)
|
||||||
|
|
||||||
|
async with trio.open_nursery() as nursery:
|
||||||
|
nursery.start_soon(
|
||||||
|
relay_client_proxy_messages,
|
||||||
|
chan,
|
||||||
|
proxy,
|
||||||
|
)
|
||||||
|
for i in range(3):
|
||||||
|
await chan.respond((
|
||||||
|
'event',
|
||||||
|
{'reason': f'farm-status-{i}'},
|
||||||
|
))
|
||||||
|
|
||||||
|
nursery.start_soon(call, 'first')
|
||||||
|
nursery.start_soon(call, 'second')
|
||||||
|
with trio.fail_after(0.1):
|
||||||
|
while len(chan.requests) < 2:
|
||||||
|
await trio.lowlevel.checkpoint()
|
||||||
|
|
||||||
|
mids: dict[str, int] = {
|
||||||
|
meth: mid
|
||||||
|
for meth, _kwargs, mid in chan.requests
|
||||||
|
}
|
||||||
|
await chan.respond({
|
||||||
|
'mid': mids['second'],
|
||||||
|
'result': 'second-result',
|
||||||
|
})
|
||||||
|
await chan.respond({
|
||||||
|
'mid': mids['first'],
|
||||||
|
'result': 'first-result',
|
||||||
|
})
|
||||||
|
with trio.fail_after(0.1):
|
||||||
|
while len(results) < 2:
|
||||||
|
await trio.lowlevel.checkpoint()
|
||||||
|
nursery.cancel_scope.cancel()
|
||||||
|
|
||||||
|
assert results == {
|
||||||
|
'first': 'first-result',
|
||||||
|
'second': 'second-result',
|
||||||
|
}
|
||||||
|
|
||||||
|
trio.run(main)
|
||||||
|
|
||||||
|
|
||||||
|
def test_method_proxy_relay_accepts_clean_eof() -> None:
|
||||||
|
'''
|
||||||
|
Normal asyncio relay completion must not fail proxy teardown.
|
||||||
|
|
||||||
|
The sole-reader relay blocks in ``LinkedTaskChannel.receive()``
|
||||||
|
until the asyncio task exits and closes its Trio send channel.
|
||||||
|
Close the fake response sender before entering the relay and
|
||||||
|
prove the resulting ``EndOfChannel`` is graceful completion.
|
||||||
|
|
||||||
|
'''
|
||||||
|
async def main() -> None:
|
||||||
|
chan = FakeChannel()
|
||||||
|
proxy = MethodProxy(
|
||||||
|
chan,
|
||||||
|
event_table={},
|
||||||
|
asyncio_ns=SimpleNamespace(),
|
||||||
|
)
|
||||||
|
await chan.close_responses()
|
||||||
|
with trio.fail_after(0.1):
|
||||||
|
await relay_client_proxy_messages(chan, proxy)
|
||||||
|
|
||||||
|
trio.run(main)
|
||||||
|
|
||||||
|
|
||||||
|
def test_method_proxy_drops_cancelled_call_response() -> None:
|
||||||
|
'''
|
||||||
|
A cancelled symbol search must not skew the next method response.
|
||||||
|
|
||||||
|
Search timeouts can cancel a Trio caller after its request
|
||||||
|
reaches the asyncio client. Wait until one request is sent,
|
||||||
|
cancel its caller, and then deliver the orphaned response. The
|
||||||
|
sole-reader relay must drop that stale ``mid`` without failing; a
|
||||||
|
subsequent call must still receive its own exact response.
|
||||||
|
|
||||||
|
'''
|
||||||
|
async def main() -> None:
|
||||||
|
chan = FakeChannel()
|
||||||
|
proxy = MethodProxy(
|
||||||
|
chan,
|
||||||
|
event_table={},
|
||||||
|
asyncio_ns=SimpleNamespace(),
|
||||||
|
)
|
||||||
|
call_scope = trio.CancelScope()
|
||||||
|
cancelled = trio.Event()
|
||||||
|
result: list[str] = []
|
||||||
|
|
||||||
|
async def cancelled_call() -> None:
|
||||||
|
with call_scope:
|
||||||
|
try:
|
||||||
|
await proxy._run_method(meth='cancelled')
|
||||||
|
finally:
|
||||||
|
cancelled.set()
|
||||||
|
|
||||||
|
async def next_call() -> None:
|
||||||
|
value = await proxy._run_method(meth='next')
|
||||||
|
result.append(value)
|
||||||
|
|
||||||
|
async with trio.open_nursery() as nursery:
|
||||||
|
nursery.start_soon(
|
||||||
|
relay_client_proxy_messages,
|
||||||
|
chan,
|
||||||
|
proxy,
|
||||||
|
)
|
||||||
|
nursery.start_soon(cancelled_call)
|
||||||
|
with trio.fail_after(0.1):
|
||||||
|
while len(chan.requests) < 1:
|
||||||
|
await trio.lowlevel.checkpoint()
|
||||||
|
cancelled_mid: int = chan.requests[0][2]
|
||||||
|
call_scope.cancel()
|
||||||
|
with trio.fail_after(0.1):
|
||||||
|
await cancelled.wait()
|
||||||
|
assert proxy._pending == {}
|
||||||
|
assert (
|
||||||
|
proxy._request_methods[cancelled_mid]
|
||||||
|
==
|
||||||
|
'cancelled'
|
||||||
|
)
|
||||||
|
|
||||||
|
await chan.respond({
|
||||||
|
'mid': cancelled_mid,
|
||||||
|
'result': 'stale',
|
||||||
|
})
|
||||||
|
with trio.fail_after(0.1):
|
||||||
|
while cancelled_mid in proxy._request_methods:
|
||||||
|
await trio.lowlevel.checkpoint()
|
||||||
|
nursery.start_soon(next_call)
|
||||||
|
with trio.fail_after(0.1):
|
||||||
|
while len(chan.requests) < 2:
|
||||||
|
await trio.lowlevel.checkpoint()
|
||||||
|
next_mid: int = chan.requests[1][2]
|
||||||
|
await chan.respond({
|
||||||
|
'mid': next_mid,
|
||||||
|
'result': 'fresh',
|
||||||
|
})
|
||||||
|
with trio.fail_after(0.1):
|
||||||
|
while not result:
|
||||||
|
await trio.lowlevel.checkpoint()
|
||||||
|
nursery.cancel_scope.cancel()
|
||||||
|
|
||||||
|
assert result == ['fresh']
|
||||||
|
|
||||||
|
trio.run(main)
|
||||||
|
|
||||||
|
|
||||||
|
def test_method_proxy_warns_when_metadata_is_evicted(
|
||||||
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
|
) -> None:
|
||||||
|
'''
|
||||||
|
Unresolved metadata eviction must remain operator-visible.
|
||||||
|
|
||||||
|
Cancelled calls whose asyncio responses never arrive retain a
|
||||||
|
bounded method name solely for later stale-response diagnostics.
|
||||||
|
Fill that table beyond its limit and prove the oldest entry is
|
||||||
|
evicted with its request ID, method name, and configured bound in
|
||||||
|
the warning.
|
||||||
|
|
||||||
|
'''
|
||||||
|
proxy = MethodProxy(
|
||||||
|
FakeChannel(),
|
||||||
|
event_table={},
|
||||||
|
asyncio_ns=SimpleNamespace(),
|
||||||
|
)
|
||||||
|
warnings: list[str] = []
|
||||||
|
monkeypatch.setattr(ib_api.log, 'warning', warnings.append)
|
||||||
|
|
||||||
|
for mid in range(257):
|
||||||
|
proxy._track_request_method(mid, f'method-{mid}')
|
||||||
|
|
||||||
|
assert len(proxy._request_methods) == 256
|
||||||
|
assert 0 not in proxy._request_methods
|
||||||
|
assert warnings == [
|
||||||
|
'Evicting unresolved method-request metadata,\n'
|
||||||
|
'mid: 0\n'
|
||||||
|
"meth: 'method-0'\n"
|
||||||
|
'pending metadata limit: 256\n'
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
'''
|
||||||
|
Package logger namespace regression tests.
|
||||||
|
|
||||||
|
'''
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from piker.log import (
|
||||||
|
get_console_log,
|
||||||
|
get_logger,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'factory',
|
||||||
|
[
|
||||||
|
get_logger,
|
||||||
|
get_console_log,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'name',
|
||||||
|
[
|
||||||
|
'piker.service._daemon',
|
||||||
|
'piker.paper',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_package_logger_name(
|
||||||
|
factory,
|
||||||
|
name: str,
|
||||||
|
):
|
||||||
|
'''
|
||||||
|
`str.lstrip('piker.')` treated the package prefix as a set of
|
||||||
|
removable characters. A submodule beginning with any of those
|
||||||
|
characters, such as `piker.paper`, was silently renamed to
|
||||||
|
`piker.aper`, while service code asserted a stale parent name.
|
||||||
|
|
||||||
|
Exercise both logger factories with service and prefix-sensitive
|
||||||
|
submodule names, proving they retain the exact requested package
|
||||||
|
namespace.
|
||||||
|
|
||||||
|
'''
|
||||||
|
log = factory(name=name)
|
||||||
|
|
||||||
|
assert log.name == name
|
||||||
|
|
@ -7,6 +7,7 @@ from typing import (
|
||||||
Callable,
|
Callable,
|
||||||
)
|
)
|
||||||
from contextlib import asynccontextmanager as acm
|
from contextlib import asynccontextmanager as acm
|
||||||
|
from types import SimpleNamespace
|
||||||
|
|
||||||
from exceptiongroup import BaseExceptionGroup
|
from exceptiongroup import BaseExceptionGroup
|
||||||
import pytest
|
import pytest
|
||||||
|
|
@ -17,6 +18,7 @@ from piker.service import (
|
||||||
find_service,
|
find_service,
|
||||||
Services,
|
Services,
|
||||||
)
|
)
|
||||||
|
from piker.service import _registry
|
||||||
from piker.data import (
|
from piker.data import (
|
||||||
open_feed,
|
open_feed,
|
||||||
)
|
)
|
||||||
|
|
@ -53,11 +55,17 @@ def test_runtime_boot(
|
||||||
|
|
||||||
tractor.wait_for_actor(
|
tractor.wait_for_actor(
|
||||||
'pikerd',
|
'pikerd',
|
||||||
arbiter_sockaddr=daemon_addr,
|
registry_addr=daemon_addr,
|
||||||
) as portal,
|
) as portal,
|
||||||
):
|
):
|
||||||
assert pikerd_portal.channel.raddr == daemon_addr
|
uw_raddr: tuple = pikerd_portal.chan.raddr.unwrap()
|
||||||
assert pikerd_portal.channel.raddr == portal.channel.raddr
|
canonical_addr: tuple = (
|
||||||
|
_registry._normalize_addresses(
|
||||||
|
[daemon_addr],
|
||||||
|
)[0]
|
||||||
|
)
|
||||||
|
assert uw_raddr == canonical_addr
|
||||||
|
assert uw_raddr == portal.chan.raddr.unwrap()
|
||||||
|
|
||||||
# no service tasks should be started
|
# no service tasks should be started
|
||||||
assert not services.service_tasks
|
assert not services.service_tasks
|
||||||
|
|
@ -65,6 +73,53 @@ def test_runtime_boot(
|
||||||
trio.run(main)
|
trio.run(main)
|
||||||
|
|
||||||
|
|
||||||
|
def test_registry_normalizes_tagged_addresses(
|
||||||
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
|
):
|
||||||
|
'''
|
||||||
|
Tractor now emits tagged registry addresses while existing Piker
|
||||||
|
callers still pass legacy socket pairs. Direct list and set
|
||||||
|
comparisons treated the two forms as different and retained the
|
||||||
|
legacy value in `Registry.addrs`.
|
||||||
|
|
||||||
|
Seed `Registry.addrs` with a legacy pair, request the equivalent
|
||||||
|
tagged address, and enter `open_registry()` as a root actor. The
|
||||||
|
yielded and stored values must both use tractor's canonical form.
|
||||||
|
|
||||||
|
'''
|
||||||
|
legacy = ('127.0.0.1', 6116)
|
||||||
|
tagged = ('tcp', '127.0.0.1', 6116)
|
||||||
|
actor = SimpleNamespace(
|
||||||
|
aid=SimpleNamespace(uid=('test', 'uid')),
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
tractor,
|
||||||
|
'current_actor',
|
||||||
|
lambda: actor,
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
tractor,
|
||||||
|
'is_root_process',
|
||||||
|
lambda: True,
|
||||||
|
)
|
||||||
|
_registry.Registry.addrs = [legacy]
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
async with _registry.open_registry(
|
||||||
|
[tagged],
|
||||||
|
) as addrs:
|
||||||
|
assert addrs == [tagged]
|
||||||
|
assert _registry.Registry.addrs == [tagged]
|
||||||
|
assert _registry._tractor_kwargs[
|
||||||
|
'registry_addrs'
|
||||||
|
] == [tagged]
|
||||||
|
|
||||||
|
try:
|
||||||
|
trio.run(main)
|
||||||
|
finally:
|
||||||
|
_registry.Registry.addrs = []
|
||||||
|
|
||||||
|
|
||||||
def test_ensure_datafeed_actors(
|
def test_ensure_datafeed_actors(
|
||||||
open_test_pikerd: AsyncContextManager,
|
open_test_pikerd: AsyncContextManager,
|
||||||
loglevel: str,
|
loglevel: str,
|
||||||
|
|
@ -108,7 +163,7 @@ async def ensure_service(
|
||||||
sockaddr: tuple[str, int] | None = None,
|
sockaddr: tuple[str, int] | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
async with find_service(name) as portal:
|
async with find_service(name) as portal:
|
||||||
remote_sockaddr = portal.channel.raddr
|
remote_sockaddr: tuple = portal.chan.raddr.unwrap()
|
||||||
print(f'FOUND `{name}` @ {remote_sockaddr}')
|
print(f'FOUND `{name}` @ {remote_sockaddr}')
|
||||||
|
|
||||||
if sockaddr:
|
if sockaddr:
|
||||||
|
|
@ -131,40 +186,49 @@ def run_test_w_cancel_method(
|
||||||
"was remotely cancelled by remote actor (\'pikerd\'")
|
"was remotely cancelled by remote actor (\'pikerd\'")
|
||||||
|
|
||||||
if cancel_method == 'sigint':
|
if cancel_method == 'sigint':
|
||||||
with pytest.raises(
|
# XXX: with modern `tractor` the (single-exc)
|
||||||
|
# group is collapsed so a bare KBI normally
|
||||||
|
# propagates; tolerate either form.
|
||||||
|
with pytest.raises((
|
||||||
|
KeyboardInterrupt,
|
||||||
BaseExceptionGroup,
|
BaseExceptionGroup,
|
||||||
) as exc_info:
|
)) as exc_info:
|
||||||
trio.run(main)
|
trio.run(main)
|
||||||
|
|
||||||
multi = exc_info.value
|
err = exc_info.value
|
||||||
|
match err:
|
||||||
|
case BaseExceptionGroup():
|
||||||
|
for suberr in err.exceptions:
|
||||||
|
match suberr:
|
||||||
|
# ensure we receive a remote
|
||||||
|
# cancellation error caused by the
|
||||||
|
# pikerd root actor.
|
||||||
|
case tractor.ContextCancelled():
|
||||||
|
assert (
|
||||||
|
cancelled_msg
|
||||||
|
in
|
||||||
|
suberr.args[0]
|
||||||
|
)
|
||||||
|
|
||||||
for suberr in multi.exceptions:
|
case KeyboardInterrupt():
|
||||||
match suberr:
|
pass
|
||||||
# ensure we receive a remote cancellation error caused
|
|
||||||
# by the pikerd root actor since we used the
|
|
||||||
# `.cancel_service()` API above B)
|
|
||||||
case tractor.ContextCancelled():
|
|
||||||
assert cancelled_msg in suberr.args[0]
|
|
||||||
|
|
||||||
case KeyboardInterrupt():
|
case _:
|
||||||
pass
|
pytest.fail(
|
||||||
|
f'Unexpected error {suberr}'
|
||||||
|
)
|
||||||
|
|
||||||
case _:
|
case KeyboardInterrupt():
|
||||||
pytest.fail(f'Unexpected error {suberr}')
|
pass
|
||||||
|
|
||||||
elif cancel_method == 'services':
|
elif cancel_method == 'services':
|
||||||
|
# XXX: cancelling our own sub-service via
|
||||||
# XXX NOTE: oddly, when you pass --pdb to pytest, i think since
|
# `Services.cancel_service()` is a *self*
|
||||||
# we also use that to enable the underlying tractor debug mode,
|
# requested cancel: modern `tractor` absorbs the
|
||||||
# it causes this to not raise for some reason? So if you see
|
# resulting `ContextCancelled` (canceller is our
|
||||||
# that while changing this test.. it's prolly that.
|
# own actor) so the runtime tears down gracefully
|
||||||
|
# with NO error raised to the opener.
|
||||||
with pytest.raises(
|
trio.run(main)
|
||||||
tractor.ContextCancelled
|
|
||||||
) as exc_info:
|
|
||||||
trio.run(main)
|
|
||||||
|
|
||||||
assert cancelled_msg in exc_info.value.args[0]
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
pytest.fail(f'Test is broken due to {cancel_method}')
|
pytest.fail(f'Test is broken due to {cancel_method}')
|
||||||
|
|
@ -197,7 +261,9 @@ def test_ensure_ems_in_paper_actors(
|
||||||
# ensure we timeout after is startup is too slow.
|
# ensure we timeout after is startup is too slow.
|
||||||
# TODO: something like this should be our start point for
|
# TODO: something like this should be our start point for
|
||||||
# benchmarking end-to-end startup B)
|
# benchmarking end-to-end startup B)
|
||||||
with trio.fail_after(9):
|
# NOTE: includes a live (kraken) symbology fetch so
|
||||||
|
# the budget needs some headroom for net latency..
|
||||||
|
with trio.fail_after(19):
|
||||||
async with (
|
async with (
|
||||||
open_test_pikerd() as (_, _, _, services),
|
open_test_pikerd() as (_, _, _, services),
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,214 @@
|
||||||
|
'''
|
||||||
|
Offline regressions for endpoint configuration and service startup.
|
||||||
|
|
||||||
|
'''
|
||||||
|
from contextlib import asynccontextmanager as acm
|
||||||
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
|
import tomllib
|
||||||
|
from types import ModuleType
|
||||||
|
|
||||||
|
from click.testing import CliRunner
|
||||||
|
import pytest
|
||||||
|
import tractor
|
||||||
|
import trio
|
||||||
|
|
||||||
|
from piker import config
|
||||||
|
from piker.cli import load_trans_eps, pikerd
|
||||||
|
from piker.service import _daemon, _actor_runtime
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('repeat', [False, True])
|
||||||
|
def test_maddrs_click_collection(repeat):
|
||||||
|
'''
|
||||||
|
Click previously produced a string for `--maddrs`, which endpoint
|
||||||
|
loading split into individual characters. Parse one or repeated
|
||||||
|
options through Click and then the real Tractor parser, without
|
||||||
|
entering the indefinitely running daemon callback. Every address
|
||||||
|
must survive intact and in the declared order.
|
||||||
|
|
||||||
|
'''
|
||||||
|
addresses = ['/ip4/127.0.0.1/tcp/6116']
|
||||||
|
if repeat:
|
||||||
|
addresses.append('/ip4/127.0.0.1/tcp/6117')
|
||||||
|
args = [
|
||||||
|
arg for address in addresses for arg in ['--maddrs', address]
|
||||||
|
]
|
||||||
|
with pikerd.make_context('pikerd', args) as ctx:
|
||||||
|
endpoints = load_trans_eps(maddrs=ctx.params['maddrs'])
|
||||||
|
assert [addr.unwrap() for addr in endpoints['pikerd']] == [
|
||||||
|
('tcp', '127.0.0.1', 6116 + index)
|
||||||
|
for index in range(len(addresses))
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_single_string_multiaddr():
|
||||||
|
'''
|
||||||
|
Direct endpoint callers may provide one string, independently of
|
||||||
|
Click's collection conversion. That input must denote a single
|
||||||
|
endpoint rather than a sequence of invalid character endpoints.
|
||||||
|
|
||||||
|
'''
|
||||||
|
endpoints = load_trans_eps(maddrs='/ip4/127.0.0.1/tcp/6116')
|
||||||
|
assert endpoints['pikerd'][0].unwrap() == (
|
||||||
|
'tcp', '127.0.0.1', 6116,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_template_single_transport():
|
||||||
|
'''
|
||||||
|
The shipped template enabled TCP and UDS together although the
|
||||||
|
locked Tractor runtime permits only one transport per actor.
|
||||||
|
Parse the real template and ensure both daemon and chart defaults
|
||||||
|
use the TCP transport selected by their startup paths.
|
||||||
|
|
||||||
|
'''
|
||||||
|
path = Path(__file__).parents[1] / 'config' / 'conf.toml'
|
||||||
|
conf = tomllib.loads(path.read_text())
|
||||||
|
endpoints = load_trans_eps(conf['network'])
|
||||||
|
for name in ['pikerd', 'chart']:
|
||||||
|
assert endpoints[name]
|
||||||
|
assert {addr.proto_key for addr in endpoints[name]} == {'tcp'}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('network', [None, {}])
|
||||||
|
def test_chart_without_network(monkeypatch, network):
|
||||||
|
'''
|
||||||
|
Existing configs without a populated network table left chart
|
||||||
|
bind endpoints unbound, crashing before the UI entrypoint. Invoke
|
||||||
|
the actual Click callback with absent and empty tables, replacing
|
||||||
|
only config IO and the UI entrypoint. Automatic binding must be
|
||||||
|
passed as None while preserving the configured registrar address.
|
||||||
|
|
||||||
|
'''
|
||||||
|
from piker.ui.cli import chart
|
||||||
|
|
||||||
|
conf = {} if network is None else {'network': network}
|
||||||
|
monkeypatch.setattr(config, 'load', lambda **_: (conf, None))
|
||||||
|
app = ModuleType('piker.ui._app')
|
||||||
|
calls = []
|
||||||
|
app._main = lambda **kwargs: calls.append(kwargs)
|
||||||
|
monkeypatch.setitem(sys.modules, 'piker.ui._app', app)
|
||||||
|
result = CliRunner().invoke(
|
||||||
|
chart,
|
||||||
|
['btcusdt.binance'],
|
||||||
|
obj={
|
||||||
|
'pdb': False,
|
||||||
|
'brokermods': [object()],
|
||||||
|
'tractorloglevel': 'warning',
|
||||||
|
'loglevel': 'warning',
|
||||||
|
'registry_addrs': [('127.0.0.1', 6116)],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert result.exit_code == 0, result.exception
|
||||||
|
runtime = calls[0]['tractor_kwargs']
|
||||||
|
assert runtime['tpt_bind_addrs'] is None
|
||||||
|
assert runtime['registry_addrs'] == [('127.0.0.1', 6116)]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('explicit_registry', [False, True])
|
||||||
|
def test_daemon_options_resolve_registrars(
|
||||||
|
monkeypatch,
|
||||||
|
explicit_registry,
|
||||||
|
):
|
||||||
|
'''
|
||||||
|
Any nonempty pikerd kwargs previously skipped registrar address
|
||||||
|
initialization. Exercise the full discovery and spawn path with
|
||||||
|
runtime options, using protocol-boundary fakes instead of remote
|
||||||
|
actors. An explicit override must reach discovery and startup
|
||||||
|
exactly once; otherwise the inherited registrar list is used.
|
||||||
|
The service lock must be released after leaving the context.
|
||||||
|
|
||||||
|
'''
|
||||||
|
inherited = [('tcp', '127.0.0.1', 6116)]
|
||||||
|
override = [('tcp', '127.0.0.1', 6117)]
|
||||||
|
expected = override if explicit_registry else inherited
|
||||||
|
calls = []
|
||||||
|
portal = object()
|
||||||
|
|
||||||
|
@acm
|
||||||
|
async def find(name, registry_addrs):
|
||||||
|
calls.append(('find', registry_addrs))
|
||||||
|
yield None
|
||||||
|
|
||||||
|
@acm
|
||||||
|
async def open_root(**kwargs):
|
||||||
|
calls.append(('open', kwargs))
|
||||||
|
yield None
|
||||||
|
|
||||||
|
@acm
|
||||||
|
async def wait(name):
|
||||||
|
yield portal
|
||||||
|
|
||||||
|
async def start(**kwargs):
|
||||||
|
return True
|
||||||
|
|
||||||
|
monkeypatch.setattr(_daemon, 'find_service', find)
|
||||||
|
monkeypatch.setattr(_daemon, 'maybe_open_pikerd', open_root)
|
||||||
|
monkeypatch.setattr(tractor, 'wait_for_actor', wait)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
tractor,
|
||||||
|
'get_runtime_vars',
|
||||||
|
lambda: {'_registry_addrs': inherited},
|
||||||
|
)
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
lock = trio.Lock()
|
||||||
|
monkeypatch.setitem(_daemon.Services.locks, 'probe', lock)
|
||||||
|
kwargs = {'debug_mode': False}
|
||||||
|
if explicit_registry:
|
||||||
|
kwargs['registry_addrs'] = override
|
||||||
|
async with _daemon.maybe_spawn_daemon(
|
||||||
|
'probe', start, {}, **kwargs,
|
||||||
|
) as found:
|
||||||
|
assert found is portal
|
||||||
|
assert not lock.locked()
|
||||||
|
|
||||||
|
trio.run(main)
|
||||||
|
assert calls[0] == ('find', expected)
|
||||||
|
assert calls[1][1]['registry_addrs'] == expected
|
||||||
|
assert calls[1][1]['debug_mode'] is False
|
||||||
|
|
||||||
|
|
||||||
|
async def _check_distinct_daemon_bind():
|
||||||
|
'''
|
||||||
|
Open Piker's service context on a non-registrar child actor.
|
||||||
|
|
||||||
|
'''
|
||||||
|
actor = tractor.current_actor()
|
||||||
|
assert not actor.is_registrar
|
||||||
|
assert actor.accept_addrs != actor.reg_addrs
|
||||||
|
async with _actor_runtime.open_pikerd(
|
||||||
|
registry_addrs=actor.reg_addrs,
|
||||||
|
tpt_bind_addrs=[('127.0.0.1', 0)],
|
||||||
|
):
|
||||||
|
return actor.accept_addrs
|
||||||
|
|
||||||
|
|
||||||
|
def test_daemon_bind_distinct_from_registrar(reg_addr):
|
||||||
|
'''
|
||||||
|
Separate daemon and registrar endpoints were rejected because
|
||||||
|
startup checked registrar addresses against daemon listeners.
|
||||||
|
Run a real TCP registrar and a distinct child daemon with an
|
||||||
|
ephemeral listener. Its service context must start and unwind
|
||||||
|
without taking ownership of the registrar's listening address.
|
||||||
|
|
||||||
|
'''
|
||||||
|
async def main():
|
||||||
|
async with (
|
||||||
|
tractor.open_root_actor(
|
||||||
|
registry_addrs=[reg_addr],
|
||||||
|
enable_transports=['tcp'],
|
||||||
|
),
|
||||||
|
tractor.open_nursery() as nursery,
|
||||||
|
):
|
||||||
|
portal = await nursery.start_actor(
|
||||||
|
'daemon_probe',
|
||||||
|
enable_modules=[__name__],
|
||||||
|
bind_addrs=[('127.0.0.1', 0)],
|
||||||
|
)
|
||||||
|
addresses = await portal.run(_check_distinct_daemon_bind)
|
||||||
|
assert addresses
|
||||||
|
await nursery.cancel()
|
||||||
|
|
||||||
|
trio.run(main)
|
||||||
528
uv.lock
528
uv.lock
|
|
@ -1,6 +1,6 @@
|
||||||
version = 1
|
version = 1
|
||||||
revision = 3
|
revision = 3
|
||||||
requires-python = ">=3.12, <3.14"
|
requires-python = "==3.13.*"
|
||||||
resolution-markers = [
|
resolution-markers = [
|
||||||
"sys_platform == 'win32'",
|
"sys_platform == 'win32'",
|
||||||
"sys_platform == 'emscripten'",
|
"sys_platform == 'emscripten'",
|
||||||
|
|
@ -55,23 +55,6 @@ dependencies = [
|
||||||
{ name = "yarl" },
|
{ name = "yarl" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/54/07/9467d3f8dae29b14f423b414d9e67512a76743c5bb7686fb05fe10c9cc3e/aiohttp-3.9.1.tar.gz", hash = "sha256:8fc49a87ac269d4529da45871e2ffb6874e87779c3d0e2ccd813c0899221239d", size = 7482118, upload-time = "2023-11-26T17:55:44.763Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/54/07/9467d3f8dae29b14f423b414d9e67512a76743c5bb7686fb05fe10c9cc3e/aiohttp-3.9.1.tar.gz", hash = "sha256:8fc49a87ac269d4529da45871e2ffb6874e87779c3d0e2ccd813c0899221239d", size = 7482118, upload-time = "2023-11-26T17:55:44.763Z" }
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/41/d6/e4f5eadff5e4523f75b56183f474f7d5f54fc495e80ee875843d7b264492/aiohttp-3.9.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f800164276eec54e0af5c99feb9494c295118fc10a11b997bbb1348ba1a52065", size = 591673, upload-time = "2023-11-26T17:53:39.376Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/70/de/9cfb42190a946df5179375a8e59110faf8188e2c19f58a6f8f6846414c8f/aiohttp-3.9.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:500f1c59906cd142d452074f3811614be04819a38ae2b3239a48b82649c08821", size = 392831, upload-time = "2023-11-26T17:53:41.583Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/cf/45/580b5a6abb70530cea7f6e697227c61e0001eff75d50b897a62b66c6d3b7/aiohttp-3.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0b0a6a36ed7e164c6df1e18ee47afbd1990ce47cb428739d6c99aaabfaf1b3af", size = 388850, upload-time = "2023-11-26T17:53:44.157Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/02/3a/9aa79bc010bb8af6020f8e70937710d01622b97a7e04b8f8fbea97b04ff8/aiohttp-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69da0f3ed3496808e8cbc5123a866c41c12c15baaaead96d256477edf168eb57", size = 1319339, upload-time = "2023-11-26T17:53:47.152Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/3c/2a/6db78762123f368d97a38694b75d1942fcff6d476cb633dbca84c93c7221/aiohttp-3.9.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:176df045597e674fa950bf5ae536be85699e04cea68fa3a616cf75e413737eb5", size = 1359461, upload-time = "2023-11-26T17:53:50.59Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8c/4b/fec8718e62106fa0362c5109f362ce45f6985d14283678e5c82cc9dfb0af/aiohttp-3.9.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b796b44111f0cab6bbf66214186e44734b5baab949cb5fb56154142a92989aeb", size = 1401205, upload-time = "2023-11-26T17:53:53.275Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/75/5f/90a2869ad3d1fb9bd984bfc1b02d8b19e381467b238bd3668a09faa69df5/aiohttp-3.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f27fdaadce22f2ef950fc10dcdf8048407c3b42b73779e48a4e76b3c35bca26c", size = 1314647, upload-time = "2023-11-26T17:53:56.884Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a4/56/f5064eb44914235591b372b04420fd9e80b21110ae718ba72387f49ee9c0/aiohttp-3.9.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcb6532b9814ea7c5a6a3299747c49de30e84472fa72821b07f5a9818bce0f66", size = 1266651, upload-time = "2023-11-26T17:53:59.833Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/59/86/f759ee047d87cff52028e90679a2f5c15c08f1b816cd1c16eb06db65276f/aiohttp-3.9.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:54631fb69a6e44b2ba522f7c22a6fb2667a02fd97d636048478db2fd8c4e98fe", size = 1321196, upload-time = "2023-11-26T17:54:03.058Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b6/ae/30c8962df269f86912be9e3ec59b51dd8eaeccb5d23695f63177a0e21d1b/aiohttp-3.9.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4b4c452d0190c5a820d3f5c0f3cd8a28ace48c54053e24da9d6041bf81113183", size = 1267553, upload-time = "2023-11-26T17:54:05.551Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/f3/1a/6452aa5ab519e79c43831e59fcef6f76426b51810d9772e03addc3efd958/aiohttp-3.9.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:cae4c0c2ca800c793cae07ef3d40794625471040a87e1ba392039639ad61ab5b", size = 1347571, upload-time = "2023-11-26T17:54:08.408Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/20/43/19a597a7e50ea99d04509ea82659c52149fefec45b5005d2e1f67b68ac0d/aiohttp-3.9.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:565760d6812b8d78d416c3c7cfdf5362fbe0d0d25b82fed75d0d29e18d7fc30f", size = 1395459, upload-time = "2023-11-26T17:54:11.071Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d0/89/5cdbebbdfe91c1f937ef4cc2836152cce0d2a0138029b53703d0c3f13199/aiohttp-3.9.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54311eb54f3a0c45efb9ed0d0a8f43d1bc6060d773f6973efd90037a51cd0a3f", size = 1316162, upload-time = "2023-11-26T17:54:13.789Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/21/66/114bf1d9f0a38a50bf1b7a5c8315a44fd1f35bd1fee025a230907a2cb4b7/aiohttp-3.9.1-cp312-cp312-win32.whl", hash = "sha256:85c3e3c9cb1d480e0b9a64c658cd66b3cfb8e721636ab8b0e746e2d79a7a9eed", size = 341652, upload-time = "2023-11-26T17:54:16.771Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/4e/13/e929a6a50288e60ade3961b294d2f5aeb251b6579e4290a5397e484d0df9/aiohttp-3.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:11cb254e397a82efb1805d12561e80124928e04e9c4483587ce7390b3866d213", size = 362885, upload-time = "2023-11-26T17:54:18.884Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aiosignal"
|
name = "aiosignal"
|
||||||
|
|
@ -79,7 +62,6 @@ version = "1.4.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "frozenlist" },
|
{ name = "frozenlist" },
|
||||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
|
|
@ -92,7 +74,6 @@ version = "4.12.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "idna" },
|
{ name = "idna" },
|
||||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/16/ce/8a777047513153587e5434fd752e89334ac33e379aa3497db860eeb60377/anyio-4.12.0.tar.gz", hash = "sha256:73c693b567b0c55130c104d0b43a9baf3aa6a31fc6110116509f27bf75e21ec0", size = 228266, upload-time = "2025-11-28T23:37:38.911Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/16/ce/8a777047513153587e5434fd752e89334ac33e379aa3497db860eeb60377/anyio-4.12.0.tar.gz", hash = "sha256:73c693b567b0c55130c104d0b43a9baf3aa6a31fc6110116509f27bf75e21ec0", size = 228266, upload-time = "2025-11-28T23:37:38.911Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
|
|
@ -117,6 +98,15 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/e0/44/827b2a91a5816512fcaf3cc4ebc465ccd5d598c45cefa6703fcf4a79018f/attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1", size = 60752, upload-time = "2023-12-31T06:30:30.772Z" },
|
{ url = "https://files.pythonhosted.org/packages/e0/44/827b2a91a5816512fcaf3cc4ebc465ccd5d598c45cefa6703fcf4a79018f/attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1", size = 60752, upload-time = "2023-12-31T06:30:30.772Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base58"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/7f/45/8ae61209bb9015f516102fa559a2914178da1d5868428bd86a1b4421141d/base58-2.1.1.tar.gz", hash = "sha256:c5d0cb3f5b6e81e8e35da5754388ddcc6d0d14b6c6a132cb93d69ed580a7278c", size = 6528, upload-time = "2021-10-30T22:12:17.858Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4a/45/ec96b29162a402fc4c1c5512d114d7b3787b9d1c2ec241d9568b4816ee23/base58-2.1.1-py3-none-any.whl", hash = "sha256:11a36f4d3ce51dfc1043f3218591ac4eb1ceb172919cebe05b52a5bcc8d245c2", size = 5621, upload-time = "2021-10-30T22:12:16.658Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bidict"
|
name = "bidict"
|
||||||
version = "0.23.1"
|
version = "0.23.1"
|
||||||
|
|
@ -126,15 +116,33 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5", size = 32764, upload-time = "2024-02-18T19:09:04.156Z" },
|
{ url = "https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5", size = 32764, upload-time = "2024-02-18T19:09:04.156Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blake3"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/26/6a/4cc5a9dd40fd8a6d283fd3761e5f59c490109571ef8e3c73245417e5a305/blake3-1.0.9.tar.gz", hash = "sha256:5fa374fa5070ca084368776c19b420157eb0f2d3f091343d6bc59189929d62e2", size = 116872, upload-time = "2026-06-22T18:02:25.366Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/41/1b/95b473d649f5322e69674622a307ffdb4f0b63adb0a0adcbc5cb8a8833c2/blake3-1.0.9-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:69ff5aebc7650954443aa701feff2028d7c7ea5b5e18ee265f15e2104e892328", size = 343869, upload-time = "2026-06-22T18:00:51.936Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4b/9d/adec22c719d8451af1dc9e624bf5907008ef1e0afa51aa69fd1e8c91e60e/blake3-1.0.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0cdfeff65488089ef86f7587c76055ff72b28d28d10e427b547f5711477c376d", size = 328482, upload-time = "2026-06-22T18:00:53.39Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5e/aa/0a6967ff9a6ae182419a681aed54f7338b34a1f71372e90f787a2afa42e6/blake3-1.0.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:766f1555cbe614f14f399c2fbec0983568d20edb36837ba04040807eb9e1a609", size = 373616, upload-time = "2026-06-22T18:00:54.701Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1c/51/5d4e198bf3ae902c6697ad6ec77d7210736ad8f680980e8b648dcfcd09a0/blake3-1.0.9-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:128a62136c9a39c7cb9fdaa5fb38471f2418853da7f5a89f31495735d0ba6f2c", size = 374149, upload-time = "2026-06-22T18:00:56.015Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7e/62/d3c7c364925b3f10828e5137376f3947f112c32188e899b42f09c2fde98a/blake3-1.0.9-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1ea0bf17b184b03444007646d902207d2b4d4f3e91a0cac3836552d83db74b9", size = 446151, upload-time = "2026-06-22T18:00:57.378Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b1/01/55b89389c5036c9d24b1d762d6265e91552e10b76a3c99fece3c4a7a4783/blake3-1.0.9-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73a48f7e9f0e047f51a445d9b0361ab1907bdc72b6857815a84dacd2e59556f8", size = 487256, upload-time = "2026-06-22T18:00:58.763Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b2/7a/a21b52253292ad3e4df63ea4a01ce11d3ee8f4a8a8d80eaf0c7ce92a62bd/blake3-1.0.9-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b27550ada40f839aca64c66127940e4318bb6ef3e291890ef913017f6f637448", size = 383977, upload-time = "2026-06-22T18:01:00.192Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f3/f0/fe7188201a29ee9b042616c786a98afd864d537ca96198e64c3fe4ff13a9/blake3-1.0.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66c84dbc2a31eda88b55bbf5c5b711037bf0698eba0fd1faf06bdaf313c39048", size = 383615, upload-time = "2026-06-22T18:01:01.557Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/22/08/f6a213b950e30fe9ef7d7fc061ec388e66ed62643570226882e6f7136ea3/blake3-1.0.9-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:dab59b324aa65c09e937d6c43de5de85ec9581627f4e79dcc9806d85b54a1c34", size = 380288, upload-time = "2026-06-22T18:01:03.025Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f1/fb/b171e47c1b835483bcf1545ebc289458165f8dc0f5c7f74a9176d7e9af03/blake3-1.0.9-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:eca281fedcbe5c56655bd5a4176e6036eddbbe57df96114a03838fce08b1e0ca", size = 549122, upload-time = "2026-06-22T18:01:04.486Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a7/d8/7bf71c2c85a0951e406971f151435e0751716907e3924c6c48a2d6dae0db/blake3-1.0.9-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:3cbe7f190164896dc3908e920716ee66bc31d40f1a0fb603ed59ac53290fb9cf", size = 591183, upload-time = "2026-06-22T18:01:06.259Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/20/85/34c3ea03cc90b2516628494ab3e0a98aec4ca8b04d037840ccd390e480ca/blake3-1.0.9-cp313-cp313-win32.whl", hash = "sha256:508ccaf8f9377cc47e6026c2897fdc37de61faeb1420dc023b6379cc2474eb65", size = 229053, upload-time = "2026-06-22T18:01:07.638Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/db/2e/f09e8ed426f360aa2005206466ceab2f707486eb5d9db7051dbcbae056d1/blake3-1.0.9-cp313-cp313-win_amd64.whl", hash = "sha256:caded2806d2cbeed638c5e2517ed8b2a94165b3452fda35e72896142d22070e0", size = 217589, upload-time = "2026-06-22T18:01:08.922Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "caio"
|
name = "caio"
|
||||||
version = "0.9.24"
|
version = "0.9.24"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/98/04/ec9b6864135032fd454f6cd1d9444e0bb01040196ad0cd776c061fc92c6b/caio-0.9.24.tar.gz", hash = "sha256:5bcdecaea02a9aa8e3acf0364eff8ad9903d57d70cdb274a42270126290a77f1", size = 27174, upload-time = "2025-04-23T16:31:19.191Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/98/04/ec9b6864135032fd454f6cd1d9444e0bb01040196ad0cd776c061fc92c6b/caio-0.9.24.tar.gz", hash = "sha256:5bcdecaea02a9aa8e3acf0364eff8ad9903d57d70cdb274a42270126290a77f1", size = 27174, upload-time = "2025-04-23T16:31:19.191Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/5f/76/b33a89dc2516aae045ef509cf2febe7ffb2a36c4eebb8f301a7ef2093385/caio-0.9.24-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae3566228383175265a7583107f21a7cb044a752ea29ba84fce7c1a49a05903", size = 42212, upload-time = "2025-04-23T16:31:08.457Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a9/8c/cb62483e69309bbad503c2ace29c4ac3466558a20e9aed840d313e1dcacd/caio-0.9.24-cp312-cp312-manylinux_2_34_aarch64.whl", hash = "sha256:a306b0dda91cb4ca3170f066c114597f8ea41b3da578574a9d2b54f86963de68", size = 81517, upload-time = "2025-04-23T16:31:09.686Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/64/80/8a8cdfd4b47e06d1e9de6d5431c2603e0741282fa06f757f10c04e619d8f/caio-0.9.24-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:8ee158e56128d865fb7d57a9c9c22fca4e8aa8d8664859c977a36fff3ccb3609", size = 80216, upload-time = "2025-04-23T16:31:10.98Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/66/35/06e77837fc5455d330c5502460fc3743989d4ff840b61aa79af3a7ec5b19/caio-0.9.24-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1d47ef8d76aca74c17cb07339a441c5530fc4b8dd9222dfb1e1abd7f9f9b814f", size = 42214, upload-time = "2025-04-23T16:31:12.272Z" },
|
{ url = "https://files.pythonhosted.org/packages/66/35/06e77837fc5455d330c5502460fc3743989d4ff840b61aa79af3a7ec5b19/caio-0.9.24-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1d47ef8d76aca74c17cb07339a441c5530fc4b8dd9222dfb1e1abd7f9f9b814f", size = 42214, upload-time = "2025-04-23T16:31:12.272Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e0/e2/c16aeaea4b2103e04fdc2e7088ede6313e1971704c87fcd681b58ab1c6b4/caio-0.9.24-cp313-cp313-manylinux_2_34_aarch64.whl", hash = "sha256:d15fc746c4bf0077d75df05939d1e97c07ccaa8e580681a77021d6929f65d9f4", size = 81557, upload-time = "2025-04-23T16:31:13.526Z" },
|
{ url = "https://files.pythonhosted.org/packages/e0/e2/c16aeaea4b2103e04fdc2e7088ede6313e1971704c87fcd681b58ab1c6b4/caio-0.9.24-cp313-cp313-manylinux_2_34_aarch64.whl", hash = "sha256:d15fc746c4bf0077d75df05939d1e97c07ccaa8e580681a77021d6929f65d9f4", size = 81557, upload-time = "2025-04-23T16:31:13.526Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/78/3b/adeb0cffe98dbe60661f316ec0060037a5209a5ed8be38ac8e79fdbc856d/caio-0.9.24-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:9368eae0a9badd5f31264896c51b47431d96c0d46f1979018fb1d20c49f56156", size = 80242, upload-time = "2025-04-23T16:31:14.365Z" },
|
{ url = "https://files.pythonhosted.org/packages/78/3b/adeb0cffe98dbe60661f316ec0060037a5209a5ed8be38ac8e79fdbc856d/caio-0.9.24-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:9368eae0a9badd5f31264896c51b47431d96c0d46f1979018fb1d20c49f56156", size = 80242, upload-time = "2025-04-23T16:31:14.365Z" },
|
||||||
|
|
@ -158,18 +166,6 @@ dependencies = [
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" },
|
{ url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" },
|
{ url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" },
|
{ url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" },
|
||||||
|
|
@ -190,22 +186,6 @@ version = "3.4.4"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" },
|
{ url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" },
|
{ url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" },
|
{ url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" },
|
||||||
|
|
@ -316,10 +296,6 @@ version = "3.2.2"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/29/17/55fc687ba986f2210298fa2f60fec265fa3004c3f9a1e958ea1fe2d4e061/cython-3.2.2.tar.gz", hash = "sha256:c3add3d483acc73129a61d105389344d792c17e7c1cee24863f16416bd071634", size = 3275797, upload-time = "2025-11-30T12:48:20.942Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/29/17/55fc687ba986f2210298fa2f60fec265fa3004c3f9a1e958ea1fe2d4e061/cython-3.2.2.tar.gz", hash = "sha256:c3add3d483acc73129a61d105389344d792c17e7c1cee24863f16416bd071634", size = 3275797, upload-time = "2025-11-30T12:48:20.942Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/57/0f/6fd78dc581373722bb9dedfc90c35b59ba88af988756315af227a877c7a2/cython-3.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:692a41c8fe06fb2dc55ca2c8d71c80c469fd16fe69486ed99f3b3cbb2d3af83f", size = 2968037, upload-time = "2025-11-30T12:48:47.279Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b0/52/50b6263c2fbad73aae8911ce54641ee1739d430a0592d3b3510591d7842b/cython-3.2.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:098590c1dc309f8a0406ade031963a95a87714296b425539f9920aebf924560d", size = 3223137, upload-time = "2025-11-30T12:48:48.951Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d6/44/4e34d161674c9162c6eb9ddef0cd69d41d92ae7e6dee3945fed3a6871ebe/cython-3.2.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3898c076e9c458bcb3e4936187919fda5f5365fe4c567d35d2b003444b6f3fe", size = 3390943, upload-time = "2025-11-30T12:48:51.125Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/62/8a/ffc2df024c1341737008fbaf0fbea51ef983a7146b43b84a239f197cf005/cython-3.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:2b910b89a2a71004064c5e890b9512a251eda63fae252caa0feb9835057035f9", size = 2756403, upload-time = "2025-11-30T12:48:52.929Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a2/4f/b5355918962ec28b376eb8e357c718d58baf32d6df7017be8d147dd4ba29/cython-3.2.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa24cd0bdab27ca099b2467806c684404add597c1108e07ddf7b6471653c85d7", size = 2958578, upload-time = "2025-11-30T12:48:55.354Z" },
|
{ url = "https://files.pythonhosted.org/packages/a2/4f/b5355918962ec28b376eb8e357c718d58baf32d6df7017be8d147dd4ba29/cython-3.2.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa24cd0bdab27ca099b2467806c684404add597c1108e07ddf7b6471653c85d7", size = 2958578, upload-time = "2025-11-30T12:48:55.354Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/46/21/a8038c8253e7a5241ed1db6d031bac586f7a502d92f487124abbc3f3e94f/cython-3.2.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60f4aa425e1ff98abf8d965ae7020f06dd2cbc01dbd945137d2f9cca4ff0524a", size = 3212479, upload-time = "2025-11-30T12:48:57.567Z" },
|
{ url = "https://files.pythonhosted.org/packages/46/21/a8038c8253e7a5241ed1db6d031bac586f7a502d92f487124abbc3f3e94f/cython-3.2.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60f4aa425e1ff98abf8d965ae7020f06dd2cbc01dbd945137d2f9cca4ff0524a", size = 3212479, upload-time = "2025-11-30T12:48:57.567Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/57/c1/76928c07176a4402c74d5b304936ad8ee167dd04a07cf7dca545e8c25f9b/cython-3.2.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a473df474ba89e9fee81ee82b31062a267f9e598096b222783477e56d02ad12c", size = 3374773, upload-time = "2025-11-30T12:48:59.318Z" },
|
{ url = "https://files.pythonhosted.org/packages/57/c1/76928c07176a4402c74d5b304936ad8ee167dd04a07cf7dca545e8c25f9b/cython-3.2.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a473df474ba89e9fee81ee82b31062a267f9e598096b222783477e56d02ad12c", size = 3374773, upload-time = "2025-11-30T12:48:59.318Z" },
|
||||||
|
|
@ -336,6 +312,15 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/76/f2/98fd8d0b514622a789fd2824b59bd6041b799aaeeba14a8d92d52f6654dd/cython-3.2.2-py3-none-any.whl", hash = "sha256:13b99ecb9482aff6a6c12d1ca6feef6940c507af909914b49f568de74fa965fb", size = 1255106, upload-time = "2025-11-30T12:48:18.454Z" },
|
{ url = "https://files.pythonhosted.org/packages/76/f2/98fd8d0b514622a789fd2824b59bd6041b799aaeeba14a8d92d52f6654dd/cython-3.2.2-py3-none-any.whl", hash = "sha256:13b99ecb9482aff6a6c12d1ca6feef6940c507af909914b49f568de74fa965fb", size = 1255106, upload-time = "2025-11-30T12:48:18.454Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dnspython"
|
||||||
|
version = "2.8.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "elastic-transport"
|
name = "elastic-transport"
|
||||||
version = "8.17.1"
|
version = "8.17.1"
|
||||||
|
|
@ -367,9 +352,6 @@ wheels = [
|
||||||
name = "exceptiongroup"
|
name = "exceptiongroup"
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
|
||||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
|
{ url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
|
||||||
|
|
@ -398,22 +380,6 @@ version = "1.8.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/69/29/948b9aa87e75820a38650af445d2ef2b6b8a6fab1a23b6bb9e4ef0be2d59/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", size = 87782, upload-time = "2025-10-06T05:36:06.649Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/64/80/4f6e318ee2a7c0750ed724fa33a4bdf1eacdc5a39a7a24e818a773cd91af/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", size = 50594, upload-time = "2025-10-06T05:36:07.69Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", size = 50448, upload-time = "2025-10-06T05:36:08.78Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", size = 242411, upload-time = "2025-10-06T05:36:09.801Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8f/83/f61505a05109ef3293dfb1ff594d13d64a2324ac3482be2cedc2be818256/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", size = 243014, upload-time = "2025-10-06T05:36:11.394Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d8/cb/cb6c7b0f7d4023ddda30cf56b8b17494eb3a79e3fda666bf735f63118b35/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", size = 234909, upload-time = "2025-10-06T05:36:12.598Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/31/c5/cd7a1f3b8b34af009fb17d4123c5a778b44ae2804e3ad6b86204255f9ec5/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", size = 250049, upload-time = "2025-10-06T05:36:14.065Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c0/01/2f95d3b416c584a1e7f0e1d6d31998c4a795f7544069ee2e0962a4b60740/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", size = 256485, upload-time = "2025-10-06T05:36:15.39Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ce/03/024bf7720b3abaebcff6d0793d73c154237b85bdf67b7ed55e5e9596dc9a/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", size = 237619, upload-time = "2025-10-06T05:36:16.558Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/69/fa/f8abdfe7d76b731f5d8bd217827cf6764d4f1d9763407e42717b4bed50a0/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", size = 250320, upload-time = "2025-10-06T05:36:17.821Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/f5/3c/b051329f718b463b22613e269ad72138cc256c540f78a6de89452803a47d/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", size = 246820, upload-time = "2025-10-06T05:36:19.046Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/0f/ae/58282e8f98e444b3f4dd42448ff36fa38bef29e40d40f330b22e7108f565/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", size = 250518, upload-time = "2025-10-06T05:36:20.763Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8f/96/007e5944694d66123183845a106547a15944fbbb7154788cbf7272789536/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", size = 239096, upload-time = "2025-10-06T05:36:22.129Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/66/bb/852b9d6db2fa40be96f29c0d1205c306288f0684df8fd26ca1951d461a56/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", size = 39985, upload-time = "2025-10-06T05:36:23.661Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", size = 44591, upload-time = "2025-10-06T05:36:24.958Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a7/06/1dc65480ab147339fecc70797e9c2f69d9cea9cf38934ce08df070fdb9cb/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd", size = 40102, upload-time = "2025-10-06T05:36:26.333Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/2d/40/0832c31a37d60f60ed79e9dfb5a92e1e2af4f40a16a29abcc7992af9edff/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", size = 85717, upload-time = "2025-10-06T05:36:27.341Z" },
|
{ url = "https://files.pythonhosted.org/packages/2d/40/0832c31a37d60f60ed79e9dfb5a92e1e2af4f40a16a29abcc7992af9edff/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", size = 85717, upload-time = "2025-10-06T05:36:27.341Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", size = 49651, upload-time = "2025-10-06T05:36:28.855Z" },
|
{ url = "https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", size = 49651, upload-time = "2025-10-06T05:36:28.855Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", size = 49417, upload-time = "2025-10-06T05:36:29.877Z" },
|
{ url = "https://files.pythonhosted.org/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", size = 49417, upload-time = "2025-10-06T05:36:29.877Z" },
|
||||||
|
|
@ -469,14 +435,6 @@ version = "3.3.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/c7/e5/40dbda2736893e3e53d25838e0f19a2b417dfc122b9989c91918db30b5d3/greenlet-3.3.0.tar.gz", hash = "sha256:a82bb225a4e9e4d653dd2fb7b8b2d36e4fb25bc0165422a11e48b88e9e6f78fb", size = 190651, upload-time = "2025-12-04T14:49:44.05Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/c7/e5/40dbda2736893e3e53d25838e0f19a2b417dfc122b9989c91918db30b5d3/greenlet-3.3.0.tar.gz", hash = "sha256:a82bb225a4e9e4d653dd2fb7b8b2d36e4fb25bc0165422a11e48b88e9e6f78fb", size = 190651, upload-time = "2025-12-04T14:49:44.05Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/f8/0a/a3871375c7b9727edaeeea994bfff7c63ff7804c9829c19309ba2e058807/greenlet-3.3.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:b01548f6e0b9e9784a2c99c5651e5dc89ffcbe870bc5fb2e5ef864e9cc6b5dcb", size = 276379, upload-time = "2025-12-04T14:23:30.498Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/43/ab/7ebfe34dce8b87be0d11dae91acbf76f7b8246bf9d6b319c741f99fa59c6/greenlet-3.3.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:349345b770dc88f81506c6861d22a6ccd422207829d2c854ae2af8025af303e3", size = 597294, upload-time = "2025-12-04T14:50:06.847Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a4/39/f1c8da50024feecd0793dbd5e08f526809b8ab5609224a2da40aad3a7641/greenlet-3.3.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e8e18ed6995e9e2c0b4ed264d2cf89260ab3ac7e13555b8032b25a74c6d18655", size = 607742, upload-time = "2025-12-04T14:57:42.349Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/77/cb/43692bcd5f7a0da6ec0ec6d58ee7cddb606d055ce94a62ac9b1aa481e969/greenlet-3.3.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c024b1e5696626890038e34f76140ed1daf858e37496d33f2af57f06189e70d7", size = 622297, upload-time = "2025-12-04T15:07:13.552Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/75/b0/6bde0b1011a60782108c01de5913c588cf51a839174538d266de15e4bf4d/greenlet-3.3.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:047ab3df20ede6a57c35c14bf5200fcf04039d50f908270d3f9a7a82064f543b", size = 609885, upload-time = "2025-12-04T14:26:02.368Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/49/0e/49b46ac39f931f59f987b7cd9f34bfec8ef81d2a1e6e00682f55be5de9f4/greenlet-3.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d9ad37fc657b1102ec880e637cccf20191581f75c64087a549e66c57e1ceb53", size = 1567424, upload-time = "2025-12-04T15:04:23.757Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/05/f5/49a9ac2dff7f10091935def9165c90236d8f175afb27cbed38fb1d61ab6b/greenlet-3.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83cd0e36932e0e7f36a64b732a6f60c2fc2df28c351bae79fbaf4f8092fe7614", size = 1636017, upload-time = "2025-12-04T14:27:29.688Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/6c/79/3912a94cf27ec503e51ba493692d6db1e3cd8ac7ac52b0b47c8e33d7f4f9/greenlet-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a7a34b13d43a6b78abf828a6d0e87d3385680eaf830cd60d20d52f249faabf39", size = 301964, upload-time = "2025-12-04T14:36:58.316Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/02/2f/28592176381b9ab2cafa12829ba7b472d177f3acc35d8fbcf3673d966fff/greenlet-3.3.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:a1e41a81c7e2825822f4e068c48cb2196002362619e2d70b148f20a831c00739", size = 275140, upload-time = "2025-12-04T14:23:01.282Z" },
|
{ url = "https://files.pythonhosted.org/packages/02/2f/28592176381b9ab2cafa12829ba7b472d177f3acc35d8fbcf3673d966fff/greenlet-3.3.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:a1e41a81c7e2825822f4e068c48cb2196002362619e2d70b148f20a831c00739", size = 275140, upload-time = "2025-12-04T14:23:01.282Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/2c/80/fbe937bf81e9fca98c981fe499e59a3f45df2a04da0baa5c2be0dca0d329/greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f515a47d02da4d30caaa85b69474cec77b7929b2e936ff7fb853d42f4bf8808", size = 599219, upload-time = "2025-12-04T14:50:08.309Z" },
|
{ url = "https://files.pythonhosted.org/packages/2c/80/fbe937bf81e9fca98c981fe499e59a3f45df2a04da0baa5c2be0dca0d329/greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f515a47d02da4d30caaa85b69474cec77b7929b2e936ff7fb853d42f4bf8808", size = 599219, upload-time = "2025-12-04T14:50:08.309Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c2/ff/7c985128f0514271b8268476af89aee6866df5eec04ac17dcfbc676213df/greenlet-3.3.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d2d9fd66bfadf230b385fdc90426fcd6eb64db54b40c495b72ac0feb5766c54", size = 610211, upload-time = "2025-12-04T14:57:43.968Z" },
|
{ url = "https://files.pythonhosted.org/packages/c2/ff/7c985128f0514271b8268476af89aee6866df5eec04ac17dcfbc676213df/greenlet-3.3.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d2d9fd66bfadf230b385fdc90426fcd6eb64db54b40c495b72ac0feb5766c54", size = 610211, upload-time = "2025-12-04T14:57:43.968Z" },
|
||||||
|
|
@ -604,11 +562,6 @@ version = "0.45.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/99/8d/5baf1cef7f9c084fb35a8afbde88074f0d6a727bc63ef764fe0e7543ba40/llvmlite-0.45.1.tar.gz", hash = "sha256:09430bb9d0bb58fc45a45a57c7eae912850bedc095cd0810a57de109c69e1c32", size = 185600, upload-time = "2025-10-01T17:59:52.046Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/99/8d/5baf1cef7f9c084fb35a8afbde88074f0d6a727bc63ef764fe0e7543ba40/llvmlite-0.45.1.tar.gz", hash = "sha256:09430bb9d0bb58fc45a45a57c7eae912850bedc095cd0810a57de109c69e1c32", size = 185600, upload-time = "2025-10-01T17:59:52.046Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/e2/7c/82cbd5c656e8991bcc110c69d05913be2229302a92acb96109e166ae31fb/llvmlite-0.45.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:28e763aba92fe9c72296911e040231d486447c01d4f90027c8e893d89d49b20e", size = 43043524, upload-time = "2025-10-01T18:03:30.666Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9d/bc/5314005bb2c7ee9f33102c6456c18cc81745d7055155d1218f1624463774/llvmlite-0.45.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1a53f4b74ee9fd30cb3d27d904dadece67a7575198bd80e687ee76474620735f", size = 37253123, upload-time = "2025-10-01T18:04:18.177Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/96/76/0f7154952f037cb320b83e1c952ec4a19d5d689cf7d27cb8a26887d7bbc1/llvmlite-0.45.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5b3796b1b1e1c14dcae34285d2f4ea488402fbd2c400ccf7137603ca3800864f", size = 56288211, upload-time = "2025-10-01T18:01:24.079Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/00/b1/0b581942be2683ceb6862d558979e87387e14ad65a1e4db0e7dd671fa315/llvmlite-0.45.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:779e2f2ceefef0f4368548685f0b4adde34e5f4b457e90391f570a10b348d433", size = 55140958, upload-time = "2025-10-01T18:02:30.482Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/33/94/9ba4ebcf4d541a325fd8098ddc073b663af75cc8b065b6059848f7d4dce7/llvmlite-0.45.1-cp312-cp312-win_amd64.whl", hash = "sha256:9e6c9949baf25d9aa9cd7cf0f6d011b9ca660dd17f5ba2b23bdbdb77cc86b116", size = 38132231, upload-time = "2025-10-01T18:05:03.664Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/1d/e2/c185bb7e88514d5025f93c6c4092f6120c6cea8fe938974ec9860fb03bbb/llvmlite-0.45.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:d9ea9e6f17569a4253515cc01dade70aba536476e3d750b2e18d81d7e670eb15", size = 43043524, upload-time = "2025-10-01T18:03:43.249Z" },
|
{ url = "https://files.pythonhosted.org/packages/1d/e2/c185bb7e88514d5025f93c6c4092f6120c6cea8fe938974ec9860fb03bbb/llvmlite-0.45.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:d9ea9e6f17569a4253515cc01dade70aba536476e3d750b2e18d81d7e670eb15", size = 43043524, upload-time = "2025-10-01T18:03:43.249Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/09/b8/b5437b9ecb2064e89ccf67dccae0d02cd38911705112dd0dcbfa9cd9a9de/llvmlite-0.45.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:c9f3cadee1630ce4ac18ea38adebf2a4f57a89bd2740ce83746876797f6e0bfb", size = 37253121, upload-time = "2025-10-01T18:04:30.557Z" },
|
{ url = "https://files.pythonhosted.org/packages/09/b8/b5437b9ecb2064e89ccf67dccae0d02cd38911705112dd0dcbfa9cd9a9de/llvmlite-0.45.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:c9f3cadee1630ce4ac18ea38adebf2a4f57a89bd2740ce83746876797f6e0bfb", size = 37253121, upload-time = "2025-10-01T18:04:30.557Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f7/97/ad1a907c0173a90dd4df7228f24a3ec61058bc1a9ff8a0caec20a0cc622e/llvmlite-0.45.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:57c48bf2e1083eedbc9406fb83c4e6483017879714916fe8be8a72a9672c995a", size = 56288210, upload-time = "2025-10-01T18:01:40.26Z" },
|
{ url = "https://files.pythonhosted.org/packages/f7/97/ad1a907c0173a90dd4df7228f24a3ec61058bc1a9ff8a0caec20a0cc622e/llvmlite-0.45.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:57c48bf2e1083eedbc9406fb83c4e6483017879714916fe8be8a72a9672c995a", size = 56288210, upload-time = "2025-10-01T18:01:40.26Z" },
|
||||||
|
|
@ -638,25 +591,75 @@ wheels = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "msgspec"
|
name = "mmh3"
|
||||||
version = "0.19.0"
|
version = "5.3.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/cf/9b/95d8ce458462b8b71b8a70fa94563b2498b89933689f3a7b8911edfae3d7/msgspec-0.19.0.tar.gz", hash = "sha256:604037e7cd475345848116e89c553aa9a233259733ab51986ac924ab1b976f8e", size = 216934, upload-time = "2024-12-27T17:40:28.597Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/aa/69/d00269fee7a3102fcc0f04f0a312e41c6b237762bdcad4c19426f18e697c/mmh3-5.3.0.tar.gz", hash = "sha256:95832419b87b882bec9dcd7d041d74887ba7745b3659c14be1ae1db5cfa35cad", size = 33607, upload-time = "2026-08-26T04:58:20.042Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/b2/5f/a70c24f075e3e7af2fae5414c7048b0e11389685b7f717bb55ba282a34a7/msgspec-0.19.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f98bd8962ad549c27d63845b50af3f53ec468b6318400c9f1adfe8b092d7b62f", size = 190485, upload-time = "2024-12-27T17:39:44.974Z" },
|
{ url = "https://files.pythonhosted.org/packages/8b/fa/e07f6b9e2fba550fe539b6c66ee7fc28e44f5bd445a7203ae4c169d4aa72/mmh3-5.3.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:6576400e7a748ec5c7ea72f38d626939876dd1756f4a0ccf552b8646dcf6f3e9", size = 41040, upload-time = "2026-08-26T04:56:29.766Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/89/b0/1b9763938cfae12acf14b682fcf05c92855974d921a5a985ecc197d1c672/msgspec-0.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:43bbb237feab761b815ed9df43b266114203f53596f9b6e6f00ebd79d178cdf2", size = 183910, upload-time = "2024-12-27T17:39:46.401Z" },
|
{ url = "https://files.pythonhosted.org/packages/62/9c/cb0f23e71bddcc519331c9787ec029e0d2fef64ed1bc490ad84b00a43950/mmh3-5.3.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:2b4cd2fcf1b517872530d9ef1a2de2ef9b86e5a0f8927539ea0b68337618244e", size = 42153, upload-time = "2026-08-26T04:56:30.954Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/87/81/0c8c93f0b92c97e326b279795f9c5b956c5a97af28ca0fbb9fd86c83737a/msgspec-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cfc033c02c3e0aec52b71710d7f84cb3ca5eb407ab2ad23d75631153fdb1f12", size = 210633, upload-time = "2024-12-27T17:39:49.099Z" },
|
{ url = "https://files.pythonhosted.org/packages/27/1c/99f2ff480922046a496c2e53728a13a467b68f01a0f48370577c0825a763/mmh3-5.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:f401a82d80c53d88605b82a80623edd95d922732d2c513c1c5f8e4b5e10c2913", size = 38796, upload-time = "2026-08-26T04:56:32.207Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d0/ef/c5422ce8af73928d194a6606f8ae36e93a52fd5e8df5abd366903a5ca8da/msgspec-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d911c442571605e17658ca2b416fd8579c5050ac9adc5e00c2cb3126c97f73bc", size = 213594, upload-time = "2024-12-27T17:39:51.204Z" },
|
{ url = "https://files.pythonhosted.org/packages/ad/05/e137452583b33a56d053ad48643a7c56e4cf466efc8a145da6a736913ae3/mmh3-5.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:86238bb78ff65c9fc1e6b371b78f271e23c5d61898222c201122209dc8eadc76", size = 39474, upload-time = "2026-08-26T04:56:33.196Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/19/2b/4137bc2ed45660444842d042be2cf5b18aa06efd2cda107cff18253b9653/msgspec-0.19.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:757b501fa57e24896cf40a831442b19a864f56d253679f34f260dcb002524a6c", size = 214053, upload-time = "2024-12-27T17:39:52.866Z" },
|
{ url = "https://files.pythonhosted.org/packages/74/e8/a9031fe6ed0eb06ab1c98eb76182eb01dc484dc46873a8e5ef3097d9bdf4/mmh3-5.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:222ea0a485e23bdcb29e28d15b8b01ebe34e8720bad4b5f92b645ed86e3fc715", size = 39983, upload-time = "2026-08-26T04:56:34.195Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/9d/e6/8ad51bdc806aac1dc501e8fe43f759f9ed7284043d722b53323ea421c360/msgspec-0.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5f0f65f29b45e2816d8bded36e6b837a4bf5fb60ec4bc3c625fa2c6da4124537", size = 219081, upload-time = "2024-12-27T17:39:55.142Z" },
|
{ url = "https://files.pythonhosted.org/packages/f9/ae/11459b39af5341de2a048998a717f57b3a1c4e6a9edf8fe09e314b2c263c/mmh3-5.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d95ee6696aa5b7283f4a27b67eb7db1c4fb5bb7a9117205d29ebaaa7f6294d7b", size = 55464, upload-time = "2026-08-26T04:56:35.23Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b1/ef/27dd35a7049c9a4f4211c6cd6a8c9db0a50647546f003a5867827ec45391/msgspec-0.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:067f0de1c33cfa0b6a8206562efdf6be5985b988b53dd244a8e06f993f27c8c0", size = 187467, upload-time = "2024-12-27T17:39:56.531Z" },
|
{ url = "https://files.pythonhosted.org/packages/49/b7/841b580415a614a3ad836db1cb8d57c425bbeb717c80263a9d979b1a4eac/mmh3-5.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e2f439ffd4fd7d64b77f6a287d4605700bad26fe12bb1b63b4ee45211344e2fc", size = 40084, upload-time = "2026-08-26T04:56:36.44Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/3c/cb/2842c312bbe618d8fefc8b9cedce37f773cdc8fa453306546dba2c21fd98/msgspec-0.19.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f12d30dd6266557aaaf0aa0f9580a9a8fbeadfa83699c487713e355ec5f0bd86", size = 190498, upload-time = "2024-12-27T17:40:00.427Z" },
|
{ url = "https://files.pythonhosted.org/packages/02/f6/f5cb0e2f7bb7df876847dab63ee984c3f6173569d5b892edc04bc797c1b7/mmh3-5.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7f9cb34c661454f73432112a81ac522ebe69500feeb8d77f744f6bd3e8b2f2ba", size = 39693, upload-time = "2026-08-26T04:56:37.428Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/58/95/c40b01b93465e1a5f3b6c7d91b10fb574818163740cc3acbe722d1e0e7e4/msgspec-0.19.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82b2c42c1b9ebc89e822e7e13bbe9d17ede0c23c187469fdd9505afd5a481314", size = 183950, upload-time = "2024-12-27T17:40:04.219Z" },
|
{ url = "https://files.pythonhosted.org/packages/b5/61/9506d0b30d7388846cc3b884ec63b8d67f3ad2d521e61775315111e70ec3/mmh3-5.3.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b6b7397804e9299bd0c01ea426245fa3d730d3e9c31f583f51aa87bed399c481", size = 97247, upload-time = "2026-08-26T04:56:38.439Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e8/f0/5b764e066ce9aba4b70d1db8b087ea66098c7c27d59b9dd8a3532774d48f/msgspec-0.19.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19746b50be214a54239aab822964f2ac81e38b0055cca94808359d779338c10e", size = 210647, upload-time = "2024-12-27T17:40:05.606Z" },
|
{ url = "https://files.pythonhosted.org/packages/da/6f/c6a4acf4715fede1e0acb17d6080ebe9b88290d113bbf9513a8728c65b4d/mmh3-5.3.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4a19b00097fcc8e3008bb006cd6bfaf0544e9fa2abc4cc77fbad57971a37dcc0", size = 103256, upload-time = "2026-08-26T04:56:39.52Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/9d/87/bc14f49bc95c4cb0dd0a8c56028a67c014ee7e6818ccdce74a4862af259b/msgspec-0.19.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60ef4bdb0ec8e4ad62e5a1f95230c08efb1f64f32e6e8dd2ced685bcc73858b5", size = 213563, upload-time = "2024-12-27T17:40:10.516Z" },
|
{ url = "https://files.pythonhosted.org/packages/a3/2a/f4fe4ebf2e44f49953ed1ee6b90d329d6843ebb949e60e881dbfde84e17d/mmh3-5.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83d93abf6a68d54b4e2c4c041ffcffeb94b1c9ab3171443fda3f5f19024be517", size = 106172, upload-time = "2026-08-26T04:56:40.67Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/53/2f/2b1c2b056894fbaa975f68f81e3014bb447516a8b010f1bed3fb0e016ed7/msgspec-0.19.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac7f7c377c122b649f7545810c6cd1b47586e3aa3059126ce3516ac7ccc6a6a9", size = 213996, upload-time = "2024-12-27T17:40:12.244Z" },
|
{ url = "https://files.pythonhosted.org/packages/1b/61/23168dc6fa92e1d9b57905b89c694a521a00570f0fe325bc3f6422fe6119/mmh3-5.3.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:598350a6adefb5799c800fd00bbeacbc115ee560e2fd7b35f703608c1037a2ed", size = 113020, upload-time = "2026-08-26T04:56:42.035Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/aa/5a/4cd408d90d1417e8d2ce6a22b98a6853c1b4d7cb7669153e4424d60087f6/msgspec-0.19.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5bc1472223a643f5ffb5bf46ccdede7f9795078194f14edd69e3aab7020d327", size = 219087, upload-time = "2024-12-27T17:40:14.881Z" },
|
{ url = "https://files.pythonhosted.org/packages/6e/f6/68dbb5461727bb14fbca2342a7bba4521400d679d64e00dd98a992eb0be4/mmh3-5.3.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c0772d6bba19a5601d24b3c6ce6627484fd5a3fd1d402913e1578b1447d51a0", size = 120648, upload-time = "2026-08-26T04:56:43.339Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/23/d8/f15b40611c2d5753d1abb0ca0da0c75348daf1252220e5dda2867bd81062/msgspec-0.19.0-cp313-cp313-win_amd64.whl", hash = "sha256:317050bc0f7739cb30d257ff09152ca309bf5a369854bbf1e57dffc310c1f20f", size = 187432, upload-time = "2024-12-27T17:40:16.256Z" },
|
{ url = "https://files.pythonhosted.org/packages/92/18/a879ce4c26e8c1741b575e6c854b2323fd7e116000965c8904428e66fba6/mmh3-5.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00105934e7d52f80b4364282918c37e2cc3cf9868ef4052016cbc39d8711c3f4", size = 99034, upload-time = "2026-08-26T04:56:44.771Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1b/28/b0548d78133f8e79bb16d6487f2df504ff4e16ea1330954f26be83b645ca/mmh3-5.3.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:99a5b0a908beb01b0e134b7b085d0ea6bfb7ed28ba3ed0737365aa2ce9bda0e4", size = 98587, upload-time = "2026-08-26T04:56:46.089Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/97/10/abfa952c6a443d07efb286b53b439d4418f7cfbac49fca8974cd78c17427/mmh3-5.3.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:da4ad7a0d4c589069c46101dcb55ee304616293bcf614f4c445b3ecc961fa836", size = 106407, upload-time = "2026-08-26T04:56:47.16Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a6/61/3b974a1cfe683c6cb01d2d3f2d5eddfca7e0a175d976d2307269143f4e0e/mmh3-5.3.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:8962a67c314f1da82957aee5b940698aaffff13e41b3298baa59d30cbddb23e2", size = 109922, upload-time = "2026-08-26T04:56:48.451Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0e/d2/ac7e18d6fcee3b26e06b3d33ecab4459b7aa6aff9859b13eb13e353a69ab/mmh3-5.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f61f2850b318c043961662f6cdd08e69b05f1d25d0e321782a3995d39f811548", size = 97456, upload-time = "2026-08-26T04:56:49.559Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ee/80/7911629b930d46ef8cb3165bce44f021d31361a2d7c56e35efe7b0d90493/mmh3-5.3.0-cp313-cp313-win32.whl", hash = "sha256:d7eec1b09bde3a9b6e2102717a587b9c9a96c360a1ef478b5668414619cac606", size = 40458, upload-time = "2026-08-26T04:56:50.785Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/45/c7/138d77c740f9d33ceffa968786fe23abe24ce442c210772b5b7cb6e0c198/mmh3-5.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:b1829bfe98d1f6e7bd79646b78e73dcef92c5aa32aaa622b9e07bf39df98c9b5", size = 41879, upload-time = "2026-08-26T04:56:51.785Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8b/e1/4312e5c18c8ef4060c9b50f1a645c9af7c3b79fad012c18fbe64a1b17103/mmh3-5.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:3fb0d4918b7d827ac804069849fde03d516628cbbf7bffe0b957ba6f1440cca6", size = 39203, upload-time = "2026-08-26T04:56:52.746Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "morphys"
|
||||||
|
version = "1.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f9/4f/cb781d0ac5d079adabc77dc4f0bc99fc81c390029bd33c6e70552139e762/morphys-1.0-py2.py3-none-any.whl", hash = "sha256:76d6dbaa4d65f597e59d332c81da786d83e4669387b9b2a750cfec74e7beec20", size = 5618, upload-time = "2017-01-10T20:08:56.872Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "msgspec"
|
||||||
|
version = "0.21.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/e3/60/f79b9b013a16fa3a58350c9295ddc6789f2e335f36ea61ed10a21b215364/msgspec-0.21.1.tar.gz", hash = "sha256:2313508e394b0d208f8f56892ca9b2799e2561329de9763b19619595a6c0f72c", size = 319193, upload-time = "2026-04-12T21:44:50.394Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7e/74/f11ede02839b19ff459f88e3145df5d711626ca84da4e23520cebf819367/msgspec-0.21.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:764173717a01743f007e9f74520ed281f24672c604514f7d76c1c3a10e8edb66", size = 196176, upload-time = "2026-04-12T21:44:17.613Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bb/40/4476c1bd341418a046c4955aff632ec769315d1e3cb94e6acf86d461f9ed/msgspec-0.21.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:344c7cd0eaed1fb81d7959f99100ef71ec9b536881a376f11b9a6c4803365697", size = 188524, upload-time = "2026-04-12T21:44:18.815Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ca/d9/9e9d7d7e5061b47540d03d640fab9b3965ba7ae49c1b2154861c8f007518/msgspec-0.21.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48943e278b3854c2f89f955ddc6f9f430d3f0784b16e47d10604ee0463cd21f5", size = 218880, upload-time = "2026-04-12T21:44:20.028Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/74/66/2bb344f34abb4b57e60c7c9c761994e0417b9718ec1460bf00c296f2a7ea/msgspec-0.21.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a9aa659ebb0101b1cbc31461212b87e341d961f0ab0772aaf068a99e001ec4aa", size = 225050, upload-time = "2026-04-12T21:44:21.577Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1a/84/7c1e412f76092277bf760cef12b7979d03314d259ab5b5cafde5d0c1722d/msgspec-0.21.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7b27d1a8ead2b6f5b0c4f2d07b8be1ccfcc041c8a0e704781edebe3ae13c484", size = 222713, upload-time = "2026-04-12T21:44:22.83Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4e/27/0bba04b2b4ef05f3d068429410bc71d2cea925f1596a8f41152cccd5edb8/msgspec-0.21.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:38fe93e86b61328fe544cb7fd871fad5a27c8734bfda90f65e5dbe288ae50f61", size = 227259, upload-time = "2026-04-12T21:44:24.11Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b0/2d/09574b0eea02fed2c2c1383dbaae2c7f79dc16dcd6487a886000afb5d7c4/msgspec-0.21.1-cp313-cp313-win_amd64.whl", hash = "sha256:8bc666331c35fcce05a7cd2d6221adbe0f6058f8e750711413d22793c080ac6a", size = 189857, upload-time = "2026-04-12T21:44:25.359Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/46/34/105b1576ad182879914f0c821f17ee1d13abb165cb060448f96fe2aff078/msgspec-0.21.1-cp313-cp313-win_arm64.whl", hash = "sha256:42bb1241e0750c1a4346f2aa84db26c5ffd99a4eb3a954927d9f149ff2f42898", size = 175403, upload-time = "2026-04-12T21:44:26.608Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "multiaddr"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = { git = "https://github.com/multiformats/py-multiaddr.git?rev=f86519daaa21699023d0037c58cdff600313dd09#f86519daaa21699023d0037c58cdff600313dd09" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "base58" },
|
||||||
|
{ name = "dnspython" },
|
||||||
|
{ name = "idna" },
|
||||||
|
{ name = "netaddr" },
|
||||||
|
{ name = "psutil" },
|
||||||
|
{ name = "py-cid" },
|
||||||
|
{ name = "py-multibase" },
|
||||||
|
{ name = "py-multicodec" },
|
||||||
|
{ name = "py-multihash" },
|
||||||
|
{ name = "trio" },
|
||||||
|
{ name = "trio-typing" },
|
||||||
|
{ name = "varint" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -665,24 +668,6 @@ version = "6.7.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/c2/9e/9f61ac18d9c8b475889f32ccfa91c9f59363480613fc807b6e3023d6f60b/multidict-6.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184", size = 76877, upload-time = "2025-10-06T14:49:20.884Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/38/6f/614f09a04e6184f8824268fce4bc925e9849edfa654ddd59f0b64508c595/multidict-6.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45", size = 45467, upload-time = "2025-10-06T14:49:22.054Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b3/93/c4f67a436dd026f2e780c433277fff72be79152894d9fc36f44569cab1a6/multidict-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa", size = 43834, upload-time = "2025-10-06T14:49:23.566Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/7f/f5/013798161ca665e4a422afbc5e2d9e4070142a9ff8905e482139cd09e4d0/multidict-6.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7", size = 250545, upload-time = "2025-10-06T14:49:24.882Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/71/2f/91dbac13e0ba94669ea5119ba267c9a832f0cb65419aca75549fcf09a3dc/multidict-6.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e", size = 258305, upload-time = "2025-10-06T14:49:26.778Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ef/b0/754038b26f6e04488b48ac621f779c341338d78503fb45403755af2df477/multidict-6.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546", size = 242363, upload-time = "2025-10-06T14:49:28.562Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/87/15/9da40b9336a7c9fa606c4cf2ed80a649dffeb42b905d4f63a1d7eb17d746/multidict-6.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4", size = 268375, upload-time = "2025-10-06T14:49:29.96Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/82/72/c53fcade0cc94dfaad583105fd92b3a783af2091eddcb41a6d5a52474000/multidict-6.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1", size = 269346, upload-time = "2025-10-06T14:49:31.404Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/0d/e2/9baffdae21a76f77ef8447f1a05a96ec4bc0a24dae08767abc0a2fe680b8/multidict-6.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d", size = 256107, upload-time = "2025-10-06T14:49:32.974Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/3c/06/3f06f611087dc60d65ef775f1fb5aca7c6d61c6db4990e7cda0cef9b1651/multidict-6.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304", size = 253592, upload-time = "2025-10-06T14:49:34.52Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/20/24/54e804ec7945b6023b340c412ce9c3f81e91b3bf5fa5ce65558740141bee/multidict-6.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12", size = 251024, upload-time = "2025-10-06T14:49:35.956Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/14/48/011cba467ea0b17ceb938315d219391d3e421dfd35928e5dbdc3f4ae76ef/multidict-6.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62", size = 251484, upload-time = "2025-10-06T14:49:37.631Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/0d/2f/919258b43bb35b99fa127435cfb2d91798eb3a943396631ef43e3720dcf4/multidict-6.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0", size = 263579, upload-time = "2025-10-06T14:49:39.502Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/31/22/a0e884d86b5242b5a74cf08e876bdf299e413016b66e55511f7a804a366e/multidict-6.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a", size = 259654, upload-time = "2025-10-06T14:49:41.32Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b2/e5/17e10e1b5c5f5a40f2fcbb45953c9b215f8a4098003915e46a93f5fcaa8f/multidict-6.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8", size = 251511, upload-time = "2025-10-06T14:49:46.021Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e3/9a/201bb1e17e7af53139597069c375e7b0dcbd47594604f65c2d5359508566/multidict-6.7.0-cp312-cp312-win32.whl", hash = "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4", size = 41895, upload-time = "2025-10-06T14:49:48.718Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/46/e2/348cd32faad84eaf1d20cce80e2bb0ef8d312c55bca1f7fa9865e7770aaf/multidict-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b", size = 46073, upload-time = "2025-10-06T14:49:50.28Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/25/ec/aad2613c1910dce907480e0c3aa306905830f25df2e54ccc9dea450cb5aa/multidict-6.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec", size = 43226, upload-time = "2025-10-06T14:49:52.304Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d2/86/33272a544eeb36d66e4d9a920602d1a2f57d4ebea4ef3cdfe5a912574c95/multidict-6.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6", size = 76135, upload-time = "2025-10-06T14:49:54.26Z" },
|
{ url = "https://files.pythonhosted.org/packages/d2/86/33272a544eeb36d66e4d9a920602d1a2f57d4ebea4ef3cdfe5a912574c95/multidict-6.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6", size = 76135, upload-time = "2025-10-06T14:49:54.26Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/91/1c/eb97db117a1ebe46d457a3d235a7b9d2e6dcab174f42d1b67663dd9e5371/multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159", size = 45117, upload-time = "2025-10-06T14:49:55.82Z" },
|
{ url = "https://files.pythonhosted.org/packages/91/1c/eb97db117a1ebe46d457a3d235a7b9d2e6dcab174f42d1b67663dd9e5371/multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159", size = 45117, upload-time = "2025-10-06T14:49:55.82Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f1/d8/6c3442322e41fb1dd4de8bd67bfd11cd72352ac131f6368315617de752f1/multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca", size = 43472, upload-time = "2025-10-06T14:49:57.048Z" },
|
{ url = "https://files.pythonhosted.org/packages/f1/d8/6c3442322e41fb1dd4de8bd67bfd11cd72352ac131f6368315617de752f1/multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca", size = 43472, upload-time = "2025-10-06T14:49:57.048Z" },
|
||||||
|
|
@ -740,6 +725,15 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" },
|
{ url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "netaddr"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/54/90/188b2a69654f27b221fba92fda7217778208532c962509e959a9cee5229d/netaddr-1.3.0.tar.gz", hash = "sha256:5c3c3d9895b551b763779ba7db7a03487dc1f8e3b385af819af341ae9ef6e48a", size = 2260504, upload-time = "2024-05-28T21:30:37.743Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/12/cc/f4fe2c7ce68b92cbf5b2d379ca366e1edae38cccaad00f69f529b460c3ef/netaddr-1.3.0-py3-none-any.whl", hash = "sha256:c2c6a8ebe5554ce33b7d5b3a306b71bbb373e000bbbf2350dd5213cc56e3dbbe", size = 2262023, upload-time = "2024-05-28T21:30:34.191Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "numba"
|
name = "numba"
|
||||||
version = "0.62.1"
|
version = "0.62.1"
|
||||||
|
|
@ -750,11 +744,6 @@ dependencies = [
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/a3/20/33dbdbfe60e5fd8e3dbfde299d106279a33d9f8308346022316781368591/numba-0.62.1.tar.gz", hash = "sha256:7b774242aa890e34c21200a1fc62e5b5757d5286267e71103257f4e2af0d5161", size = 2749817, upload-time = "2025-09-29T10:46:31.551Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/a3/20/33dbdbfe60e5fd8e3dbfde299d106279a33d9f8308346022316781368591/numba-0.62.1.tar.gz", hash = "sha256:7b774242aa890e34c21200a1fc62e5b5757d5286267e71103257f4e2af0d5161", size = 2749817, upload-time = "2025-09-29T10:46:31.551Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/5e/fa/30fa6873e9f821c0ae755915a3ca444e6ff8d6a7b6860b669a3d33377ac7/numba-0.62.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:1b743b32f8fa5fff22e19c2e906db2f0a340782caf024477b97801b918cf0494", size = 2685346, upload-time = "2025-09-29T10:43:43.677Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a9/d5/504ce8dc46e0dba2790c77e6b878ee65b60fe3e7d6d0006483ef6fde5a97/numba-0.62.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:90fa21b0142bcf08ad8e32a97d25d0b84b1e921bc9423f8dda07d3652860eef6", size = 2688139, upload-time = "2025-09-29T10:44:04.894Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/50/5f/6a802741176c93f2ebe97ad90751894c7b0c922b52ba99a4395e79492205/numba-0.62.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6ef84d0ac19f1bf80431347b6f4ce3c39b7ec13f48f233a48c01e2ec06ecbc59", size = 3796453, upload-time = "2025-09-29T10:42:52.771Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/7e/df/efd21527d25150c4544eccc9d0b7260a5dec4b7e98b5a581990e05a133c0/numba-0.62.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9315cc5e441300e0ca07c828a627d92a6802bcbf27c5487f31ae73783c58da53", size = 3496451, upload-time = "2025-09-29T10:43:19.279Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/80/44/79bfdab12a02796bf4f1841630355c82b5a69933b1d50eb15c7fa37dabe8/numba-0.62.1-cp312-cp312-win_amd64.whl", hash = "sha256:44e3aa6228039992f058f5ebfcfd372c83798e9464297bdad8cc79febcf7891e", size = 2745552, upload-time = "2025-09-29T10:44:26.399Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/22/76/501ea2c07c089ef1386868f33dff2978f43f51b854e34397b20fc55e0a58/numba-0.62.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:b72489ba8411cc9fdcaa2458d8f7677751e94f0109eeb53e5becfdc818c64afb", size = 2685766, upload-time = "2025-09-29T10:43:49.161Z" },
|
{ url = "https://files.pythonhosted.org/packages/22/76/501ea2c07c089ef1386868f33dff2978f43f51b854e34397b20fc55e0a58/numba-0.62.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:b72489ba8411cc9fdcaa2458d8f7677751e94f0109eeb53e5becfdc818c64afb", size = 2685766, upload-time = "2025-09-29T10:43:49.161Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/80/68/444986ed95350c0611d5c7b46828411c222ce41a0c76707c36425d27ce29/numba-0.62.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:44a1412095534a26fb5da2717bc755b57da5f3053965128fe3dc286652cc6a92", size = 2688741, upload-time = "2025-09-29T10:44:10.07Z" },
|
{ url = "https://files.pythonhosted.org/packages/80/68/444986ed95350c0611d5c7b46828411c222ce41a0c76707c36425d27ce29/numba-0.62.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:44a1412095534a26fb5da2717bc755b57da5f3053965128fe3dc286652cc6a92", size = 2688741, upload-time = "2025-09-29T10:44:10.07Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/78/7e/bf2e3634993d57f95305c7cee4c9c6cb3c9c78404ee7b49569a0dfecfe33/numba-0.62.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8c9460b9e936c5bd2f0570e20a0a5909ee6e8b694fd958b210e3bde3a6dba2d7", size = 3804576, upload-time = "2025-09-29T10:42:59.53Z" },
|
{ url = "https://files.pythonhosted.org/packages/78/7e/bf2e3634993d57f95305c7cee4c9c6cb3c9c78404ee7b49569a0dfecfe33/numba-0.62.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8c9460b9e936c5bd2f0570e20a0a5909ee6e8b694fd958b210e3bde3a6dba2d7", size = 3804576, upload-time = "2025-09-29T10:42:59.53Z" },
|
||||||
|
|
@ -768,17 +757,6 @@ version = "2.3.5"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/76/65/21b3bc86aac7b8f2862db1e808f1ea22b028e30a225a34a5ede9bf8678f2/numpy-2.3.5.tar.gz", hash = "sha256:784db1dcdab56bf0517743e746dfb0f885fc68d948aba86eeec2cba234bdf1c0", size = 20584950, upload-time = "2025-11-16T22:52:42.067Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/76/65/21b3bc86aac7b8f2862db1e808f1ea22b028e30a225a34a5ede9bf8678f2/numpy-2.3.5.tar.gz", hash = "sha256:784db1dcdab56bf0517743e746dfb0f885fc68d948aba86eeec2cba234bdf1c0", size = 20584950, upload-time = "2025-11-16T22:52:42.067Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/44/37/e669fe6cbb2b96c62f6bbedc6a81c0f3b7362f6a59230b23caa673a85721/numpy-2.3.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:74ae7b798248fe62021dbf3c914245ad45d1a6b0cb4a29ecb4b31d0bfbc4cc3e", size = 16733873, upload-time = "2025-11-16T22:49:49.84Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c5/65/df0db6c097892c9380851ab9e44b52d4f7ba576b833996e0080181c0c439/numpy-2.3.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee3888d9ff7c14604052b2ca5535a30216aa0a58e948cdd3eeb8d3415f638769", size = 12259838, upload-time = "2025-11-16T22:49:52.863Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/5b/e1/1ee06e70eb2136797abe847d386e7c0e830b67ad1d43f364dd04fa50d338/numpy-2.3.5-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:612a95a17655e213502f60cfb9bf9408efdc9eb1d5f50535cc6eb365d11b42b5", size = 5088378, upload-time = "2025-11-16T22:49:55.055Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/6d/9c/1ca85fb86708724275103b81ec4cf1ac1d08f465368acfc8da7ab545bdae/numpy-2.3.5-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3101e5177d114a593d79dd79658650fe28b5a0d8abeb8ce6f437c0e6df5be1a4", size = 6628559, upload-time = "2025-11-16T22:49:57.371Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/74/78/fcd41e5a0ce4f3f7b003da85825acddae6d7ecb60cf25194741b036ca7d6/numpy-2.3.5-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b973c57ff8e184109db042c842423ff4f60446239bd585a5131cc47f06f789d", size = 14250702, upload-time = "2025-11-16T22:49:59.632Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b6/23/2a1b231b8ff672b4c450dac27164a8b2ca7d9b7144f9c02d2396518352eb/numpy-2.3.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d8163f43acde9a73c2a33605353a4f1bc4798745a8b1d73183b28e5b435ae28", size = 16606086, upload-time = "2025-11-16T22:50:02.127Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a0/c5/5ad26fbfbe2012e190cc7d5003e4d874b88bb18861d0829edc140a713021/numpy-2.3.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:51c1e14eb1e154ebd80e860722f9e6ed6ec89714ad2db2d3aa33c31d7c12179b", size = 16025985, upload-time = "2025-11-16T22:50:04.536Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d2/fa/dd48e225c46c819288148d9d060b047fd2a6fb1eb37eae25112ee4cb4453/numpy-2.3.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b46b4ec24f7293f23adcd2d146960559aaf8020213de8ad1909dba6c013bf89c", size = 18542976, upload-time = "2025-11-16T22:50:07.557Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/05/79/ccbd23a75862d95af03d28b5c6901a1b7da4803181513d52f3b86ed9446e/numpy-2.3.5-cp312-cp312-win32.whl", hash = "sha256:3997b5b3c9a771e157f9aae01dd579ee35ad7109be18db0e85dbdbe1de06e952", size = 6285274, upload-time = "2025-11-16T22:50:10.746Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/2d/57/8aeaf160312f7f489dea47ab61e430b5cb051f59a98ae68b7133ce8fa06a/numpy-2.3.5-cp312-cp312-win_amd64.whl", hash = "sha256:86945f2ee6d10cdfd67bcb4069c1662dd711f7e2a4343db5cecec06b87cf31aa", size = 12782922, upload-time = "2025-11-16T22:50:12.811Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/78/a6/aae5cc2ca78c45e64b9ef22f089141d661516856cf7c8a54ba434576900d/numpy-2.3.5-cp312-cp312-win_arm64.whl", hash = "sha256:f28620fe26bee16243be2b7b874da327312240a7cdc38b769a697578d2100013", size = 10194667, upload-time = "2025-11-16T22:50:16.16Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/db/69/9cde09f36da4b5a505341180a3f2e6fadc352fd4d2b7096ce9778db83f1a/numpy-2.3.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d0f23b44f57077c1ede8c5f26b30f706498b4862d3ff0a7298b8411dd2f043ff", size = 16728251, upload-time = "2025-11-16T22:50:19.013Z" },
|
{ url = "https://files.pythonhosted.org/packages/db/69/9cde09f36da4b5a505341180a3f2e6fadc352fd4d2b7096ce9778db83f1a/numpy-2.3.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d0f23b44f57077c1ede8c5f26b30f706498b4862d3ff0a7298b8411dd2f043ff", size = 16728251, upload-time = "2025-11-16T22:50:19.013Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/79/fb/f505c95ceddd7027347b067689db71ca80bd5ecc926f913f1a23e65cf09b/numpy-2.3.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa5bc7c5d59d831d9773d1170acac7893ce3a5e130540605770ade83280e7188", size = 12254652, upload-time = "2025-11-16T22:50:21.487Z" },
|
{ url = "https://files.pythonhosted.org/packages/79/fb/f505c95ceddd7027347b067689db71ca80bd5ecc926f913f1a23e65cf09b/numpy-2.3.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa5bc7c5d59d831d9773d1170acac7893ce3a5e130540605770ade83280e7188", size = 12254652, upload-time = "2025-11-16T22:50:21.487Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/78/da/8c7738060ca9c31b30e9301ee0cf6c5ffdbf889d9593285a1cead337f9a5/numpy-2.3.5-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:ccc933afd4d20aad3c00bcef049cb40049f7f196e0397f1109dba6fed63267b0", size = 5083172, upload-time = "2025-11-16T22:50:24.562Z" },
|
{ url = "https://files.pythonhosted.org/packages/78/da/8c7738060ca9c31b30e9301ee0cf6c5ffdbf889d9593285a1cead337f9a5/numpy-2.3.5-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:ccc933afd4d20aad3c00bcef049cb40049f7f196e0397f1109dba6fed63267b0", size = 5083172, upload-time = "2025-11-16T22:50:24.562Z" },
|
||||||
|
|
@ -808,10 +786,6 @@ name = "order-book"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/ca/7e/a118618ff5cb05040a27f3f1c6325c7324e998a90d3635b6f4b557f89f06/order_book-0.6.1.tar.gz", hash = "sha256:636cee1e6b9b74afd623797ff62a8decbf6de28db398d4a818ff9e73128f9f21", size = 34054, upload-time = "2024-04-23T00:15:05.66Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/ca/7e/a118618ff5cb05040a27f3f1c6325c7324e998a90d3635b6f4b557f89f06/order_book-0.6.1.tar.gz", hash = "sha256:636cee1e6b9b74afd623797ff62a8decbf6de28db398d4a818ff9e73128f9f21", size = 34054, upload-time = "2024-04-23T00:15:05.66Z" }
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/cb/4c/1b9854b19dc9738d6398786089f5f7a411d28b55b3942ac950a6f7e3ea03/order_book-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2c64369d4404614b5a7fdd3687c52e79515d9bac737d70b222527554930542e", size = 26747, upload-time = "2024-04-23T00:15:04.289Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9b/b4/8e4cf9fe1c9c73ce21963b6d5c1005551d4fa6bb4093cadad4c0875574d1/order_book-0.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:285e4046751e2aaf0edc3b180fc229c2b316723d9332bcac4575a84ae90090b6", size = 66768, upload-time = "2024-04-23T00:14:46.898Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "outcome"
|
name = "outcome"
|
||||||
|
|
@ -845,14 +819,6 @@ dependencies = [
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/de/da/b1dc0481ab8d55d0f46e343cfe67d4551a0e14fcee52bd38ca1bd73258d8/pandas-3.0.0.tar.gz", hash = "sha256:0facf7e87d38f721f0af46fe70d97373a37701b1c09f7ed7aeeb292ade5c050f", size = 4633005, upload-time = "2026-01-21T15:52:04.726Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/de/da/b1dc0481ab8d55d0f46e343cfe67d4551a0e14fcee52bd38ca1bd73258d8/pandas-3.0.0.tar.gz", hash = "sha256:0facf7e87d38f721f0af46fe70d97373a37701b1c09f7ed7aeeb292ade5c050f", size = 4633005, upload-time = "2026-01-21T15:52:04.726Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/0b/38/db33686f4b5fa64d7af40d96361f6a4615b8c6c8f1b3d334eee46ae6160e/pandas-3.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9803b31f5039b3c3b10cc858c5e40054adb4b29b4d81cb2fd789f4121c8efbcd", size = 10334013, upload-time = "2026-01-21T15:50:34.771Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a5/7b/9254310594e9774906bacdd4e732415e1f86ab7dbb4b377ef9ede58cd8ec/pandas-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14c2a4099cd38a1d18ff108168ea417909b2dea3bd1ebff2ccf28ddb6a74d740", size = 9874154, upload-time = "2026-01-21T15:50:36.67Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/63/d4/726c5a67a13bc66643e66d2e9ff115cead482a44fc56991d0c4014f15aaf/pandas-3.0.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d257699b9a9960e6125686098d5714ac59d05222bef7a5e6af7a7fd87c650801", size = 10384433, upload-time = "2026-01-21T15:50:39.132Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/bf/2e/9211f09bedb04f9832122942de8b051804b31a39cfbad199a819bb88d9f3/pandas-3.0.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:69780c98f286076dcafca38d8b8eee1676adf220199c0a39f0ecbf976b68151a", size = 10864519, upload-time = "2026-01-21T15:50:41.043Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/00/8d/50858522cdc46ac88b9afdc3015e298959a70a08cd21e008a44e9520180c/pandas-3.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4a66384f017240f3858a4c8a7cf21b0591c3ac885cddb7758a589f0f71e87ebb", size = 11394124, upload-time = "2026-01-21T15:50:43.377Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/86/3f/83b2577db02503cd93d8e95b0f794ad9d4be0ba7cb6c8bcdcac964a34a42/pandas-3.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be8c515c9bc33989d97b89db66ea0cececb0f6e3c2a87fcc8b69443a6923e95f", size = 11920444, upload-time = "2026-01-21T15:50:45.932Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/64/2d/4f8a2f192ed12c90a0aab47f5557ece0e56b0370c49de9454a09de7381b2/pandas-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:a453aad8c4f4e9f166436994a33884442ea62aa8b27d007311e87521b97246e1", size = 9730970, upload-time = "2026-01-21T15:50:47.962Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d4/64/ff571be435cf1e643ca98d0945d76732c0b4e9c37191a89c8550b105eed1/pandas-3.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:da768007b5a33057f6d9053563d6b74dd6d029c337d93c6d0d22a763a5c2ecc0", size = 9041950, upload-time = "2026-01-21T15:50:50.422Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/6f/fa/7f0ac4ca8877c57537aaff2a842f8760e630d8e824b730eb2e859ffe96ca/pandas-3.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b78d646249b9a2bc191040988c7bb524c92fa8534fb0898a0741d7e6f2ffafa6", size = 10307129, upload-time = "2026-01-21T15:50:52.877Z" },
|
{ url = "https://files.pythonhosted.org/packages/6f/fa/7f0ac4ca8877c57537aaff2a842f8760e630d8e824b730eb2e859ffe96ca/pandas-3.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b78d646249b9a2bc191040988c7bb524c92fa8534fb0898a0741d7e6f2ffafa6", size = 10307129, upload-time = "2026-01-21T15:50:52.877Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6f/11/28a221815dcea4c0c9414dfc845e34a84a6a7dabc6da3194498ed5ba4361/pandas-3.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bc9cba7b355cb4162442a88ce495e01cb605f17ac1e27d6596ac963504e0305f", size = 9850201, upload-time = "2026-01-21T15:50:54.807Z" },
|
{ url = "https://files.pythonhosted.org/packages/6f/11/28a221815dcea4c0c9414dfc845e34a84a6a7dabc6da3194498ed5ba4361/pandas-3.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bc9cba7b355cb4162442a88ce495e01cb605f17ac1e27d6596ac963504e0305f", size = 9850201, upload-time = "2026-01-21T15:50:54.807Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ba/da/53bbc8c5363b7e5bd10f9ae59ab250fc7a382ea6ba08e4d06d8694370354/pandas-3.0.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c9a1a149aed3b6c9bf246033ff91e1b02d529546c5d6fb6b74a28fea0cf4c70", size = 10354031, upload-time = "2026-01-21T15:50:57.463Z" },
|
{ url = "https://files.pythonhosted.org/packages/ba/da/53bbc8c5363b7e5bd10f9ae59ab250fc7a382ea6ba08e4d06d8694370354/pandas-3.0.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c9a1a149aed3b6c9bf246033ff91e1b02d529546c5d6fb6b74a28fea0cf4c70", size = 10354031, upload-time = "2026-01-21T15:50:57.463Z" },
|
||||||
|
|
@ -894,16 +860,6 @@ dependencies = [
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/23/7c/009c12b86c7cc6c403aec80f8a4308598dfc5995e5c523a5491faaa3952e/pendulum-3.1.0.tar.gz", hash = "sha256:66f96303560f41d097bee7d2dc98ffca716fbb3a832c4b3062034c2d45865015", size = 85930, upload-time = "2025-04-19T14:30:01.675Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/23/7c/009c12b86c7cc6c403aec80f8a4308598dfc5995e5c523a5491faaa3952e/pendulum-3.1.0.tar.gz", hash = "sha256:66f96303560f41d097bee7d2dc98ffca716fbb3a832c4b3062034c2d45865015", size = 85930, upload-time = "2025-04-19T14:30:01.675Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/7a/d7/b1bfe15a742f2c2713acb1fdc7dc3594ff46ef9418ac6a96fcb12a6ba60b/pendulum-3.1.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4dfd53e7583ccae138be86d6c0a0b324c7547df2afcec1876943c4d481cf9608", size = 336209, upload-time = "2025-04-19T14:01:27.815Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/eb/87/0392da0c603c828b926d9f7097fbdddaafc01388cb8a00888635d04758c3/pendulum-3.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6a6e06a28f3a7d696546347805536f6f38be458cb79de4f80754430696bea9e6", size = 323130, upload-time = "2025-04-19T14:01:29.336Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c0/61/95f1eec25796be6dddf71440ee16ec1fd0c573fc61a73bd1ef6daacd529a/pendulum-3.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e68d6a51880708084afd8958af42dc8c5e819a70a6c6ae903b1c4bfc61e0f25", size = 341509, upload-time = "2025-04-19T14:01:31.1Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b5/7b/eb0f5e6aa87d5e1b467a1611009dbdc92f0f72425ebf07669bfadd8885a6/pendulum-3.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e3f1e5da39a7ea7119efda1dd96b529748c1566f8a983412d0908455d606942", size = 378674, upload-time = "2025-04-19T14:01:32.974Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/29/68/5a4c1b5de3e54e16cab21d2ec88f9cd3f18599e96cc90a441c0b0ab6b03f/pendulum-3.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9af1e5eeddb4ebbe1b1c9afb9fd8077d73416ade42dd61264b3f3b87742e0bb", size = 436133, upload-time = "2025-04-19T14:01:34.349Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/87/5d/f7a1d693e5c0f789185117d5c1d5bee104f5b0d9fbf061d715fb61c840a8/pendulum-3.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20f74aa8029a42e327bfc150472e0e4d2358fa5d795f70460160ba81b94b6945", size = 351232, upload-time = "2025-04-19T14:01:35.669Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/30/77/c97617eb31f1d0554edb073201a294019b9e0a9bd2f73c68e6d8d048cd6b/pendulum-3.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:cf6229e5ee70c2660148523f46c472e677654d0097bec010d6730f08312a4931", size = 521562, upload-time = "2025-04-19T14:01:37.05Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/76/22/0d0ef3393303877e757b848ecef8a9a8c7627e17e7590af82d14633b2cd1/pendulum-3.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:350cabb23bf1aec7c7694b915d3030bff53a2ad4aeabc8c8c0d807c8194113d6", size = 523221, upload-time = "2025-04-19T14:01:38.444Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/99/f3/aefb579aa3cebd6f2866b205fc7a60d33e9a696e9e629024752107dc3cf5/pendulum-3.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:42959341e843077c41d47420f28c3631de054abd64da83f9b956519b5c7a06a7", size = 260502, upload-time = "2025-04-19T14:01:39.814Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/02/74/4332b5d6e34c63d4df8e8eab2249e74c05513b1477757463f7fdca99e9be/pendulum-3.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:006758e2125da2e624493324dfd5d7d1b02b0c44bc39358e18bf0f66d0767f5f", size = 253089, upload-time = "2025-04-19T14:01:41.171Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8e/1f/af928ba4aa403dac9569f787adcf024005e7654433d71f7a84e608716837/pendulum-3.1.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:28658b0baf4b30eb31d096a375983cfed033e60c0a7bbe94fa23f06cd779b50b", size = 336209, upload-time = "2025-04-19T14:01:42.775Z" },
|
{ url = "https://files.pythonhosted.org/packages/8e/1f/af928ba4aa403dac9569f787adcf024005e7654433d71f7a84e608716837/pendulum-3.1.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:28658b0baf4b30eb31d096a375983cfed033e60c0a7bbe94fa23f06cd779b50b", size = 336209, upload-time = "2025-04-19T14:01:42.775Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b6/16/b010643007ba964c397da7fa622924423883c1bbff1a53f9d1022cd7f024/pendulum-3.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b114dcb99ce511cb8f5495c7b6f0056b2c3dba444ef1ea6e48030d7371bd531a", size = 323132, upload-time = "2025-04-19T14:01:44.577Z" },
|
{ url = "https://files.pythonhosted.org/packages/b6/16/b010643007ba964c397da7fa622924423883c1bbff1a53f9d1022cd7f024/pendulum-3.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b114dcb99ce511cb8f5495c7b6f0056b2c3dba444ef1ea6e48030d7371bd531a", size = 323132, upload-time = "2025-04-19T14:01:44.577Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/64/19/c3c47aeecb5d9bceb0e89faafd800d39809b696c5b7bba8ec8370ad5052c/pendulum-3.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2404a6a54c80252ea393291f0b7f35525a61abae3d795407f34e118a8f133a18", size = 341509, upload-time = "2025-04-19T14:01:46.084Z" },
|
{ url = "https://files.pythonhosted.org/packages/64/19/c3c47aeecb5d9bceb0e89faafd800d39809b696c5b7bba8ec8370ad5052c/pendulum-3.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2404a6a54c80252ea393291f0b7f35525a61abae3d795407f34e118a8f133a18", size = 341509, upload-time = "2025-04-19T14:01:46.084Z" },
|
||||||
|
|
@ -1021,7 +977,7 @@ requires-dist = [
|
||||||
{ name = "exchange-calendars", specifier = ">=4.13.1" },
|
{ name = "exchange-calendars", specifier = ">=4.13.1" },
|
||||||
{ name = "httpx", specifier = ">=0.27.0,<0.28.0" },
|
{ name = "httpx", specifier = ">=0.27.0,<0.28.0" },
|
||||||
{ name = "ib-async", specifier = ">=2.1.0" },
|
{ name = "ib-async", specifier = ">=2.1.0" },
|
||||||
{ name = "msgspec", specifier = ">=0.19.0,<0.20" },
|
{ name = "msgspec", specifier = ">=0.20.0" },
|
||||||
{ name = "numba", specifier = ">=0.61.0" },
|
{ name = "numba", specifier = ">=0.61.0" },
|
||||||
{ name = "numpy", specifier = ">=2.0" },
|
{ name = "numpy", specifier = ">=2.0" },
|
||||||
{ name = "pendulum" },
|
{ name = "pendulum" },
|
||||||
|
|
@ -1034,7 +990,7 @@ requires-dist = [
|
||||||
{ name = "tomli", specifier = ">=2.0.1,<3.0.0" },
|
{ name = "tomli", specifier = ">=2.0.1,<3.0.0" },
|
||||||
{ name = "tomli-w", specifier = ">=1.0.0,<2.0.0" },
|
{ name = "tomli-w", specifier = ">=1.0.0,<2.0.0" },
|
||||||
{ name = "tomlkit", git = "https://github.com/pikers/tomlkit.git?branch=piker_pin" },
|
{ name = "tomlkit", git = "https://github.com/pikers/tomlkit.git?branch=piker_pin" },
|
||||||
{ name = "tractor", git = "https://github.com/goodboy/tractor.git?branch=main" },
|
{ name = "tractor", git = "https://github.com/goodboy/tractor.git?branch=wkt%2Faddr_unpacking" },
|
||||||
{ name = "trio", specifier = ">=0.27" },
|
{ name = "trio", specifier = ">=0.27" },
|
||||||
{ name = "trio-typing", specifier = ">=0.10.0" },
|
{ name = "trio-typing", specifier = ">=0.10.0" },
|
||||||
{ name = "trio-util", specifier = ">=0.7.0,<0.8.0" },
|
{ name = "trio-util", specifier = ">=0.7.0,<0.8.0" },
|
||||||
|
|
@ -1059,7 +1015,7 @@ dev = [
|
||||||
{ name = "pytest" },
|
{ name = "pytest" },
|
||||||
{ name = "qdarkstyle", specifier = ">=3.0.2,<4.0.0" },
|
{ name = "qdarkstyle", specifier = ">=3.0.2,<4.0.0" },
|
||||||
{ name = "rapidfuzz", specifier = ">=3.2.0,<4.0.0" },
|
{ name = "rapidfuzz", specifier = ">=3.2.0,<4.0.0" },
|
||||||
{ name = "xonsh", specifier = ">=0.22.2" },
|
{ name = "xonsh", specifier = ">=0.24.2" },
|
||||||
]
|
]
|
||||||
lint = [{ name = "ruff", specifier = ">=0.9.6" }]
|
lint = [{ name = "ruff", specifier = ">=0.9.6" }]
|
||||||
repl = [
|
repl = [
|
||||||
|
|
@ -1068,7 +1024,7 @@ repl = [
|
||||||
{ name = "pexpect", specifier = ">=4.9.0" },
|
{ name = "pexpect", specifier = ">=4.9.0" },
|
||||||
{ name = "prompt-toolkit", specifier = "==3.0.40" },
|
{ name = "prompt-toolkit", specifier = "==3.0.40" },
|
||||||
{ name = "pyperclip", specifier = ">=1.9.0" },
|
{ name = "pyperclip", specifier = ">=1.9.0" },
|
||||||
{ name = "xonsh", specifier = ">=0.22.2" },
|
{ name = "xonsh", specifier = ">=0.24.2" },
|
||||||
]
|
]
|
||||||
testing = [{ name = "pytest" }]
|
testing = [{ name = "pytest" }]
|
||||||
uis = [
|
uis = [
|
||||||
|
|
@ -1156,21 +1112,6 @@ version = "0.4.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/a2/0f/f17b1b2b221d5ca28b4b876e8bb046ac40466513960646bda8e1853cdfa2/propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", size = 80061, upload-time = "2025-10-08T19:46:46.075Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/76/47/8ccf75935f51448ba9a16a71b783eb7ef6b9ee60f5d14c7f8a8a79fbeed7/propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", size = 46037, upload-time = "2025-10-08T19:46:47.23Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", size = 47324, upload-time = "2025-10-08T19:46:48.384Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9e/d3/6c7ee328b39a81ee877c962469f1e795f9db87f925251efeb0545e0020d0/propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", size = 225505, upload-time = "2025-10-08T19:46:50.055Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/01/5d/1c53f4563490b1d06a684742cc6076ef944bc6457df6051b7d1a877c057b/propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", size = 230242, upload-time = "2025-10-08T19:46:51.815Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/20/e1/ce4620633b0e2422207c3cb774a0ee61cac13abc6217763a7b9e2e3f4a12/propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", size = 238474, upload-time = "2025-10-08T19:46:53.208Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", size = 221575, upload-time = "2025-10-08T19:46:54.511Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/6e/a5/8a5e8678bcc9d3a1a15b9a29165640d64762d424a16af543f00629c87338/propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", size = 216736, upload-time = "2025-10-08T19:46:56.212Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/f1/63/b7b215eddeac83ca1c6b934f89d09a625aa9ee4ba158338854c87210cc36/propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", size = 213019, upload-time = "2025-10-08T19:46:57.595Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/57/74/f580099a58c8af587cac7ba19ee7cb418506342fbbe2d4a4401661cca886/propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", size = 220376, upload-time = "2025-10-08T19:46:59.067Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c4/ee/542f1313aff7eaf19c2bb758c5d0560d2683dac001a1c96d0774af799843/propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", size = 226988, upload-time = "2025-10-08T19:47:00.544Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8f/18/9c6b015dd9c6930f6ce2229e1f02fb35298b847f2087ea2b436a5bfa7287/propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", size = 215615, upload-time = "2025-10-08T19:47:01.968Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/80/9e/e7b85720b98c45a45e1fca6a177024934dc9bc5f4d5dd04207f216fc33ed/propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", size = 38066, upload-time = "2025-10-08T19:47:03.503Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", size = 41655, upload-time = "2025-10-08T19:47:04.973Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/68/ab/6b5c191bb5de08036a8c697b265d4ca76148efb10fa162f14af14fb5f076/propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", size = 37789, upload-time = "2025-10-08T19:47:06.077Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/bf/df/6d9c1b6ac12b003837dde8a10231a7344512186e87b36e855bef32241942/propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", size = 77750, upload-time = "2025-10-08T19:47:07.648Z" },
|
{ url = "https://files.pythonhosted.org/packages/bf/df/6d9c1b6ac12b003837dde8a10231a7344512186e87b36e855bef32241942/propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", size = 77750, upload-time = "2025-10-08T19:47:07.648Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8b/e8/677a0025e8a2acf07d3418a2e7ba529c9c33caf09d3c1f25513023c1db56/propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", size = 44780, upload-time = "2025-10-08T19:47:08.851Z" },
|
{ url = "https://files.pythonhosted.org/packages/8b/e8/677a0025e8a2acf07d3418a2e7ba529c9c33caf09d3c1f25513023c1db56/propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", size = 44780, upload-time = "2025-10-08T19:47:08.851Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/89/a4/92380f7ca60f99ebae761936bc48a72a639e8a47b29050615eef757cb2a7/propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", size = 46308, upload-time = "2025-10-08T19:47:09.982Z" },
|
{ url = "https://files.pythonhosted.org/packages/89/a4/92380f7ca60f99ebae761936bc48a72a639e8a47b29050615eef757cb2a7/propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", size = 46308, upload-time = "2025-10-08T19:47:09.982Z" },
|
||||||
|
|
@ -1204,6 +1145,28 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" },
|
{ url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "psutil"
|
||||||
|
version = "7.2.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595, upload-time = "2026-01-28T18:14:57.293Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082, upload-time = "2026-01-28T18:14:59.732Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476, upload-time = "2026-01-28T18:15:01.884Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062, upload-time = "2026-01-28T18:15:04.436Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893, upload-time = "2026-01-28T18:15:06.378Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589, upload-time = "2026-01-28T18:15:08.03Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ptyprocess"
|
name = "ptyprocess"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
|
@ -1213,19 +1176,70 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" },
|
{ url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "py-cid"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "morphys" },
|
||||||
|
{ name = "py-multibase" },
|
||||||
|
{ name = "py-multicodec" },
|
||||||
|
{ name = "py-multihash" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/96/8e/68c2bd0346247570e8e01e8c170a0237884e95cdfa43989527b71adaa978/py_cid-0.5.0.tar.gz", hash = "sha256:93c62586c672353a9862f3fce13c9848ea39a00378e0980e2f0eed91631f3d28", size = 38028, upload-time = "2026-02-13T19:03:28.603Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2b/18/eaea1571ae8b4fa490793a4b78a9641c4579a884f7a26f3d1b019d7e91c2/py_cid-0.5.0-py3-none-any.whl", hash = "sha256:2fbad437384534e2a0ab0c4068aac3e510c4cb710c89c8f6bf98f4b07ed54e3e", size = 16046, upload-time = "2026-02-13T19:03:27.516Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "py-multibase"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "morphys" },
|
||||||
|
{ name = "python-baseconv" },
|
||||||
|
{ name = "six" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/bc/52/5ed393ab49df7e3b03995d3c4e53bae1e8c2ca40909cf25a41b346c09a38/py_multibase-2.0.0.tar.gz", hash = "sha256:58c1a264195fa1ae29ea707c6fc8196446f4bdb92e0f9a0f131e0f280b238839", size = 26857, upload-time = "2025-12-18T02:24:49.132Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/36/c7/38035079d9978b32b962f996f1cccaa166ecfe38723ab4349ab32166c037/py_multibase-2.0.0-py3-none-any.whl", hash = "sha256:b29ce489b556134e73998a11712c406b70950812955df64084754e0774e40900", size = 10608, upload-time = "2025-12-18T02:24:47.827Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "py-multicodec"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "varint" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/5e/26/ef24db0fbfec080b72c5ac4a1000da3a4d696a1e31862c695d683097a1b5/py_multicodec-1.0.0.tar.gz", hash = "sha256:78e4e3e47b6288cf635c3ca987152e6cb5510bdcdab307e7690c76ec3d5bbfeb", size = 44668, upload-time = "2025-12-18T20:41:37.976Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/76/da/768d07490faeae88ac361184164be9c262fececc3c6241b5fc471be4f659/py_multicodec-1.0.0-py3-none-any.whl", hash = "sha256:ae2e687bac8fdf54e3f5b3feded36b61a304d5e3c3af9438f7481f543ec15b8d", size = 26200, upload-time = "2025-12-18T20:41:37.055Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "py-multihash"
|
||||||
|
version = "3.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "base58" },
|
||||||
|
{ name = "blake3" },
|
||||||
|
{ name = "mmh3" },
|
||||||
|
{ name = "morphys" },
|
||||||
|
{ name = "six" },
|
||||||
|
{ name = "varint" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/11/3d/ed68b0eccd0654f7f3c163d9b3d428f903e5e3e884ab1f0d0a16ba6a4f11/py_multihash-3.0.0.tar.gz", hash = "sha256:2e848941de5ef0533ca26b81940e2ffcf7b4322a3f803e8c97f4f0eca8767aa7", size = 41630, upload-time = "2025-12-17T19:30:00.596Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/24/e2/d65606db8369916fb5a9b4fe14df7e6072970d919300f3fb1c989a1d8e7d/py_multihash-3.0.0-py3-none-any.whl", hash = "sha256:3863ec1313b4eac1e5169137c143d40bf77456e57388f839441deba089f87326", size = 21215, upload-time = "2025-12-17T19:29:59.322Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyarrow"
|
name = "pyarrow"
|
||||||
version = "22.0.0"
|
version = "22.0.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/30/53/04a7fdc63e6056116c9ddc8b43bc28c12cdd181b85cbeadb79278475f3ae/pyarrow-22.0.0.tar.gz", hash = "sha256:3d600dc583260d845c7d8a6db540339dd883081925da2bd1c5cb808f720b3cd9", size = 1151151, upload-time = "2025-10-24T12:30:00.762Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/30/53/04a7fdc63e6056116c9ddc8b43bc28c12cdd181b85cbeadb79278475f3ae/pyarrow-22.0.0.tar.gz", hash = "sha256:3d600dc583260d845c7d8a6db540339dd883081925da2bd1c5cb808f720b3cd9", size = 1151151, upload-time = "2025-10-24T12:30:00.762Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/af/63/ba23862d69652f85b615ca14ad14f3bcfc5bf1b99ef3f0cd04ff93fdad5a/pyarrow-22.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:bea79263d55c24a32b0d79c00a1c58bb2ee5f0757ed95656b01c0fb310c5af3d", size = 34211578, upload-time = "2025-10-24T10:05:21.583Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b1/d0/f9ad86fe809efd2bcc8be32032fa72e8b0d112b01ae56a053006376c5930/pyarrow-22.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:12fe549c9b10ac98c91cf791d2945e878875d95508e1a5d14091a7aaa66d9cf8", size = 35989906, upload-time = "2025-10-24T10:05:29.485Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b4/a8/f910afcb14630e64d673f15904ec27dd31f1e009b77033c365c84e8c1e1d/pyarrow-22.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:334f900ff08ce0423407af97e6c26ad5d4e3b0763645559ece6fbf3747d6a8f5", size = 45021677, upload-time = "2025-10-24T10:05:38.274Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/13/95/aec81f781c75cd10554dc17a25849c720d54feafb6f7847690478dcf5ef8/pyarrow-22.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:c6c791b09c57ed76a18b03f2631753a4960eefbbca80f846da8baefc6491fcfe", size = 47726315, upload-time = "2025-10-24T10:05:47.314Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/bb/d4/74ac9f7a54cfde12ee42734ea25d5a3c9a45db78f9def949307a92720d37/pyarrow-22.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c3200cb41cdbc65156e5f8c908d739b0dfed57e890329413da2748d1a2cd1a4e", size = 47990906, upload-time = "2025-10-24T10:05:58.254Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/2e/71/fedf2499bf7a95062eafc989ace56572f3343432570e1c54e6599d5b88da/pyarrow-22.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ac93252226cf288753d8b46280f4edf3433bf9508b6977f8dd8526b521a1bbb9", size = 50306783, upload-time = "2025-10-24T10:06:08.08Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/68/ed/b202abd5a5b78f519722f3d29063dda03c114711093c1995a33b8e2e0f4b/pyarrow-22.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:44729980b6c50a5f2bfcc2668d36c569ce17f8b17bccaf470c4313dcbbf13c9d", size = 27972883, upload-time = "2025-10-24T10:06:14.204Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a6/d6/d0fac16a2963002fc22c8fa75180a838737203d558f0ed3b564c4a54eef5/pyarrow-22.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e6e95176209257803a8b3d0394f21604e796dadb643d2f7ca21b66c9c0b30c9a", size = 34204629, upload-time = "2025-10-24T10:06:20.274Z" },
|
{ url = "https://files.pythonhosted.org/packages/a6/d6/d0fac16a2963002fc22c8fa75180a838737203d558f0ed3b564c4a54eef5/pyarrow-22.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e6e95176209257803a8b3d0394f21604e796dadb643d2f7ca21b66c9c0b30c9a", size = 34204629, upload-time = "2025-10-24T10:06:20.274Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c6/9c/1d6357347fbae062ad3f17082f9ebc29cc733321e892c0d2085f42a2212b/pyarrow-22.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:001ea83a58024818826a9e3f89bf9310a114f7e26dfe404a4c32686f97bd7901", size = 35985783, upload-time = "2025-10-24T10:06:27.301Z" },
|
{ url = "https://files.pythonhosted.org/packages/c6/9c/1d6357347fbae062ad3f17082f9ebc29cc733321e892c0d2085f42a2212b/pyarrow-22.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:001ea83a58024818826a9e3f89bf9310a114f7e26dfe404a4c32686f97bd7901", size = 35985783, upload-time = "2025-10-24T10:06:27.301Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ff/c0/782344c2ce58afbea010150df07e3a2f5fdad299cd631697ae7bd3bac6e3/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:ce20fe000754f477c8a9125543f1936ea5b8867c5406757c224d745ed033e691", size = 45020999, upload-time = "2025-10-24T10:06:35.387Z" },
|
{ url = "https://files.pythonhosted.org/packages/ff/c0/782344c2ce58afbea010150df07e3a2f5fdad299cd631697ae7bd3bac6e3/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:ce20fe000754f477c8a9125543f1936ea5b8867c5406757c224d745ed033e691", size = 45020999, upload-time = "2025-10-24T10:06:35.387Z" },
|
||||||
|
|
@ -1251,19 +1265,6 @@ dependencies = [
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/8d/ad/9d1e96486d2eb5a2672c4d9a2dd372d015b8d7a332c6ac2722c4c8e6bbbf/pycares-4.11.0.tar.gz", hash = "sha256:c863d9003ca0ce7df26429007859afd2a621d3276ed9fef154a9123db9252557", size = 654473, upload-time = "2025-09-09T15:18:21.849Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/8d/ad/9d1e96486d2eb5a2672c4d9a2dd372d015b8d7a332c6ac2722c4c8e6bbbf/pycares-4.11.0.tar.gz", hash = "sha256:c863d9003ca0ce7df26429007859afd2a621d3276ed9fef154a9123db9252557", size = 654473, upload-time = "2025-09-09T15:18:21.849Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/e2/4e/4821b66feefaaa8ec03494c1a11614c430983572e54ff062b4589441e199/pycares-4.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b93d624560ba52287873bacff70b42c99943821ecbc810b959b0953560f53c36", size = 145906, upload-time = "2025-09-09T15:16:53.204Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e8/81/93a505dcbb7533254b0ce1da519591dcda889d6a66dcdfa5737e3280e18a/pycares-4.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:775d99966e28c8abd9910ddef2de0f1e173afc5a11cea9f184613c747373ab80", size = 141972, upload-time = "2025-09-09T15:16:54.43Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/7d/d6/76994c8b21316e48ea6c3ce3298574c28f90c9c41428a3349a57104621c9/pycares-4.11.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:84fde689557361764f052850a2d68916050adbfd9321f6105aca1d8f1a9bd49b", size = 637832, upload-time = "2025-09-09T15:16:55.523Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/bb/a4/5ca7e316d0edb714d78974cb34f4883f63fe9f580644c2db99fb62b05f56/pycares-4.11.0-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:30ceed06f3bf5eff865a34d21562c25a7f3dad0ed336b9dd415330e03a6c50c4", size = 687751, upload-time = "2025-09-09T15:16:57.55Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/cb/8d/c5c578fdd335d7b1dcaea88fae3497390095b5b05a1ba34a29f62d037abb/pycares-4.11.0-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:97d971b3a88a803bb95ff8a40ea4d68da59319eb8b59e924e318e2560af8c16d", size = 678362, upload-time = "2025-09-09T15:16:58.859Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b9/96/9be4d838a9348dd2e72a90c34d186b918b66d499af5be79afa18a6ba2808/pycares-4.11.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:2d5cac829da91ade70ce1af97dad448c6cd4778b48facbce1b015e16ced93642", size = 641069, upload-time = "2025-09-09T15:17:00.046Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/39/d6/8ea9b5dcef6b566cde034aa2b68743f7b0a19fa0fba9ea01a4f98b8a57fb/pycares-4.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee1ea367835eb441d246164c09d1f9703197af4425fc6865cefcde9e2ca81f85", size = 622357, upload-time = "2025-09-09T15:17:01.205Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/07/f8/3401e89b5d2970e30e02f9beb29ad59e2a8f19ef2c68c978de2b764cacb0/pycares-4.11.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3139ec1f4450a4b253386035c5ecd2722582ae3320a456df5021ffe3f174260a", size = 670290, upload-time = "2025-09-09T15:17:02.413Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a2/c4/ff6a166e1d1d1987339548a19d0b1d52ec3ead8b3a8a2247a0d96e56013c/pycares-4.11.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5d70324ca1d82c6c4b00aa678347f7560d1ef2ce1d181978903459a97751543a", size = 652958, upload-time = "2025-09-09T15:17:04.203Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b8/7c/fc084b395921c9b862d31a83f809fe649c24314b51b527ad0ab0df33edd4/pycares-4.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e2f8d9cfe0eb3a2997fde5df99b1aaea5a46dabfcfcac97b2d05f027c2cd5e28", size = 629239, upload-time = "2025-09-09T15:17:05.477Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b0/7f/2f26062bea95ab657f979217d50df563dc9fd9cc4c5dd21a6e7323e9efe7/pycares-4.11.0-cp312-cp312-win32.whl", hash = "sha256:1571a7055c03a95d5270c914034eac7f8bfa1b432fc1de53d871b821752191a4", size = 118918, upload-time = "2025-09-09T15:17:06.882Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a5/86/277473d20f3df4e00fa7e0ebb21955b2830b15247462aaf8f3fc8c4950be/pycares-4.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:7570e0b50db619b2ee370461c462617225dc3a3f63f975c6f117e2f0c94f82ca", size = 144560, upload-time = "2025-09-09T15:17:07.891Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/f0/f9/d65ad17ec921d8b7eb42161dec2024ee2f5c9f1c44cabf0dd1b7f4fac6c5/pycares-4.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:f199702740f3b766ed8c70efb885538be76cb48cd0cb596b948626f0b825e07a", size = 115695, upload-time = "2025-09-09T15:17:09.333Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/dc/a9/62fea7ad72ac1fed2ac9dd8e9a7379b7eb0288bf2b3ea5731642c3a6f7de/pycares-4.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c296ab94d1974f8d2f76c499755a9ce31ffd4986e8898ef19b90e32525f7d84", size = 145909, upload-time = "2025-09-09T15:17:10.491Z" },
|
{ url = "https://files.pythonhosted.org/packages/dc/a9/62fea7ad72ac1fed2ac9dd8e9a7379b7eb0288bf2b3ea5731642c3a6f7de/pycares-4.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c296ab94d1974f8d2f76c499755a9ce31ffd4986e8898ef19b90e32525f7d84", size = 145909, upload-time = "2025-09-09T15:17:10.491Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f4/ac/0317d6d0d3bd7599c53b8f1db09ad04260647d2f6842018e322584791fd5/pycares-4.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e0fcd3a8bac57a0987d9b09953ba0f8703eb9dca7c77f7051d8c2ed001185be8", size = 141974, upload-time = "2025-09-09T15:17:11.634Z" },
|
{ url = "https://files.pythonhosted.org/packages/f4/ac/0317d6d0d3bd7599c53b8f1db09ad04260647d2f6842018e322584791fd5/pycares-4.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e0fcd3a8bac57a0987d9b09953ba0f8703eb9dca7c77f7051d8c2ed001185be8", size = 141974, upload-time = "2025-09-09T15:17:11.634Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/63/11/731b565ae1e81c43dac247a248ee204628186f6df97c9927bd06c62237f8/pycares-4.11.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:bac55842047567ddae177fb8189b89a60633ac956d5d37260f7f71b517fd8b87", size = 637796, upload-time = "2025-09-09T15:17:12.815Z" },
|
{ url = "https://files.pythonhosted.org/packages/63/11/731b565ae1e81c43dac247a248ee204628186f6df97c9927bd06c62237f8/pycares-4.11.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:bac55842047567ddae177fb8189b89a60633ac956d5d37260f7f71b517fd8b87", size = 637796, upload-time = "2025-09-09T15:17:12.815Z" },
|
||||||
|
|
@ -1351,11 +1352,6 @@ version = "13.10.3"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/0d/e9/d1b97154cec1d6c8a3d93fb6565d1463bc528fa5103491d626d07a451c7c/pyqt6_sip-13.10.3.tar.gz", hash = "sha256:630895b3827e2c3b4e072089157985691fe4210d64340e71141f93775ea4ae51", size = 92621, upload-time = "2025-12-06T13:19:44.569Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/0d/e9/d1b97154cec1d6c8a3d93fb6565d1463bc528fa5103491d626d07a451c7c/pyqt6_sip-13.10.3.tar.gz", hash = "sha256:630895b3827e2c3b4e072089157985691fe4210d64340e71141f93775ea4ae51", size = 92621, upload-time = "2025-12-06T13:19:44.569Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/61/46/c44d1956a2a6bae272883b276125964736adc0e0a87f95a4af0f7876ba08/pyqt6_sip-13.10.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:61e4e935f1d80dd107b0a97fbcbbf27e07046666f72663fa4b0d700514e8201c", size = 112365, upload-time = "2025-12-06T13:19:27.79Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/11/fd/04adac969ba70bb042d52e13c99c968fce0e1fa6a52146f03a974168a848/pyqt6_sip-13.10.3-cp312-cp312-manylinux1_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3f3e2a79738319b795f0d1b2a555b1ea669b1a306b604bac876c84833cabb008", size = 301147, upload-time = "2025-12-06T13:19:30.279Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/74/83/7ba660ddd7070090bcd387140865474affd901861ba8f6dfcb18504f7f26/pyqt6_sip-13.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:748758dfd7f77aeb1c5becfc934a722ce10de51bfdf9902f9cad19c27ba146e7", size = 323336, upload-time = "2025-12-06T13:19:28.961Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/cc/0b/6c77989542751c5ec3d829ff6f65b13c646606560c72b96aeb4dfae843b0/pyqt6_sip-13.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:7361b7005a375cd647f2d1e3ca7000967406831bef466003e6ead2af27d84a2b", size = 53459, upload-time = "2025-12-06T13:19:31.353Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9b/73/74df7a24c75719ee36e94d97e147c3c260c1a6268e48d692f561f9d5b9dc/pyqt6_sip-13.10.3-cp312-cp312-win_arm64.whl", hash = "sha256:dd21e6f70f7cfe81e1d9b96800652ffeb5947b41354c4fd58a5e3d3f02499a7a", size = 48647, upload-time = "2025-12-06T13:19:32.271Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/0c/a9/25a07fb16308e9405ac01369013943ae58bef72c8700d8a6100182b8d937/pyqt6_sip-13.10.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a8b5532398c0e6d0064d4dce4c096ff20bf710507dafefb036eff61c3f59cda8", size = 112348, upload-time = "2025-12-06T13:19:33.323Z" },
|
{ url = "https://files.pythonhosted.org/packages/0c/a9/25a07fb16308e9405ac01369013943ae58bef72c8700d8a6100182b8d937/pyqt6_sip-13.10.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a8b5532398c0e6d0064d4dce4c096ff20bf710507dafefb036eff61c3f59cda8", size = 112348, upload-time = "2025-12-06T13:19:33.323Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/4a/f1/38b625b0638681659bc3c7eaa548b65862a305d26b48835b67cdd6add720/pyqt6_sip-13.10.3-cp313-cp313-manylinux1_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d02c138c6eacb13ef668bfe6becfb6ab40bb40135f34a36ef31b7dc860976493", size = 301470, upload-time = "2025-12-06T13:19:35.824Z" },
|
{ url = "https://files.pythonhosted.org/packages/4a/f1/38b625b0638681659bc3c7eaa548b65862a305d26b48835b67cdd6add720/pyqt6_sip-13.10.3-cp313-cp313-manylinux1_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d02c138c6eacb13ef668bfe6becfb6ab40bb40135f34a36ef31b7dc860976493", size = 301470, upload-time = "2025-12-06T13:19:35.824Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/cd/8d/a2eaccc88cc53e6370e3728593ea80d10a132f87078ce7cbcfc8c33d9b3f/pyqt6_sip-13.10.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e234a3af9539f71bb566e7136317b92f189a89553970284d833cd63cca4dafdd", size = 323466, upload-time = "2025-12-06T13:19:34.445Z" },
|
{ url = "https://files.pythonhosted.org/packages/cd/8d/a2eaccc88cc53e6370e3728593ea80d10a132f87078ce7cbcfc8c33d9b3f/pyqt6_sip-13.10.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e234a3af9539f71bb566e7136317b92f189a89553970284d833cd63cca4dafdd", size = 323466, upload-time = "2025-12-06T13:19:34.445Z" },
|
||||||
|
|
@ -1396,6 +1392,12 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" },
|
{ url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python-baseconv"
|
||||||
|
version = "1.2.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/33/d0/9297d7d8dd74767b4d5560d834b30b2fff17d39987c23ed8656f476e0d9b/python-baseconv-1.2.2.tar.gz", hash = "sha256:0539f8bd0464013b05ad62e0a1673f0ac9086c76b43ebf9f833053527cd9931b", size = 4929, upload-time = "2019-04-04T19:28:57.17Z" }
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "python-dateutil"
|
name = "python-dateutil"
|
||||||
version = "2.9.0.post0"
|
version = "2.9.0.post0"
|
||||||
|
|
@ -1436,16 +1438,6 @@ version = "6.0.3"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" },
|
{ url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" },
|
{ url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" },
|
{ url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" },
|
||||||
|
|
@ -1488,17 +1480,6 @@ version = "3.14.3"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/d3/28/9d808fe62375b9aab5ba92fa9b29371297b067c2790b2d7cda648b1e2f8d/rapidfuzz-3.14.3.tar.gz", hash = "sha256:2491937177868bc4b1e469087601d53f925e8d270ccc21e07404b4b5814b7b5f", size = 57863900, upload-time = "2025-11-01T11:54:52.321Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/d3/28/9d808fe62375b9aab5ba92fa9b29371297b067c2790b2d7cda648b1e2f8d/rapidfuzz-3.14.3.tar.gz", hash = "sha256:2491937177868bc4b1e469087601d53f925e8d270ccc21e07404b4b5814b7b5f", size = 57863900, upload-time = "2025-11-01T11:54:52.321Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/fa/8e/3c215e860b458cfbedb3ed73bc72e98eb7e0ed72f6b48099604a7a3260c2/rapidfuzz-3.14.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:685c93ea961d135893b5984a5a9851637d23767feabe414ec974f43babbd8226", size = 1945306, upload-time = "2025-11-01T11:53:06.452Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/36/d9/31b33512015c899f4a6e6af64df8dfe8acddf4c8b40a4b3e0e6e1bcd00e5/rapidfuzz-3.14.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fa7c8f26f009f8c673fbfb443792f0cf8cf50c4e18121ff1e285b5e08a94fbdb", size = 1390788, upload-time = "2025-11-01T11:53:08.721Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a9/67/2ee6f8de6e2081ccd560a571d9c9063184fe467f484a17fa90311a7f4a2e/rapidfuzz-3.14.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57f878330c8d361b2ce76cebb8e3e1dc827293b6abf404e67d53260d27b5d941", size = 1374580, upload-time = "2025-11-01T11:53:10.164Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/30/83/80d22997acd928eda7deadc19ccd15883904622396d6571e935993e0453a/rapidfuzz-3.14.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c5f545f454871e6af05753a0172849c82feaf0f521c5ca62ba09e1b382d6382", size = 3154947, upload-time = "2025-11-01T11:53:12.093Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/5b/cf/9f49831085a16384695f9fb096b99662f589e30b89b4a589a1ebc1a19d34/rapidfuzz-3.14.3-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:07aa0b5d8863e3151e05026a28e0d924accf0a7a3b605da978f0359bb804df43", size = 1223872, upload-time = "2025-11-01T11:53:13.664Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c8/0f/41ee8034e744b871c2e071ef0d360686f5ccfe5659f4fd96c3ec406b3c8b/rapidfuzz-3.14.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73b07566bc7e010e7b5bd490fb04bb312e820970180df6b5655e9e6224c137db", size = 2392512, upload-time = "2025-11-01T11:53:15.109Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/da/86/280038b6b0c2ccec54fb957c732ad6b41cc1fd03b288d76545b9cf98343f/rapidfuzz-3.14.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6de00eb84c71476af7d3110cf25d8fe7c792d7f5fa86764ef0b4ca97e78ca3ed", size = 2521398, upload-time = "2025-11-01T11:53:17.146Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fa/7b/05c26f939607dca0006505e3216248ae2de631e39ef94dd63dbbf0860021/rapidfuzz-3.14.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d7843a1abf0091773a530636fdd2a49a41bcae22f9910b86b4f903e76ddc82dc", size = 4259416, upload-time = "2025-11-01T11:53:19.34Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/40/eb/9e3af4103d91788f81111af1b54a28de347cdbed8eaa6c91d5e98a889aab/rapidfuzz-3.14.3-cp312-cp312-win32.whl", hash = "sha256:dea97ac3ca18cd3ba8f3d04b5c1fe4aa60e58e8d9b7793d3bd595fdb04128d7a", size = 1709527, upload-time = "2025-11-01T11:53:20.949Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b8/63/d06ecce90e2cf1747e29aeab9f823d21e5877a4c51b79720b2d3be7848f8/rapidfuzz-3.14.3-cp312-cp312-win_amd64.whl", hash = "sha256:b5100fd6bcee4d27f28f4e0a1c6b5127bc8ba7c2a9959cad9eab0bf4a7ab3329", size = 1538989, upload-time = "2025-11-01T11:53:22.428Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fc/6d/beee32dcda64af8128aab3ace2ccb33d797ed58c434c6419eea015fec779/rapidfuzz-3.14.3-cp312-cp312-win_arm64.whl", hash = "sha256:4e49c9e992bc5fc873bd0fff7ef16a4405130ec42f2ce3d2b735ba5d3d4eb70f", size = 811161, upload-time = "2025-11-01T11:53:23.811Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e4/4f/0d94d09646853bd26978cb3a7541b6233c5760687777fa97da8de0d9a6ac/rapidfuzz-3.14.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dbcb726064b12f356bf10fffdb6db4b6dce5390b23627c08652b3f6e49aa56ae", size = 1939646, upload-time = "2025-11-01T11:53:25.292Z" },
|
{ url = "https://files.pythonhosted.org/packages/e4/4f/0d94d09646853bd26978cb3a7541b6233c5760687777fa97da8de0d9a6ac/rapidfuzz-3.14.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dbcb726064b12f356bf10fffdb6db4b6dce5390b23627c08652b3f6e49aa56ae", size = 1939646, upload-time = "2025-11-01T11:53:25.292Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b6/eb/f96aefc00f3bbdbab9c0657363ea8437a207d7545ac1c3789673e05d80bd/rapidfuzz-3.14.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1704fc70d214294e554a2421b473779bcdeef715881c5e927dc0f11e1692a0ff", size = 1385512, upload-time = "2025-11-01T11:53:27.594Z" },
|
{ url = "https://files.pythonhosted.org/packages/b6/eb/f96aefc00f3bbdbab9c0657363ea8437a207d7545ac1c3789673e05d80bd/rapidfuzz-3.14.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1704fc70d214294e554a2421b473779bcdeef715881c5e927dc0f11e1692a0ff", size = 1385512, upload-time = "2025-11-01T11:53:27.594Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/26/34/71c4f7749c12ee223dba90017a5947e8f03731a7cc9f489b662a8e9e643d/rapidfuzz-3.14.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc65e72790ddfd310c2c8912b45106e3800fefe160b0c2ef4d6b6fec4e826457", size = 1373571, upload-time = "2025-11-01T11:53:29.096Z" },
|
{ url = "https://files.pythonhosted.org/packages/26/34/71c4f7749c12ee223dba90017a5947e8f03731a7cc9f489b662a8e9e643d/rapidfuzz-3.14.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc65e72790ddfd310c2c8912b45106e3800fefe160b0c2ef4d6b6fec4e826457", size = 1373571, upload-time = "2025-11-01T11:53:29.096Z" },
|
||||||
|
|
@ -1577,6 +1558,26 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/74/31/b0e29d572670dca3674eeee78e418f20bdf97fa8aa9ea71380885e175ca0/ruff-0.14.10-py3-none-win_arm64.whl", hash = "sha256:e51d046cf6dda98a4633b8a8a771451107413b0f07183b2bef03f075599e44e6", size = 13729839, upload-time = "2025-12-18T19:28:48.636Z" },
|
{ url = "https://files.pythonhosted.org/packages/74/31/b0e29d572670dca3674eeee78e418f20bdf97fa8aa9ea71380885e175ca0/ruff-0.14.10-py3-none-win_arm64.whl", hash = "sha256:e51d046cf6dda98a4633b8a8a771451107413b0f07183b2bef03f075599e44e6", size = 13729839, upload-time = "2025-12-18T19:28:48.636Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "setproctitle"
|
||||||
|
version = "1.3.8"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/49/b0/6b8a516c5a9e9630bd5293db78314ac012f690305fe93beadea388626efb/setproctitle-1.3.8.tar.gz", hash = "sha256:cafe209d064a6efb88cb45a03e97981ff8832802b2b5d009dde0197a3b7b41c8", size = 27214, upload-time = "2026-10-01T21:09:27.121Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/58/46/125791eb19c85340c6d43de8c821b143aecbfa0882343f244f5744474229/setproctitle-1.3.8-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a4a782f9ab26e662a890c1a7d865c452c83ed554de44aa83da35fa5bdcc79921", size = 18100, upload-time = "2026-10-01T20:59:33.41Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/47/51/73b1e62c3e019e683e58d31f9f8af57e6750f36ce079004d29b7790e22ce/setproctitle-1.3.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d63adfa4be8f9dbac4be6b359e2a8eb15a733545ef613d02a12ae27a4d40e975", size = 13116, upload-time = "2026-10-01T20:59:35.159Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/ae/095c6ad159e3a7b95bc6d9a3eae18abfea1ebc79ed3377617406a1668150/setproctitle-1.3.8-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d4289e209e805d7d276a534f062092974fbe6814889d4c132c247205ebb49a65", size = 33275, upload-time = "2026-10-01T20:59:37.235Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f7/6e/5196258efd941cb874b3f4da91460601b867fdc434eba48a70455736d4be/setproctitle-1.3.8-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8bb543b4b58ad839f7f0d335a7f4b40cef6989952e7239de3532de0b7771607e", size = 34124, upload-time = "2026-10-01T20:59:39.529Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/36/01/e9754e0916e6dda232a8c337bda69d2fea33acee0c5d3bdf580b8155a50d/setproctitle-1.3.8-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b705f01a531dba8fbbab90e30d432af4cc70a79c0a33b238e2c061816140cad0", size = 36006, upload-time = "2026-10-01T20:59:41.501Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ee/a9/c63d2d745f18423937429a8611743e7b3e17259173150fbcdaa59daa4a51/setproctitle-1.3.8-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8e286e4c4e90063072a6e088a8d6526a7ffceb47429db88ba50ba58eeebcc758", size = 32268, upload-time = "2026-10-01T20:59:43.795Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/36/0c/a72818902f32ea9b848db5ccc828eb9cd9bc8661975610e1d46ea4aacbe2/setproctitle-1.3.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7b77c8671974288cf192e481ed63e928f1086762e97e8845d09d65ba121f8aaa", size = 33179, upload-time = "2026-10-01T20:59:45.809Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bb/55/fa59463ae6b957048e0e842d4b5513eced1b71554d8af0f5d91cd23cde23/setproctitle-1.3.8-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0e85b55eac9abfa3166ab00dac21e718ac2624a1df7d0b75559a2d3e3781cb33", size = 34472, upload-time = "2026-10-01T20:59:47.858Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b7/77/1f0cf55055788bf7eb9a146040a64d7ec42cd56153894856effc70e943ec/setproctitle-1.3.8-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f215ec9237d5f8e96d0205be6e2141292c20b133343c2153b6d4934f523ef422", size = 31428, upload-time = "2026-10-01T20:59:49.753Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/32/98/d1d8a6cd620d72a04f5d3335125e5b2fc5667bd06a76bb5bbc50b101e804/setproctitle-1.3.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b0e70a5d294e4c8cf7dc94e015fca6d4913779a424937e66b429fba82d8eb5e2", size = 32776, upload-time = "2026-10-01T20:59:51.763Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4b/34/8b9eea1e80ac7a7f622eead8a0e4d73a60098344ed6f373e111f7ce8d29d/setproctitle-1.3.8-cp313-cp313-win32.whl", hash = "sha256:f85b4d87273e0ec63568433bbb8ccf160b548c49b53576fe010bad9f698b8586", size = 12105, upload-time = "2026-10-01T20:59:53.444Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bf/f0/98883c658859d331faf91eccac8946cb2f8feb2590905015b129fdeb09cd/setproctitle-1.3.8-cp313-cp313-win_amd64.whl", hash = "sha256:bcdf74fe8a6e3b31bed1bc7d3e2a38cfbda3263d2750492ea0725dbc2db5aacf", size = 12933, upload-time = "2026-10-01T20:59:55.045Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shellingham"
|
name = "shellingham"
|
||||||
version = "1.5.4"
|
version = "1.5.4"
|
||||||
|
|
@ -1631,14 +1632,6 @@ version = "2.3.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/52/ed/3f73f72945444548f33eba9a87fc7a6e969915e7b1acc8260b30e1f76a2f/tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549", size = 17392, upload-time = "2025-10-08T22:01:47.119Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/52/ed/3f73f72945444548f33eba9a87fc7a6e969915e7b1acc8260b30e1f76a2f/tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549", size = 17392, upload-time = "2025-10-08T22:01:47.119Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/ff/b7/40f36368fcabc518bb11c8f06379a0fd631985046c038aca08c6d6a43c6e/tomli-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac", size = 154891, upload-time = "2025-10-08T22:01:09.082Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/f9/3f/d9dd692199e3b3aab2e4e4dd948abd0f790d9ded8cd10cbaae276a898434/tomli-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22", size = 148796, upload-time = "2025-10-08T22:01:10.266Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/60/83/59bff4996c2cf9f9387a0f5a3394629c7efa5ef16142076a23a90f1955fa/tomli-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f", size = 242121, upload-time = "2025-10-08T22:01:11.332Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/45/e5/7c5119ff39de8693d6baab6c0b6dcb556d192c165596e9fc231ea1052041/tomli-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52", size = 250070, upload-time = "2025-10-08T22:01:12.498Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/45/12/ad5126d3a278f27e6701abde51d342aa78d06e27ce2bb596a01f7709a5a2/tomli-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8", size = 245859, upload-time = "2025-10-08T22:01:13.551Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fb/a1/4d6865da6a71c603cfe6ad0e6556c73c76548557a8d658f9e3b142df245f/tomli-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6", size = 250296, upload-time = "2025-10-08T22:01:14.614Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a0/b7/a7a7042715d55c9ba6e8b196d65d2cb662578b4d8cd17d882d45322b0d78/tomli-2.3.0-cp312-cp312-win32.whl", hash = "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876", size = 97124, upload-time = "2025-10-08T22:01:15.629Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/06/1e/f22f100db15a68b520664eb3328fb0ae4e90530887928558112c8d1f4515/tomli-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878", size = 107698, upload-time = "2025-10-08T22:01:16.51Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/89/48/06ee6eabe4fdd9ecd48bf488f4ac783844fd777f547b8d1b61c11939974e/tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b", size = 154819, upload-time = "2025-10-08T22:01:17.964Z" },
|
{ url = "https://files.pythonhosted.org/packages/89/48/06ee6eabe4fdd9ecd48bf488f4ac783844fd777f547b8d1b61c11939974e/tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b", size = 154819, upload-time = "2025-10-08T22:01:17.964Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f1/01/88793757d54d8937015c75dcdfb673c65471945f6be98e6a0410fba167ed/tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae", size = 148766, upload-time = "2025-10-08T22:01:18.959Z" },
|
{ url = "https://files.pythonhosted.org/packages/f1/01/88793757d54d8937015c75dcdfb673c65471945f6be98e6a0410fba167ed/tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae", size = 148766, upload-time = "2025-10-08T22:01:18.959Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/42/17/5e2c956f0144b812e7e107f94f1cc54af734eb17b5191c0bbfb72de5e93e/tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b", size = 240771, upload-time = "2025-10-08T22:01:20.106Z" },
|
{ url = "https://files.pythonhosted.org/packages/42/17/5e2c956f0144b812e7e107f94f1cc54af734eb17b5191c0bbfb72de5e93e/tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b", size = 240771, upload-time = "2025-10-08T22:01:20.106Z" },
|
||||||
|
|
@ -1676,14 +1669,16 @@ wheels = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tractor"
|
name = "tractor"
|
||||||
version = "0.1.0a6.dev0"
|
version = "0.1.0a6.dev0"
|
||||||
source = { git = "https://github.com/goodboy/tractor.git?branch=main#e77198bb64f0467a50e251ed140daee439752354" }
|
source = { git = "https://github.com/goodboy/tractor.git?branch=wkt%2Faddr_unpacking#a966928dead4cbf369ad244834ce9dbe988ac8ca" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "bidict" },
|
{ name = "bidict" },
|
||||||
{ name = "cffi" },
|
|
||||||
{ name = "colorlog" },
|
{ name = "colorlog" },
|
||||||
{ name = "msgspec" },
|
{ name = "msgspec" },
|
||||||
|
{ name = "multiaddr" },
|
||||||
{ name = "pdbp" },
|
{ name = "pdbp" },
|
||||||
{ name = "platformdirs" },
|
{ name = "platformdirs" },
|
||||||
|
{ name = "py-multibase" },
|
||||||
|
{ name = "setproctitle" },
|
||||||
{ name = "tricycle" },
|
{ name = "tricycle" },
|
||||||
{ name = "trio" },
|
{ name = "trio" },
|
||||||
{ name = "wrapt" },
|
{ name = "wrapt" },
|
||||||
|
|
@ -1810,12 +1805,6 @@ version = "0.22.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/06/f0/18d39dbd1971d6d62c4629cc7fa67f74821b0dc1f5a77af43719de7936a7/uvloop-0.22.1.tar.gz", hash = "sha256:6c84bae345b9147082b17371e3dd5d42775bddce91f885499017f4607fdaf39f", size = 2443250, upload-time = "2025-10-16T22:17:19.342Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/06/f0/18d39dbd1971d6d62c4629cc7fa67f74821b0dc1f5a77af43719de7936a7/uvloop-0.22.1.tar.gz", hash = "sha256:6c84bae345b9147082b17371e3dd5d42775bddce91f885499017f4607fdaf39f", size = 2443250, upload-time = "2025-10-16T22:17:19.342Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/3d/ff/7f72e8170be527b4977b033239a83a68d5c881cc4775fca255c677f7ac5d/uvloop-0.22.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fe94b4564e865d968414598eea1a6de60adba0c040ba4ed05ac1300de402cd42", size = 1359936, upload-time = "2025-10-16T22:16:29.436Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c3/c6/e5d433f88fd54d81ef4be58b2b7b0cea13c442454a1db703a1eea0db1a59/uvloop-0.22.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:51eb9bd88391483410daad430813d982010f9c9c89512321f5b60e2cddbdddd6", size = 752769, upload-time = "2025-10-16T22:16:30.493Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/24/68/a6ac446820273e71aa762fa21cdcc09861edd3536ff47c5cd3b7afb10eeb/uvloop-0.22.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:700e674a166ca5778255e0e1dc4e9d79ab2acc57b9171b79e65feba7184b3370", size = 4317413, upload-time = "2025-10-16T22:16:31.644Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/5f/6f/e62b4dfc7ad6518e7eff2516f680d02a0f6eb62c0c212e152ca708a0085e/uvloop-0.22.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b5b1ac819a3f946d3b2ee07f09149578ae76066d70b44df3fa990add49a82e4", size = 4426307, upload-time = "2025-10-16T22:16:32.917Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/90/60/97362554ac21e20e81bcef1150cb2a7e4ffdaf8ea1e5b2e8bf7a053caa18/uvloop-0.22.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e047cc068570bac9866237739607d1313b9253c3051ad84738cbb095be0537b2", size = 4131970, upload-time = "2025-10-16T22:16:34.015Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/99/39/6b3f7d234ba3964c428a6e40006340f53ba37993f46ed6e111c6e9141d18/uvloop-0.22.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:512fec6815e2dd45161054592441ef76c830eddaad55c8aa30952e6fe1ed07c0", size = 4296343, upload-time = "2025-10-16T22:16:35.149Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/89/8c/182a2a593195bfd39842ea68ebc084e20c850806117213f5a299dfc513d9/uvloop-0.22.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:561577354eb94200d75aca23fbde86ee11be36b00e52a4eaf8f50fb0c86b7705", size = 1358611, upload-time = "2025-10-16T22:16:36.833Z" },
|
{ url = "https://files.pythonhosted.org/packages/89/8c/182a2a593195bfd39842ea68ebc084e20c850806117213f5a299dfc513d9/uvloop-0.22.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:561577354eb94200d75aca23fbde86ee11be36b00e52a4eaf8f50fb0c86b7705", size = 1358611, upload-time = "2025-10-16T22:16:36.833Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d2/14/e301ee96a6dc95224b6f1162cd3312f6d1217be3907b79173b06785f2fe7/uvloop-0.22.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cdf5192ab3e674ca26da2eada35b288d2fa49fdd0f357a19f0e7c4e7d5077c8", size = 751811, upload-time = "2025-10-16T22:16:38.275Z" },
|
{ url = "https://files.pythonhosted.org/packages/d2/14/e301ee96a6dc95224b6f1162cd3312f6d1217be3907b79173b06785f2fe7/uvloop-0.22.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cdf5192ab3e674ca26da2eada35b288d2fa49fdd0f357a19f0e7c4e7d5077c8", size = 751811, upload-time = "2025-10-16T22:16:38.275Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b7/02/654426ce265ac19e2980bfd9ea6590ca96a56f10c76e63801a2df01c0486/uvloop-0.22.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e2ea3d6190a2968f4a14a23019d3b16870dd2190cd69c8180f7c632d21de68d", size = 4288562, upload-time = "2025-10-16T22:16:39.375Z" },
|
{ url = "https://files.pythonhosted.org/packages/b7/02/654426ce265ac19e2980bfd9ea6590ca96a56f10c76e63801a2df01c0486/uvloop-0.22.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e2ea3d6190a2968f4a14a23019d3b16870dd2190cd69c8180f7c632d21de68d", size = 4288562, upload-time = "2025-10-16T22:16:39.375Z" },
|
||||||
|
|
@ -1824,6 +1813,12 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/f8/ba/d69adbe699b768f6b29a5eec7b47dd610bd17a69de51b251126a801369ea/uvloop-0.22.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1f38ec5e3f18c8a10ded09742f7fb8de0108796eb673f30ce7762ce1b8550cad", size = 4239051, upload-time = "2025-10-16T22:16:43.224Z" },
|
{ url = "https://files.pythonhosted.org/packages/f8/ba/d69adbe699b768f6b29a5eec7b47dd610bd17a69de51b251126a801369ea/uvloop-0.22.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1f38ec5e3f18c8a10ded09742f7fb8de0108796eb673f30ce7762ce1b8550cad", size = 4239051, upload-time = "2025-10-16T22:16:43.224Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "varint"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/a8/fe/1ea0ba0896dfa47186692655b86db3214c4b7c9e0e76c7b1dc257d101ab1/varint-1.0.2.tar.gz", hash = "sha256:a6ecc02377ac5ee9d65a6a8ad45c9ff1dac8ccee19400a5950fb51d594214ca5", size = 1886, upload-time = "2016-02-24T20:42:38.5Z" }
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wcwidth"
|
name = "wcwidth"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
|
|
@ -1839,17 +1834,6 @@ version = "12.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/2e/62/7a7874b7285413c954a4cca3c11fd851f11b2fe5b4ae2d9bee4f6d9bdb10/websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b", size = 104994, upload-time = "2023-10-21T14:21:11.88Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/2e/62/7a7874b7285413c954a4cca3c11fd851f11b2fe5b4ae2d9bee4f6d9bdb10/websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b", size = 104994, upload-time = "2023-10-21T14:21:11.88Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/a9/6d/23cc898647c8a614a0d9ca703695dd04322fb5135096a20c2684b7c852b6/websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df", size = 124061, upload-time = "2023-10-21T14:20:02.221Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/39/34/364f30fdf1a375e4002a26ee3061138d1571dfda6421126127d379d13930/websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc", size = 121296, upload-time = "2023-10-21T14:20:03.591Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/2e/00/96ae1c9dcb3bc316ef683f2febd8c97dde9f254dc36c3afc65c7645f734c/websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b", size = 121326, upload-time = "2023-10-21T14:20:04.956Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/af/f1/bba1e64430685dd456c1a1fd6b0c791ae33104967b928aefeff261761e8d/websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb", size = 131807, upload-time = "2023-10-21T14:20:06.153Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/62/3b/98ee269712f37d892b93852ce07b3e6d7653160ca4c0d4f8c8663f8021f8/websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92", size = 130751, upload-time = "2023-10-21T14:20:07.753Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/f1/00/d6f01ca2b191f8b0808e4132ccd2e7691f0453cbd7d0f72330eb97453c3a/websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed", size = 131176, upload-time = "2023-10-21T14:20:09.212Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/af/9c/703ff3cd8109dcdee6152bae055d852ebaa7750117760ded697ab836cbcf/websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5", size = 136246, upload-time = "2023-10-21T14:20:10.423Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/0b/a5/1a38fb85a456b9dc874ec984f3ff34f6550eafd17a3da28753cd3c1628e8/websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2", size = 135466, upload-time = "2023-10-21T14:20:11.826Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/3c/98/1261f289dff7e65a38d59d2f591de6ed0a2580b729aebddec033c4d10881/websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113", size = 136083, upload-time = "2023-10-21T14:20:13.451Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a9/1c/f68769fba63ccb9c13fe0a25b616bd5aebeef1c7ddebc2ccc32462fb784d/websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d", size = 124460, upload-time = "2023-10-21T14:20:14.719Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/20/52/8915f51f9aaef4e4361c89dd6cf69f72a0159f14e0d25026c81b6ad22525/websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f", size = 124985, upload-time = "2023-10-21T14:20:15.817Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/79/4d/9cc401e7b07e80532ebc8c8e993f42541534da9e9249c59ee0139dcb0352/websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e", size = 118370, upload-time = "2023-10-21T14:21:10.075Z" },
|
{ url = "https://files.pythonhosted.org/packages/79/4d/9cc401e7b07e80532ebc8c8e993f42541534da9e9249c59ee0139dcb0352/websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e", size = 118370, upload-time = "2023-10-21T14:21:10.075Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1859,16 +1843,6 @@ version = "1.17.3"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0", size = 55547, upload-time = "2025-08-12T05:53:21.714Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0", size = 55547, upload-time = "2025-08-12T05:53:21.714Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/9f/41/cad1aba93e752f1f9268c77270da3c469883d56e2798e7df6240dcb2287b/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0", size = 53998, upload-time = "2025-08-12T05:51:47.138Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/60/f8/096a7cc13097a1869fe44efe68dace40d2a16ecb853141394047f0780b96/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba", size = 39020, upload-time = "2025-08-12T05:51:35.906Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/33/df/bdf864b8997aab4febb96a9ae5c124f700a5abd9b5e13d2a3214ec4be705/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd", size = 39098, upload-time = "2025-08-12T05:51:57.474Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9f/81/5d931d78d0eb732b95dc3ddaeeb71c8bb572fb01356e9133916cd729ecdd/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828", size = 88036, upload-time = "2025-08-12T05:52:34.784Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ca/38/2e1785df03b3d72d34fc6252d91d9d12dc27a5c89caef3335a1bbb8908ca/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9", size = 88156, upload-time = "2025-08-12T05:52:13.599Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b3/8b/48cdb60fe0603e34e05cffda0b2a4adab81fd43718e11111a4b0100fd7c1/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396", size = 87102, upload-time = "2025-08-12T05:52:14.56Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/3c/51/d81abca783b58f40a154f1b2c56db1d2d9e0d04fa2d4224e357529f57a57/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc", size = 87732, upload-time = "2025-08-12T05:52:36.165Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9e/b1/43b286ca1392a006d5336412d41663eeef1ad57485f3e52c767376ba7e5a/wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe", size = 36705, upload-time = "2025-08-12T05:53:07.123Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/28/de/49493f962bd3c586ab4b88066e967aa2e0703d6ef2c43aa28cb83bf7b507/wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c", size = 38877, upload-time = "2025-08-12T05:53:05.436Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/f1/48/0f7102fe9cb1e8a5a77f80d4f0956d62d97034bbe88d33e94699f99d181d/wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6", size = 36885, upload-time = "2025-08-12T05:52:54.367Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fc/f6/759ece88472157acb55fc195e5b116e06730f1b651b5b314c66291729193/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0", size = 54003, upload-time = "2025-08-12T05:51:48.627Z" },
|
{ url = "https://files.pythonhosted.org/packages/fc/f6/759ece88472157acb55fc195e5b116e06730f1b651b5b314c66291729193/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0", size = 54003, upload-time = "2025-08-12T05:51:48.627Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/4f/a9/49940b9dc6d47027dc850c116d79b4155f15c08547d04db0f07121499347/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77", size = 39025, upload-time = "2025-08-12T05:51:37.156Z" },
|
{ url = "https://files.pythonhosted.org/packages/4f/a9/49940b9dc6d47027dc850c116d79b4155f15c08547d04db0f07121499347/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77", size = 39025, upload-time = "2025-08-12T05:51:37.156Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/45/35/6a08de0f2c96dcdd7fe464d7420ddb9a7655a6561150e5fc4da9356aeaab/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7", size = 39108, upload-time = "2025-08-12T05:51:58.425Z" },
|
{ url = "https://files.pythonhosted.org/packages/45/35/6a08de0f2c96dcdd7fe464d7420ddb9a7655a6561150e5fc4da9356aeaab/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7", size = 39108, upload-time = "2025-08-12T05:51:58.425Z" },
|
||||||
|
|
@ -1896,13 +1870,13 @@ wheels = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xonsh"
|
name = "xonsh"
|
||||||
version = "0.22.4"
|
version = "0.24.2"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/48/df/1fc9ed62b3d7c14612e1713e9eb7bd41d54f6ad1028a8fbb6b7cddebc345/xonsh-0.22.4.tar.gz", hash = "sha256:6be346563fec2db75778ba5d2caee155525e634e99d9cc8cc347626025c0b3fa", size = 826665, upload-time = "2026-02-17T07:53:39.424Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/c1/28/974f44afd5c05bcfb012d52a91b514e629706048c85d669a29eab2f0369a/xonsh-0.24.2.tar.gz", hash = "sha256:461244cf1de8ed28d0c07cc548342b9e7969d46e17ef8d71b5d3064307930a25", size = 1217004, upload-time = "2026-08-23T15:41:03.929Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/2e/00/7cbc0c1fb64365a0a317c54ce3a151c9644eea5a509d9cbaae61c9fd1426/xonsh-0.22.4-py311-none-any.whl", hash = "sha256:38b29b29fa85aa756462d9d9bbcaa1d85478c2108da3de6cc590a69a4bcd1a01", size = 654375, upload-time = "2026-02-17T07:53:37.702Z" },
|
{ url = "https://files.pythonhosted.org/packages/16/32/2dc9f6142d6744fa584a59507030a851971e4088af86f187437344f60315/xonsh-0.24.2-py311-none-any.whl", hash = "sha256:60015217f74663d52c4038e495546710ecdffeb0beae96834b4ac3ea970a3927", size = 821746, upload-time = "2026-08-23T15:41:02.525Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/2e/c2/3dd498dc28d8f89cdd52e39950c5e591499ae423f61694c0bb4d03ed1d82/xonsh-0.22.4-py312-none-any.whl", hash = "sha256:4e538fac9f4c3d866ddbdeca068f0c0515469c997ed58d3bfee963878c6df5a5", size = 654300, upload-time = "2026-02-17T07:53:35.813Z" },
|
{ url = "https://files.pythonhosted.org/packages/b0/77/9a9b1e1fcf377b412bb45626be1af9a97414f8a3aa96df566e06b8ebb092/xonsh-0.24.2-py312-none-any.whl", hash = "sha256:68e93b77bbf9e2a26f70bf323a1c311014dc2aed9ebcf036e68e7fe59ed0849c", size = 821749, upload-time = "2026-08-23T15:40:25.865Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/82/7d/1f9c7147518e9f03f6ce081b5bfc4f1aceb6ec5caba849024d005e41d3be/xonsh-0.22.4-py313-none-any.whl", hash = "sha256:cc5fabf0ad0c56a2a11bed1e6a43c4ec6416a5b30f24f126b8e768547c3793e2", size = 654818, upload-time = "2026-02-17T07:53:33.477Z" },
|
{ url = "https://files.pythonhosted.org/packages/08/6a/aaae1f889eec7f015aa8b7041f807871cb18a2c2bc8f0564c5ca70f4bc16/xonsh-0.24.2-py313-none-any.whl", hash = "sha256:da19e84ad0361c0c8052f5119fd08bd111995df60fa233b8a61a3d66ea253d78", size = 822213, upload-time = "2026-08-23T15:40:24.572Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1910,10 +1884,6 @@ name = "yapic-json"
|
||||||
version = "1.9.5"
|
version = "1.9.5"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/3d/35/5d52934c020bfbffaff2c09b311f65103655a25dd4182cd23984187b9872/yapic.json-1.9.5.tar.gz", hash = "sha256:d4c7a533b0670709fca9623f243e6bc5b6c0f67adbb4de508af2381c271e98b4", size = 105372, upload-time = "2024-09-29T18:43:37.038Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/3d/35/5d52934c020bfbffaff2c09b311f65103655a25dd4182cd23984187b9872/yapic.json-1.9.5.tar.gz", hash = "sha256:d4c7a533b0670709fca9623f243e6bc5b6c0f67adbb4de508af2381c271e98b4", size = 105372, upload-time = "2024-09-29T18:43:37.038Z" }
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/26/3d/eedd25e7497d7e761907705b99f8fb452e27a24f54be9d4d4cd505eec1b6/yapic.json-1.9.5-cp312-cp312-win32.whl", hash = "sha256:63036af738ccd4d3cf5a3446a2867ad62e78f66af21dcd73b77992a19ee43e15", size = 77845, upload-time = "2024-09-29T18:47:38.216Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/cb/6e/664b9557cf99e34783da9f2cb384817379cea2b8d5f02f73fe119023c4dd/yapic.json-1.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:3db5a5828efd0d207a74f71bd41ab7db995fe26920bff1e413b756b367691db2", size = 84473, upload-time = "2024-09-29T18:47:28.002Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yarl"
|
name = "yarl"
|
||||||
|
|
@ -1926,22 +1896,6 @@ dependencies = [
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/75/ff/46736024fee3429b80a165a732e38e5d5a238721e634ab41b040d49f8738/yarl-1.22.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", size = 142000, upload-time = "2025-10-06T14:09:44.631Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/5a/9a/b312ed670df903145598914770eb12de1bac44599549b3360acc96878df8/yarl-1.22.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", size = 94338, upload-time = "2025-10-06T14:09:46.372Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ba/f5/0601483296f09c3c65e303d60c070a5c19fcdbc72daa061e96170785bc7d/yarl-1.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", size = 94909, upload-time = "2025-10-06T14:09:48.648Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/60/41/9a1fe0b73dbcefce72e46cf149b0e0a67612d60bfc90fb59c2b2efdfbd86/yarl-1.22.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", size = 372940, upload-time = "2025-10-06T14:09:50.089Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/17/7a/795cb6dfee561961c30b800f0ed616b923a2ec6258b5def2a00bf8231334/yarl-1.22.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", size = 345825, upload-time = "2025-10-06T14:09:52.142Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d7/93/a58f4d596d2be2ae7bab1a5846c4d270b894958845753b2c606d666744d3/yarl-1.22.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", size = 386705, upload-time = "2025-10-06T14:09:54.128Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/61/92/682279d0e099d0e14d7fd2e176bd04f48de1484f56546a3e1313cd6c8e7c/yarl-1.22.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", size = 396518, upload-time = "2025-10-06T14:09:55.762Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/db/0f/0d52c98b8a885aeda831224b78f3be7ec2e1aa4a62091f9f9188c3c65b56/yarl-1.22.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", size = 377267, upload-time = "2025-10-06T14:09:57.958Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/22/42/d2685e35908cbeaa6532c1fc73e89e7f2efb5d8a7df3959ea8e37177c5a3/yarl-1.22.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", size = 365797, upload-time = "2025-10-06T14:09:59.527Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a2/83/cf8c7bcc6355631762f7d8bdab920ad09b82efa6b722999dfb05afa6cfac/yarl-1.22.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", size = 365535, upload-time = "2025-10-06T14:10:01.139Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/25/e1/5302ff9b28f0c59cac913b91fe3f16c59a033887e57ce9ca5d41a3a94737/yarl-1.22.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", size = 382324, upload-time = "2025-10-06T14:10:02.756Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/bf/cd/4617eb60f032f19ae3a688dc990d8f0d89ee0ea378b61cac81ede3e52fae/yarl-1.22.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", size = 383803, upload-time = "2025-10-06T14:10:04.552Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/59/65/afc6e62bb506a319ea67b694551dab4a7e6fb7bf604e9bd9f3e11d575fec/yarl-1.22.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", size = 374220, upload-time = "2025-10-06T14:10:06.489Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e7/3d/68bf18d50dc674b942daec86a9ba922d3113d8399b0e52b9897530442da2/yarl-1.22.0-cp312-cp312-win32.whl", hash = "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", size = 81589, upload-time = "2025-10-06T14:10:09.254Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c8/9a/6ad1a9b37c2f72874f93e691b2e7ecb6137fb2b899983125db4204e47575/yarl-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", size = 87213, upload-time = "2025-10-06T14:10:11.369Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/44/c5/c21b562d1680a77634d748e30c653c3ca918beb35555cff24986fff54598/yarl-1.22.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", size = 81330, upload-time = "2025-10-06T14:10:13.112Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ea/f3/d67de7260456ee105dc1d162d43a019ecad6b91e2f51809d6cddaa56690e/yarl-1.22.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", size = 139980, upload-time = "2025-10-06T14:10:14.601Z" },
|
{ url = "https://files.pythonhosted.org/packages/ea/f3/d67de7260456ee105dc1d162d43a019ecad6b91e2f51809d6cddaa56690e/yarl-1.22.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", size = 139980, upload-time = "2025-10-06T14:10:14.601Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", size = 93424, upload-time = "2025-10-06T14:10:16.115Z" },
|
{ url = "https://files.pythonhosted.org/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", size = 93424, upload-time = "2025-10-06T14:10:16.115Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/18/91/3274b215fd8442a03975ce6bee5fe6aa57a8326b29b9d3d56234a1dca244/yarl-1.22.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", size = 93821, upload-time = "2025-10-06T14:10:17.993Z" },
|
{ url = "https://files.pythonhosted.org/packages/18/91/3274b215fd8442a03975ce6bee5fe6aa57a8326b29b9d3d56234a1dca244/yarl-1.22.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", size = 93821, upload-time = "2025-10-06T14:10:17.993Z" },
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue