Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d018724aa4 | ||
|
|
5b97bed704 | ||
|
|
55786b154d | ||
|
|
6ab9681dec | ||
|
|
89641c6316 | ||
|
|
136ff6a688 | ||
|
|
d918d93f4a | ||
|
|
8046c532a6 | ||
|
|
92820a362d | ||
|
|
9fd90031a9 | ||
|
|
2f2223a112 | ||
|
|
50e6cf9dfd | ||
|
|
1b5e3093e6 | ||
|
|
9e3578b4a2 | ||
|
|
a3087e1a96 | ||
|
|
4b16ea2ca2 | ||
|
|
5dd361c4ef | ||
|
|
098112742c | ||
|
|
cd31e0743e | ||
|
|
1a7d0bf7cc | ||
|
|
41b5ebf0f0 | ||
|
|
5436bede29 | ||
|
|
c01b3958dc | ||
|
|
c16367285f | ||
|
|
17eae253e6 | ||
|
|
ab30988614 | ||
|
|
9b8e547f86 | ||
|
|
3b8cbb9ff1 | ||
|
|
d39d278296 | ||
|
|
ea8b922367 | ||
|
|
0d1c8d80e0 | ||
|
|
494d25da97 | ||
|
|
0327d93a35 | ||
|
|
680584c468 | ||
|
|
c0dbafb198 | ||
|
|
97d2c4ac34 | ||
|
|
055d633c91 | ||
|
|
68c57f265f | ||
|
|
1ba0f8ed83 | ||
|
|
7f74b083d3 | ||
|
|
97c20dae0a | ||
|
|
09c7aff640 | ||
|
|
7e7cdc9615 | ||
|
|
b6fb0fd2b9 | ||
|
|
46788e7d14 | ||
|
|
5b4f84a241 | ||
|
|
0c56bfdf9e | ||
|
|
4a5d793cd6 | ||
|
|
1894ff1aea | ||
|
|
3ab9294000 | ||
|
|
5e0641634b | ||
|
|
a1975bc9b8 | ||
|
|
6a265f03f7 | ||
|
|
c3658f028f | ||
|
|
ba3c653a29 | ||
|
|
61fbc132ed | ||
|
|
3f9f232990 | ||
|
|
29c2398846 | ||
|
|
ecc161820d | ||
|
|
5fec3052f6 | ||
|
|
437ee774ab |
6
.github/workflows/python-publish.yml
vendored
6
.github/workflows/python-publish.yml
vendored
@@ -13,10 +13,10 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4.2.2
|
||||||
- name: Publish GH release
|
- name: Publish GH release
|
||||||
uses: softprops/action-gh-release@v0.1.14
|
uses: softprops/action-gh-release@v2.1.0
|
||||||
- name: Build using poetry and publish to PyPi
|
- name: Build using poetry and publish to PyPi
|
||||||
uses: JRubics/poetry-publish@v1.11
|
uses: JRubics/poetry-publish@v2.0
|
||||||
with:
|
with:
|
||||||
pypi_token: ${{ secrets.PYPI_API_KEY }}
|
pypi_token: ${{ secrets.PYPI_API_KEY }}
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ repos:
|
|||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
|
name: check-yaml for mkdocs.yml
|
||||||
|
files: ^mkdocs\.yml$
|
||||||
|
args: [--unsafe]
|
||||||
|
- id: check-yaml
|
||||||
|
name: check-yaml for other YAML files
|
||||||
|
exclude: ^mkdocs\.yml$
|
||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 24.10.0
|
rev: 24.10.0
|
||||||
|
|||||||
@@ -1,20 +1,18 @@
|
|||||||
# .readthedocs.yaml
|
# .readthedocs.yaml
|
||||||
# Read the Docs configuration file
|
|
||||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
|
||||||
|
|
||||||
# Required
|
|
||||||
version: 2
|
version: 2
|
||||||
|
|
||||||
# Set the version of Python and other tools you might need
|
# Set the version of Python and other tools you might need
|
||||||
build:
|
build:
|
||||||
os: ubuntu-20.04
|
os: ubuntu-20.04
|
||||||
tools:
|
tools: { python: "3.11" }
|
||||||
python: "3.9"
|
jobs:
|
||||||
|
pre_create_environment:
|
||||||
|
- asdf plugin add poetry
|
||||||
|
- asdf install poetry latest
|
||||||
|
- asdf global poetry latest
|
||||||
|
- poetry config virtualenvs.create false
|
||||||
|
post_install:
|
||||||
|
- VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install --only docs
|
||||||
|
|
||||||
mkdocs:
|
mkdocs:
|
||||||
configuration: mkdocs.yml
|
configuration: mkdocs.yml
|
||||||
|
|
||||||
# Optionally declare the Python requirements required to build your docs
|
|
||||||
python:
|
|
||||||
install:
|
|
||||||
- requirements: docs/requirements.txt
|
|
||||||
189
docs/index.md
189
docs/index.md
@@ -11,145 +11,149 @@
|
|||||||
[](https://pyasic.readthedocs.io/en/latest/)
|
[](https://pyasic.readthedocs.io/en/latest/)
|
||||||
[](https://github.com/UpstreamData/pyasic/blob/master/LICENSE.txt)
|
[](https://github.com/UpstreamData/pyasic/blob/master/LICENSE.txt)
|
||||||
|
|
||||||
---
|
|
||||||
## Intro
|
## Intro
|
||||||
---
|
---
|
||||||
Welcome to `pyasic`! `pyasic` uses an asynchronous method of communicating with ASIC miners on your network, which makes it super fast.
|
Welcome to `pyasic`! `pyasic` uses an asynchronous method of communicating with ASIC miners on your network, which makes it super fast.
|
||||||
|
|
||||||
[Click here to view supported miner types](miners/supported_types.md)
|
[Click here to view supported miner types](miners/supported_types.md)
|
||||||
|
|
||||||
---
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
It is recommended to install `pyasic` in a [virtual environment](https://realpython.com/python-virtual-environments-a-primer/#what-other-popular-options-exist-aside-from-venv) to isolate it from the rest of your system. Options include:
|
|
||||||
- [pypoetry](https://python-poetry.org/): the reccommended way, since pyasic already uses it by default
|
|
||||||
|
|
||||||
```
|
|
||||||
poetry install
|
|
||||||
```
|
|
||||||
|
|
||||||
- [venv](https://docs.python.org/3/library/venv.html): included in Python standard library but has fewer features than other options
|
|
||||||
- [pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv): [pyenv](https://github.com/pyenv/pyenv) plugin for managing virtualenvs
|
|
||||||
|
|
||||||
```
|
|
||||||
pyenv install <python version number>
|
|
||||||
pyenv virtualenv <python version number> <env name>
|
|
||||||
pyenv activate <env name>
|
|
||||||
```
|
|
||||||
|
|
||||||
- [conda](https://docs.conda.io/en/latest/)
|
|
||||||
|
|
||||||
##### Installing `pyasic`
|
|
||||||
|
|
||||||
`python -m pip install pyasic` or `poetry install`
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
It is recommended to install `pyasic` in a [virtual environment](https://realpython.com/python-virtual-environments-a-primer/#what-other-popular-options-exist-aside-from-venv) to isolate it from the rest of your system.
|
||||||
|
`pyasic` can be installed directly from pip, either with `pip install pyasic`, or a different command if using a tool like `pypoetry`.
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
---
|
---
|
||||||
Getting started with `pyasic` is easy. First, find your miner (or miners) on the network by scanning for them or getting the correct class automatically for them if you know the IP.
|
Getting started with `pyasic` is easy. First, find your miner (or miners) on the network by scanning for them or getting the correct class automatically for them if you know the IP.
|
||||||
|
|
||||||
##### Scanning for miners
|
### Scanning for miners
|
||||||
To scan for miners in `pyasic`, we use the class [`MinerNetwork`][pyasic.network.MinerNetwork], which abstracts the search, communication, identification, setup, and return of a miner to 1 command.
|
To scan for miners in `pyasic`, we use the class [`MinerNetwork`][pyasic.network.MinerNetwork], which abstracts the search, communication, identification, setup, and return of a miner to 1 command.
|
||||||
The command [`MinerNetwork.scan()`][pyasic.network.MinerNetwork.scan] returns a list that contains any miners found.
|
The command [`MinerNetwork.scan()`][pyasic.network.MinerNetwork.scan] returns a list that contains any miners found.
|
||||||
```python
|
```python3
|
||||||
import asyncio # asyncio for handling the async part
|
import asyncio# (1)!
|
||||||
from pyasic.network import MinerNetwork # miner network handles the scanning
|
from pyasic.network import MinerNetwork# (2)!
|
||||||
|
|
||||||
|
|
||||||
async def scan_miners(): # define async scan function to allow awaiting
|
async def scan_miners():# (3)!
|
||||||
# create a miner network
|
network = MinerNetwork.from_subnet("192.168.1.50/24")# (4)!
|
||||||
# you can pass in any IP and it will use that in a subnet with a /24 mask (255 IPs).
|
|
||||||
network = MinerNetwork.from_subnet("192.168.1.50/24") # this uses the 192.168.1.0-255 network
|
|
||||||
|
|
||||||
# scan for miners asynchronously
|
miners = await network.scan()# (5)!
|
||||||
# this will return the correct type of miners if they are supported with all functionality.
|
|
||||||
miners = await network.scan()
|
|
||||||
print(miners)
|
print(miners)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(scan_miners()) # run the scan asynchronously with asyncio.run()
|
asyncio.run(scan_miners())# (6)!
|
||||||
```
|
```
|
||||||
|
|
||||||
|
1. `asyncio` for handling the async part.
|
||||||
|
2. `MinerNetwork` handles the scanning.
|
||||||
|
3. Define an async function to allow awaiting.
|
||||||
|
4. Create a miner network.
|
||||||
|
You can pass in any IP and it will use that in a subnet with a /24 mask (255 IPs).
|
||||||
|
This uses the 192.168.1.0-255 network.
|
||||||
|
5. Scan for miners asynchronously.
|
||||||
|
This will return the correct type of miners (if they are supported) with all functionality.
|
||||||
|
6. Run the scan asynchronously with asyncio.run().
|
||||||
|
|
||||||
---
|
---
|
||||||
##### Creating miners based on IP
|
### Creating miners based on IP
|
||||||
If you already know the IP address of your miner or miners, you can use the [`MinerFactory`][pyasic.miners.factory.MinerFactory] to communicate and identify the miners, or an abstraction of its functionality, [`get_miner()`][pyasic.miners.get_miner].
|
If you already know the IP address of your miner or miners, you can use the [`MinerFactory`][pyasic.miners.factory.MinerFactory] to communicate and identify the miners, or an abstraction of its functionality, [`get_miner()`][pyasic.miners.get_miner].
|
||||||
The function [`get_miner()`][pyasic.miners.get_miner] will return any miner it found at the IP address specified, or an `UnknownMiner` if it cannot identify the miner.
|
The function [`get_miner()`][pyasic.miners.get_miner] will return any miner it found at the IP address specified, or an `UnknownMiner` if it cannot identify the miner.
|
||||||
```python
|
```python
|
||||||
import asyncio # asyncio for handling the async part
|
import asyncio# (1)!
|
||||||
from pyasic import get_miner # handles miner creation
|
from pyasic import get_miner# (2)!
|
||||||
|
|
||||||
|
|
||||||
async def get_miners(): # define async scan function to allow awaiting
|
async def get_miners():# (3)!
|
||||||
# get the miner with the miner factory
|
miner_1 = await get_miner("192.168.1.75")# (4)!
|
||||||
# the miner factory is a singleton, and will always use the same object and cache
|
|
||||||
# this means you can always call it as MinerFactory().get_miner(), or just get_miner()
|
|
||||||
miner_1 = await get_miner("192.168.1.75")
|
|
||||||
miner_2 = await get_miner("192.168.1.76")
|
miner_2 = await get_miner("192.168.1.76")
|
||||||
print(miner_1, miner_2)
|
print(miner_1, miner_2)
|
||||||
|
|
||||||
# can also gather these, since they are async
|
|
||||||
# gathering them will get them both at the same time
|
|
||||||
# this makes it much faster to get a lot of miners at a time
|
|
||||||
tasks = [get_miner("192.168.1.75"), get_miner("192.168.1.76")]
|
tasks = [get_miner("192.168.1.75"), get_miner("192.168.1.76")]
|
||||||
miners = await asyncio.gather(*tasks)
|
miners = await asyncio.gather(*tasks)# (5)!
|
||||||
print(miners)
|
print(miners)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(get_miners()) # get the miners asynchronously with asyncio.run()
|
asyncio.run(get_miners())# (6)!
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
1. `asyncio` for handling the async part.
|
||||||
|
2. `get_miner` handles the miner type selection.
|
||||||
|
3. Define an async function to allow awaiting.
|
||||||
|
4. Get the miner.
|
||||||
|
5. Can also gather these, since they are async.
|
||||||
|
Gathering them will get them both at the same time.
|
||||||
|
This makes it much faster to get a lot of miners at a time.
|
||||||
|
6. Get the miners asynchronously with asyncio.run().
|
||||||
|
|
||||||
## Data gathering
|
## Data gathering
|
||||||
---
|
---
|
||||||
Once you have your miner(s) identified, you will likely want to get data from the miner(s). You can do this using a built-in function in each miner called `get_data()`.
|
Once you have your miner(s) identified, you will likely want to get data from the miner(s). You can do this using a built-in function in each miner called `get_data()`.
|
||||||
This function will return an instance of the dataclass [`MinerData`][pyasic.data.MinerData] with all data it can gather from the miner.
|
This function will return an instance of the dataclass [`MinerData`][pyasic.data.MinerData] with all data it can gather from the miner.
|
||||||
Each piece of data in a [`MinerData`][pyasic.data.MinerData] instance can be referenced by getting it as an attribute, such as [`MinerData().hashrate`][pyasic.data.MinerData].
|
Each piece of data in a [`MinerData`][pyasic.data.MinerData] instance can be referenced by getting it as an attribute, such as [`MinerData().hashrate`][pyasic.data.MinerData].
|
||||||
|
|
||||||
##### One miner
|
### One miner
|
||||||
```python
|
```python
|
||||||
import asyncio
|
import asyncio# (1)!
|
||||||
from pyasic import get_miner
|
from pyasic import get_miner# (2)!
|
||||||
|
|
||||||
async def gather_miner_data():
|
|
||||||
miner = await get_miner("192.168.1.75")
|
async def gather_miner_data():# (3)!
|
||||||
if miner is not None:
|
miner = await get_miner("192.168.1.75")# (4)!
|
||||||
miner_data = await miner.get_data()
|
if miner is not None:# (5)!
|
||||||
print(miner_data) # all data from the dataclass
|
miner_data = await miner.get_data()# (6)!
|
||||||
|
print(miner_data)# (7)!
|
||||||
print(miner_data.hashrate) # hashrate of the miner in TH/s
|
print(miner_data.hashrate) # hashrate of the miner in TH/s
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(gather_miner_data())
|
asyncio.run(gather_miner_data())# (9)!
|
||||||
```
|
```
|
||||||
---
|
|
||||||
##### Multiple miners
|
1. `asyncio` for handling the async part.
|
||||||
|
2. `get_miner` handles the miner type selection.
|
||||||
|
3. Define an async function to allow awaiting.
|
||||||
|
4. Get the miner.
|
||||||
|
5. Make sure the miner exists.
|
||||||
|
If this result is `None`, the miner may be offline.
|
||||||
|
6. Get data from the miner.
|
||||||
|
7. All the data from the dataclass.
|
||||||
|
8. Hashrate of the miner, with unit information.
|
||||||
|
9. Get the miner data asynchronously with asyncio.run().
|
||||||
|
|
||||||
|
### Multiple miners
|
||||||
You can do something similar with multiple miners, with only needing to make a small change to get all the data at once.
|
You can do something similar with multiple miners, with only needing to make a small change to get all the data at once.
|
||||||
```python
|
```python
|
||||||
import asyncio # asyncio for handling the async part
|
import asyncio# (1)!
|
||||||
from pyasic.network import MinerNetwork # miner network handles the scanning
|
from pyasic.network import MinerNetwork# (2)!
|
||||||
|
|
||||||
|
|
||||||
async def gather_miner_data(): # define async scan function to allow awaiting
|
async def gather_miner_data():# (3)!
|
||||||
network = MinerNetwork.from_subnet("192.168.1.50/24")
|
network = MinerNetwork.from_subnet("192.168.1.50/24")# (4)!
|
||||||
miners = await network.scan()
|
miners = await network.scan()# (5)!
|
||||||
|
|
||||||
# we need to asyncio.gather() all the miners get_data() functions to make them run together
|
|
||||||
all_miner_data = await asyncio.gather(*[miner.get_data() for miner in miners])
|
all_miner_data = await asyncio.gather(*[miner.get_data() for miner in miners])
|
||||||
|
|
||||||
for miner_data in all_miner_data:
|
for miner_data in all_miner_data:
|
||||||
print(miner_data) # print out all the data one by one
|
print(miner_data)# (7)!
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(gather_miner_data())
|
asyncio.run(gather_miner_data())# (8)!
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
1. `asyncio` for handling the async part.
|
||||||
|
2. `MinerNetwork` handles the scanning.
|
||||||
|
3. Define an async function to allow awaiting.
|
||||||
|
4. Create a miner network.
|
||||||
|
5. Scan for miners asynchronously.
|
||||||
|
6. Use `asyncio.gather()` with all the miners' `get_data()` functions to make them run together.
|
||||||
|
7. Print out the data one at a time.
|
||||||
|
8. Get the miner data asynchronously with asyncio.run().
|
||||||
|
|
||||||
## Miner control
|
## Miner control
|
||||||
---
|
---
|
||||||
`pyasic` exposes a standard interface for each miner using control functions.
|
`pyasic` exposes a standard interface for each miner using control functions.
|
||||||
Every miner class in `pyasic` must implement all the control functions defined in [`MinerProtocol`][pyasic.miners.base.MinerProtocol].
|
Every miner class in `pyasic` must implement all the following control functions.
|
||||||
|
|
||||||
These functions are
|
|
||||||
[`check_light`][pyasic.miners.base.MinerProtocol.check_light],
|
[`check_light`][pyasic.miners.base.MinerProtocol.check_light],
|
||||||
[`fault_light_off`][pyasic.miners.base.MinerProtocol.fault_light_off],
|
[`fault_light_off`][pyasic.miners.base.MinerProtocol.fault_light_off],
|
||||||
[`fault_light_on`][pyasic.miners.base.MinerProtocol.fault_light_on],
|
[`fault_light_on`][pyasic.miners.base.MinerProtocol.fault_light_on],
|
||||||
@@ -166,35 +170,41 @@ These functions are
|
|||||||
[`send_config`][pyasic.miners.base.MinerProtocol.send_config], and
|
[`send_config`][pyasic.miners.base.MinerProtocol.send_config], and
|
||||||
[`set_power_limit`][pyasic.miners.base.MinerProtocol.set_power_limit].
|
[`set_power_limit`][pyasic.miners.base.MinerProtocol.set_power_limit].
|
||||||
|
|
||||||
##### Usage
|
### Usage
|
||||||
```python
|
```python
|
||||||
import asyncio
|
import asyncio# (1)!
|
||||||
from pyasic import get_miner
|
from pyasic import get_miner# (2)!
|
||||||
|
|
||||||
|
|
||||||
async def set_fault_light():
|
async def set_fault_light():# (3)!
|
||||||
miner = await get_miner("192.168.1.20")
|
miner = await get_miner("192.168.1.20")# (4)!
|
||||||
|
|
||||||
# call control function
|
await miner.fault_light_on()# (5)!
|
||||||
await miner.fault_light_on()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(set_fault_light())
|
asyncio.run(set_fault_light())# (6)!
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
1. `asyncio` for handling the async part.
|
||||||
|
2. `get_miner` handles the miner type selection.
|
||||||
|
3. Define an async function to allow awaiting.
|
||||||
|
4. Get the miner.
|
||||||
|
5. Call the miner control function.
|
||||||
|
6. Call the control function asynchronously with asyncio.run().
|
||||||
|
|
||||||
|
|
||||||
## Helper dataclasses
|
## Helper dataclasses
|
||||||
---
|
---
|
||||||
|
|
||||||
##### [`MinerConfig`][pyasic.config.MinerConfig] and [`MinerData`][pyasic.data.MinerData]
|
### [`MinerConfig`][pyasic.config.MinerConfig] and [`MinerData`][pyasic.data.MinerData]
|
||||||
|
|
||||||
`pyasic` implements a few dataclasses as helpers to make data return types consistent across different miners and miner APIs. The different fields of these dataclasses can all be viewed with the classmethod `cls.fields()`.
|
`pyasic` implements a few dataclasses as helpers to make data return types consistent across different miners and miner APIs. The different fields of these dataclasses can all be viewed with the classmethod `cls.fields()`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
##### [`MinerData`][pyasic.data.MinerData]
|
### [`MinerData`][pyasic.data.MinerData]
|
||||||
|
|
||||||
[`MinerData`][pyasic.data.MinerData] is a return from the [`get_data()`](#get-data) function, and is used to have a consistent dataset across all returns.
|
[`MinerData`][pyasic.data.MinerData] is a return from the [`get_data()`][pyasic.miners.base.MinerProtocol.get_data] function, and is used to have a consistent dataset across all returns.
|
||||||
|
|
||||||
You can call [`MinerData.as_dict()`][pyasic.data.MinerData.as_dict] to get the dataclass as a dictionary, and there are many other helper functions contained in the class to convert to different data formats.
|
You can call [`MinerData.as_dict()`][pyasic.data.MinerData.as_dict] to get the dataclass as a dictionary, and there are many other helper functions contained in the class to convert to different data formats.
|
||||||
|
|
||||||
@@ -213,13 +223,13 @@ average_data = sum(list_of_miner_data, start=MinerData("0.0.0.0"))/len(list_of_m
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
##### [`MinerConfig`][pyasic.config.MinerConfig]
|
### [`MinerConfig`][pyasic.config.MinerConfig]
|
||||||
|
|
||||||
[`MinerConfig`][pyasic.config.MinerConfig] is `pyasic`'s way to represent a configuration file from a miner.
|
[`MinerConfig`][pyasic.config.MinerConfig] is `pyasic`'s way to represent a configuration file from a miner.
|
||||||
It is designed to unionize the configuration of all supported miner types, and is the return from [`get_config()`](#get-config).
|
It is designed to unionize the configuration of all supported miner types, and is the return from [`get_config()`][pyasic.miners.base.MinerProtocol.get_config].
|
||||||
|
|
||||||
Each miner has a unique way to convert the [`MinerConfig`][pyasic.config.MinerConfig] to their specific type, there are helper functions in the class.
|
Each miner has a unique way to convert the [`MinerConfig`][pyasic.config.MinerConfig] to their specific type, there are helper functions in the class.
|
||||||
In most cases these helper functions should not be used, as [`send_config()`](#send-config) takes a [`MinerConfig`][pyasic.config.MinerConfig] and will do the conversion to the right type for you.
|
In most cases these helper functions should not be used, as [`send_config()`][pyasic.miners.base.MinerProtocol.send_config] takes a [`MinerConfig`][pyasic.config.MinerConfig] and will do the conversion to the right type for you.
|
||||||
|
|
||||||
You can use the [`MinerConfig`][pyasic.config.MinerConfig] as follows:
|
You can use the [`MinerConfig`][pyasic.config.MinerConfig] as follows:
|
||||||
```python
|
```python
|
||||||
@@ -241,7 +251,6 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
## Settings
|
## Settings
|
||||||
---
|
---
|
||||||
`pyasic` has settings designed to make using large groups of miners easier. You can set the default password for all types of miners using the `pyasic.settings` module, used as follows:
|
`pyasic` has settings designed to make using large groups of miners easier. You can set the default password for all types of miners using the `pyasic.settings` module, used as follows:
|
||||||
@@ -252,7 +261,7 @@ from pyasic import settings
|
|||||||
settings.update("default_antminer_web_password", "my_pwd")
|
settings.update("default_antminer_web_password", "my_pwd")
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Default values:
|
### Default values:
|
||||||
```
|
```
|
||||||
"network_ping_retries": 1,
|
"network_ping_retries": 1,
|
||||||
"network_ping_timeout": 3,
|
"network_ping_timeout": 3,
|
||||||
|
|||||||
@@ -302,6 +302,13 @@
|
|||||||
show_root_heading: false
|
show_root_heading: false
|
||||||
heading_level: 4
|
heading_level: 4
|
||||||
|
|
||||||
|
## S19k Pro (VNish)
|
||||||
|
::: pyasic.miners.antminer.vnish.X19.S19.VNishS19kPro
|
||||||
|
handler: python
|
||||||
|
options:
|
||||||
|
show_root_heading: false
|
||||||
|
heading_level: 4
|
||||||
|
|
||||||
## T19 (VNish)
|
## T19 (VNish)
|
||||||
::: pyasic.miners.antminer.vnish.X19.T19.VNishT19
|
::: pyasic.miners.antminer.vnish.X19.T19.VNishT19
|
||||||
handler: python
|
handler: python
|
||||||
@@ -358,13 +365,20 @@
|
|||||||
show_root_heading: false
|
show_root_heading: false
|
||||||
heading_level: 4
|
heading_level: 4
|
||||||
|
|
||||||
## S19j Pro (Stock)
|
## S19j Pro (Hive)
|
||||||
::: pyasic.miners.antminer.hiveon.X19.S19.HiveonS19jPro
|
::: pyasic.miners.antminer.hiveon.X19.S19.HiveonS19jPro
|
||||||
handler: python
|
handler: python
|
||||||
options:
|
options:
|
||||||
show_root_heading: false
|
show_root_heading: false
|
||||||
heading_level: 4
|
heading_level: 4
|
||||||
|
|
||||||
|
## S19 (Hive)
|
||||||
|
::: pyasic.miners.antminer.hiveon.X19.S19.HiveonS19
|
||||||
|
handler: python
|
||||||
|
options:
|
||||||
|
show_root_heading: false
|
||||||
|
heading_level: 4
|
||||||
|
|
||||||
## S19 (LuxOS)
|
## S19 (LuxOS)
|
||||||
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19
|
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19
|
||||||
handler: python
|
handler: python
|
||||||
|
|||||||
@@ -43,6 +43,13 @@
|
|||||||
show_root_heading: false
|
show_root_heading: false
|
||||||
heading_level: 4
|
heading_level: 4
|
||||||
|
|
||||||
|
## L9 (Stock)
|
||||||
|
::: pyasic.miners.antminer.bmminer.X9.L9.BMMinerL9
|
||||||
|
handler: python
|
||||||
|
options:
|
||||||
|
show_root_heading: false
|
||||||
|
heading_level: 4
|
||||||
|
|
||||||
## S9 (BOS+)
|
## S9 (BOS+)
|
||||||
::: pyasic.miners.antminer.bosminer.X9.S9.BOSMinerS9
|
::: pyasic.miners.antminer.bosminer.X9.S9.BOSMinerS9
|
||||||
handler: python
|
handler: python
|
||||||
@@ -50,7 +57,7 @@
|
|||||||
show_root_heading: false
|
show_root_heading: false
|
||||||
heading_level: 4
|
heading_level: 4
|
||||||
|
|
||||||
## T9 (Stock)
|
## T9 (Hive)
|
||||||
::: pyasic.miners.antminer.hiveon.X9.T9.HiveonT9
|
::: pyasic.miners.antminer.hiveon.X9.T9.HiveonT9
|
||||||
handler: python
|
handler: python
|
||||||
options:
|
options:
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
# pyasic
|
# pyasic
|
||||||
## A11X Models
|
## A11X Models
|
||||||
|
|
||||||
|
## Avalon 1126 Pro (Stock)
|
||||||
|
::: pyasic.miners.avalonminer.cgminer.A11X.A1126.CGMinerAvalon1126Pro
|
||||||
|
handler: python
|
||||||
|
options:
|
||||||
|
show_root_heading: false
|
||||||
|
heading_level: 4
|
||||||
|
|
||||||
## Avalon 1166 Pro (Stock)
|
## Avalon 1166 Pro (Stock)
|
||||||
::: pyasic.miners.avalonminer.cgminer.A11X.A1166.CGMinerAvalon1166Pro
|
::: pyasic.miners.avalonminer.cgminer.A11X.A1166.CGMinerAvalon1166Pro
|
||||||
handler: python
|
handler: python
|
||||||
|
|||||||
@@ -10,8 +10,3 @@ You may not instantiate this class on its own, only subclass from it.
|
|||||||
handler: python
|
handler: python
|
||||||
options:
|
options:
|
||||||
heading_level: 4
|
heading_level: 4
|
||||||
|
|
||||||
::: pyasic.miners.base.MinerProtocol
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|||||||
@@ -1,91 +1,10 @@
|
|||||||
## Control functionality
|
## Control functionality
|
||||||
|
|
||||||
### Check Light
|
All control functionality is outlined by the [`MinerProtocol`][pyasic.miners.base.MinerProtocol] class.
|
||||||
::: pyasic.miners.base.MinerProtocol.check_light
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Fault Light Off
|
## Miner Protocol
|
||||||
::: pyasic.miners.base.MinerProtocol.fault_light_off
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Fault Light On
|
::: pyasic.miners.base.MinerProtocol
|
||||||
::: pyasic.miners.base.MinerProtocol.fault_light_on
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Get Config
|
|
||||||
::: pyasic.miners.base.MinerProtocol.get_config
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Get Data
|
|
||||||
::: pyasic.miners.base.MinerProtocol.get_data
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Get Errors
|
|
||||||
::: pyasic.miners.base.MinerProtocol.get_errors
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Get Hostname
|
|
||||||
::: pyasic.miners.base.MinerProtocol.get_hostname
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Get Model
|
|
||||||
::: pyasic.miners.base.MinerProtocol.get_model
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Reboot
|
|
||||||
::: pyasic.miners.base.MinerProtocol.reboot
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Restart Backend
|
|
||||||
::: pyasic.miners.base.MinerProtocol.restart_backend
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Stop Mining
|
|
||||||
::: pyasic.miners.base.MinerProtocol.stop_mining
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Resume Mining
|
|
||||||
::: pyasic.miners.base.MinerProtocol.resume_mining
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Is Mining
|
|
||||||
::: pyasic.miners.base.MinerProtocol.is_mining
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Send Config
|
|
||||||
::: pyasic.miners.base.MinerProtocol.send_config
|
|
||||||
handler: python
|
|
||||||
options:
|
|
||||||
heading_level: 4
|
|
||||||
|
|
||||||
### Set Power Limit
|
|
||||||
::: pyasic.miners.base.MinerProtocol.set_power_limit
|
|
||||||
handler: python
|
handler: python
|
||||||
options:
|
options:
|
||||||
heading_level: 4
|
heading_level: 4
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ details {
|
|||||||
<li><a href="../antminer/X9#s9i-stock">S9i (Stock)</a></li>
|
<li><a href="../antminer/X9#s9i-stock">S9i (Stock)</a></li>
|
||||||
<li><a href="../antminer/X9#s9j-stock">S9j (Stock)</a></li>
|
<li><a href="../antminer/X9#s9j-stock">S9j (Stock)</a></li>
|
||||||
<li><a href="../antminer/X9#t9-stock">T9 (Stock)</a></li>
|
<li><a href="../antminer/X9#t9-stock">T9 (Stock)</a></li>
|
||||||
|
<li><a href="../antminer/X9#l9-stock">L9 (Stock)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
@@ -377,6 +378,7 @@ details {
|
|||||||
<details>
|
<details>
|
||||||
<summary>A11X Series:</summary>
|
<summary>A11X Series:</summary>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li><a href="../avalonminer/A11X#avalon-1126-pro-stock">Avalon 1126 Pro (Stock)</a></li>
|
||||||
<li><a href="../avalonminer/A11X#avalon-1166-pro-stock">Avalon 1166 Pro (Stock)</a></li>
|
<li><a href="../avalonminer/A11X#avalon-1166-pro-stock">Avalon 1166 Pro (Stock)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
@@ -531,6 +533,7 @@ details {
|
|||||||
<li><a href="../antminer/X19#s19a-vnish">S19a (VNish)</a></li>
|
<li><a href="../antminer/X19#s19a-vnish">S19a (VNish)</a></li>
|
||||||
<li><a href="../antminer/X19#s19a-pro-vnish">S19a Pro (VNish)</a></li>
|
<li><a href="../antminer/X19#s19a-pro-vnish">S19a Pro (VNish)</a></li>
|
||||||
<li><a href="../antminer/X19#s19-pro-hydro-vnish">S19 Pro Hydro (VNish)</a></li>
|
<li><a href="../antminer/X19#s19-pro-hydro-vnish">S19 Pro Hydro (VNish)</a></li>
|
||||||
|
<li><a href="../antminer/X19#s19k-pro-vnish">S19k Pro (VNish)</a></li>
|
||||||
<li><a href="../antminer/X19#t19-vnish">T19 (VNish)</a></li>
|
<li><a href="../antminer/X19#t19-vnish">T19 (VNish)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
@@ -580,13 +583,14 @@ details {
|
|||||||
<details>
|
<details>
|
||||||
<summary>X9 Series:</summary>
|
<summary>X9 Series:</summary>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="../antminer/X9#t9-stock">T9 (Stock)</a></li>
|
<li><a href="../antminer/X9#t9-hive">T9 (Hive)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
<summary>X19 Series:</summary>
|
<summary>X19 Series:</summary>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="../antminer/X19#s19j-pro-stock">S19j Pro (Stock)</a></li>
|
<li><a href="../antminer/X19#s19j-pro-hive">S19j Pro (Hive)</a></li>
|
||||||
|
<li><a href="../antminer/X19#s19-hive">S19 (Hive)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
jinja2<3.1.4
|
|
||||||
mkdocs
|
|
||||||
mkdocstrings[python]
|
|
||||||
zipp>=3.19.1 # not directly required, pinned by Snyk to avoid a vulnerability
|
|
||||||
33
mkdocs.yml
33
mkdocs.yml
@@ -1,5 +1,34 @@
|
|||||||
site_name: pyasic
|
site_name: pyasic
|
||||||
repo_url: https://github.com/UpstreamData/pyasic
|
repo_url: https://github.com/UpstreamData/pyasic
|
||||||
|
site_url: !ENV SITE_URL
|
||||||
|
theme:
|
||||||
|
name: material
|
||||||
|
features:
|
||||||
|
- content.code.copy
|
||||||
|
- content.code.annotate
|
||||||
|
palette:
|
||||||
|
- media: "(prefers-color-scheme)"
|
||||||
|
toggle:
|
||||||
|
icon: material/brightness-auto
|
||||||
|
name: Switch to light mode
|
||||||
|
- media: "(prefers-color-scheme: light)"
|
||||||
|
scheme: default
|
||||||
|
toggle:
|
||||||
|
icon: material/weather-night
|
||||||
|
name: Switch to dark mode
|
||||||
|
- media: "(prefers-color-scheme: dark)"
|
||||||
|
scheme: slate
|
||||||
|
toggle:
|
||||||
|
icon: material/weather-sunny
|
||||||
|
name: Switch to auto mode
|
||||||
|
markdown_extensions:
|
||||||
|
- pymdownx.highlight:
|
||||||
|
anchor_linenums: true
|
||||||
|
line_spans: __span
|
||||||
|
pygments_lang_class: true
|
||||||
|
- pymdownx.inlinehilite
|
||||||
|
- pymdownx.snippets
|
||||||
|
- pymdownx.superfences
|
||||||
nav:
|
nav:
|
||||||
- Introduction: "index.md"
|
- Introduction: "index.md"
|
||||||
- Miners:
|
- Miners:
|
||||||
@@ -50,6 +79,7 @@ nav:
|
|||||||
- Antminer X17: "miners/antminer/X17.md"
|
- Antminer X17: "miners/antminer/X17.md"
|
||||||
- Antminer X19: "miners/antminer/X19.md"
|
- Antminer X19: "miners/antminer/X19.md"
|
||||||
- Antminer X21: "miners/antminer/X21.md"
|
- Antminer X21: "miners/antminer/X21.md"
|
||||||
|
- Avalon Nano: "miners/avalonminer/nano.md"
|
||||||
- Avalon 7X: "miners/avalonminer/A7X.md"
|
- Avalon 7X: "miners/avalonminer/A7X.md"
|
||||||
- Avalon 8X: "miners/avalonminer/A8X.md"
|
- Avalon 8X: "miners/avalonminer/A8X.md"
|
||||||
- Avalon 9X: "miners/avalonminer/A9X.md"
|
- Avalon 9X: "miners/avalonminer/A9X.md"
|
||||||
@@ -62,6 +92,7 @@ nav:
|
|||||||
- Whatsminer M6X: "miners/whatsminer/M6X.md"
|
- Whatsminer M6X: "miners/whatsminer/M6X.md"
|
||||||
- Innosilicon T3X: "miners/innosilicon/T3X.md"
|
- Innosilicon T3X: "miners/innosilicon/T3X.md"
|
||||||
- Innosilicon A10X: "miners/innosilicon/A10X.md"
|
- Innosilicon A10X: "miners/innosilicon/A10X.md"
|
||||||
|
- Innosilicon A11X: "miners/innosilicon/A11X.md"
|
||||||
- Goldshell X5: "miners/goldshell/X5.md"
|
- Goldshell X5: "miners/goldshell/X5.md"
|
||||||
- Goldshell XMax: "miners/goldshell/XMax.md"
|
- Goldshell XMax: "miners/goldshell/XMax.md"
|
||||||
- Goldshell XBox: "miners/goldshell/XBox.md"
|
- Goldshell XBox: "miners/goldshell/XBox.md"
|
||||||
@@ -70,6 +101,8 @@ nav:
|
|||||||
- Auradine AT: "miners/auradine/AT.md"
|
- Auradine AT: "miners/auradine/AT.md"
|
||||||
- Blockminer: "miners/blockminer/blockminer.md"
|
- Blockminer: "miners/blockminer/blockminer.md"
|
||||||
- BitAxe BM: "miners/bitaxe/BM.md"
|
- BitAxe BM: "miners/bitaxe/BM.md"
|
||||||
|
- Hammer DX: "miners/hammer/DX.md"
|
||||||
|
- Iceriver KSX: "miners/iceriver/KSX.md"
|
||||||
- Base Miner: "miners/base_miner.md"
|
- Base Miner: "miners/base_miner.md"
|
||||||
- Settings:
|
- Settings:
|
||||||
- Settings: "settings/settings.md"
|
- Settings: "settings/settings.md"
|
||||||
|
|||||||
634
poetry.lock
generated
634
poetry.lock
generated
@@ -68,6 +68,20 @@ pkcs11 = ["python-pkcs11 (>=0.7.0)"]
|
|||||||
pyopenssl = ["pyOpenSSL (>=23.0.0)"]
|
pyopenssl = ["pyOpenSSL (>=23.0.0)"]
|
||||||
pywin32 = ["pywin32 (>=227)"]
|
pywin32 = ["pywin32 (>=227)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "babel"
|
||||||
|
version = "2.16.0"
|
||||||
|
description = "Internationalization utilities"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"},
|
||||||
|
{file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "betterproto"
|
name = "betterproto"
|
||||||
version = "2.0.0b7"
|
version = "2.0.0b7"
|
||||||
@@ -189,6 +203,120 @@ files = [
|
|||||||
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
|
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "charset-normalizer"
|
||||||
|
version = "3.4.0"
|
||||||
|
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7.0"
|
||||||
|
files = [
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"},
|
||||||
|
{file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"},
|
||||||
|
{file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"},
|
||||||
|
{file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "click"
|
name = "click"
|
||||||
version = "8.1.7"
|
version = "8.1.7"
|
||||||
@@ -412,13 +540,13 @@ trio = ["trio (>=0.22.0,<1.0)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httpx"
|
name = "httpx"
|
||||||
version = "0.27.2"
|
version = "0.28.0"
|
||||||
description = "The next generation HTTP client."
|
description = "The next generation HTTP client."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"},
|
{file = "httpx-0.28.0-py3-none-any.whl", hash = "sha256:dc0b419a0cfeb6e8b34e85167c0da2671206f5095f1baa9663d23bcfd6b535fc"},
|
||||||
{file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"},
|
{file = "httpx-0.28.0.tar.gz", hash = "sha256:0858d3bab51ba7e386637f22a61d8ccddaeec5f3fe4209da3a6168dbb91573e0"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -426,7 +554,6 @@ anyio = "*"
|
|||||||
certifi = "*"
|
certifi = "*"
|
||||||
httpcore = "==1.*"
|
httpcore = "==1.*"
|
||||||
idna = "*"
|
idna = "*"
|
||||||
sniffio = "*"
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
brotli = ["brotli", "brotlicffi"]
|
brotli = ["brotli", "brotlicffi"]
|
||||||
@@ -448,13 +575,13 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "identify"
|
name = "identify"
|
||||||
version = "2.6.2"
|
version = "2.6.3"
|
||||||
description = "File identification library for Python"
|
description = "File identification library for Python"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
files = [
|
files = [
|
||||||
{file = "identify-2.6.2-py2.py3-none-any.whl", hash = "sha256:c097384259f49e372f4ea00a19719d95ae27dd5ff0fd77ad630aa891306b82f3"},
|
{file = "identify-2.6.3-py2.py3-none-any.whl", hash = "sha256:9edba65473324c2ea9684b1f944fe3191db3345e50b6d04571d10ed164f8d7bd"},
|
||||||
{file = "identify-2.6.2.tar.gz", hash = "sha256:fab5c716c24d7a789775228823797296a2994b075fb6080ac83a102772a98cbd"},
|
{file = "identify-2.6.3.tar.gz", hash = "sha256:62f5dae9b5fef52c84cc188514e9ea4f3f636b1d8799ab5ebc475471f9e47a02"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@@ -692,24 +819,68 @@ platformdirs = ">=2.2.0"
|
|||||||
pyyaml = ">=5.1"
|
pyyaml = ">=5.1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mkdocstrings"
|
name = "mkdocs-material"
|
||||||
version = "0.20.0"
|
version = "9.5.47"
|
||||||
description = "Automatic documentation from sources, for MkDocs."
|
description = "Documentation that simply works"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "mkdocstrings-0.20.0-py3-none-any.whl", hash = "sha256:f17fc2c4f760ec302b069075ef9e31045aa6372ca91d2f35ded3adba8e25a472"},
|
{file = "mkdocs_material-9.5.47-py3-none-any.whl", hash = "sha256:53fb9c9624e7865da6ec807d116cd7be24b3cb36ab31b1d1d1a9af58c56009a2"},
|
||||||
{file = "mkdocstrings-0.20.0.tar.gz", hash = "sha256:c757f4f646d4f939491d6bc9256bfe33e36c5f8026392f49eaa351d241c838e5"},
|
{file = "mkdocs_material-9.5.47.tar.gz", hash = "sha256:fc3b7a8e00ad896660bd3a5cc12ca0cb28bdc2bcbe2a946b5714c23ac91b0ede"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
babel = ">=2.10,<3.0"
|
||||||
|
colorama = ">=0.4,<1.0"
|
||||||
|
jinja2 = ">=3.0,<4.0"
|
||||||
|
markdown = ">=3.2,<4.0"
|
||||||
|
mkdocs = ">=1.6,<2.0"
|
||||||
|
mkdocs-material-extensions = ">=1.3,<2.0"
|
||||||
|
paginate = ">=0.5,<1.0"
|
||||||
|
pygments = ">=2.16,<3.0"
|
||||||
|
pymdown-extensions = ">=10.2,<11.0"
|
||||||
|
regex = ">=2022.4"
|
||||||
|
requests = ">=2.26,<3.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"]
|
||||||
|
imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"]
|
||||||
|
recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mkdocs-material-extensions"
|
||||||
|
version = "1.3.1"
|
||||||
|
description = "Extension pack for Python Markdown and MkDocs Material."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"},
|
||||||
|
{file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mkdocstrings"
|
||||||
|
version = "0.26.2"
|
||||||
|
description = "Automatic documentation from sources, for MkDocs."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "mkdocstrings-0.26.2-py3-none-any.whl", hash = "sha256:1248f3228464f3b8d1a15bd91249ce1701fe3104ac517a5f167a0e01ca850ba5"},
|
||||||
|
{file = "mkdocstrings-0.26.2.tar.gz", hash = "sha256:34a8b50f1e6cfd29546c6c09fbe02154adfb0b361bb758834bf56aa284ba876e"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
click = ">=7.0"
|
||||||
|
importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""}
|
||||||
Jinja2 = ">=2.11.1"
|
Jinja2 = ">=2.11.1"
|
||||||
Markdown = ">=3.3"
|
Markdown = ">=3.6"
|
||||||
MarkupSafe = ">=1.1"
|
MarkupSafe = ">=1.1"
|
||||||
mkdocs = ">=1.2"
|
mkdocs = ">=1.4"
|
||||||
mkdocs-autorefs = ">=0.3.1"
|
mkdocs-autorefs = ">=1.2"
|
||||||
mkdocstrings-python = {version = ">=0.5.2", optional = true, markers = "extra == \"python\""}
|
mkdocstrings-python = {version = ">=0.5.2", optional = true, markers = "extra == \"python\""}
|
||||||
|
platformdirs = ">=2.2"
|
||||||
pymdown-extensions = ">=6.3"
|
pymdown-extensions = ">=6.3"
|
||||||
|
typing-extensions = {version = ">=4.1", markers = "python_version < \"3.10\""}
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
crystal = ["mkdocstrings-crystal (>=0.3.4)"]
|
crystal = ["mkdocstrings-crystal (>=0.3.4)"]
|
||||||
@@ -718,18 +889,19 @@ python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mkdocstrings-python"
|
name = "mkdocstrings-python"
|
||||||
version = "1.8.0"
|
version = "1.12.2"
|
||||||
description = "A Python handler for mkdocstrings."
|
description = "A Python handler for mkdocstrings."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.9"
|
||||||
files = [
|
files = [
|
||||||
{file = "mkdocstrings_python-1.8.0-py3-none-any.whl", hash = "sha256:4209970cc90bec194568682a535848a8d8489516c6ed4adbe58bbc67b699ca9d"},
|
{file = "mkdocstrings_python-1.12.2-py3-none-any.whl", hash = "sha256:7f7d40d6db3cb1f5d19dbcd80e3efe4d0ba32b073272c0c0de9de2e604eda62a"},
|
||||||
{file = "mkdocstrings_python-1.8.0.tar.gz", hash = "sha256:1488bddf50ee42c07d9a488dddc197f8e8999c2899687043ec5dd1643d057192"},
|
{file = "mkdocstrings_python-1.12.2.tar.gz", hash = "sha256:7a1760941c0b52a2cd87b960a9e21112ffe52e7df9d0b9583d04d47ed2e186f3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
griffe = ">=0.37"
|
griffe = ">=0.49"
|
||||||
mkdocstrings = ">=0.20"
|
mkdocs-autorefs = ">=1.2"
|
||||||
|
mkdocstrings = ">=0.26"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "multidict"
|
name = "multidict"
|
||||||
@@ -857,6 +1029,21 @@ files = [
|
|||||||
{file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
|
{file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paginate"
|
||||||
|
version = "0.5.7"
|
||||||
|
description = "Divides large result sets into pages for easier browsing"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591"},
|
||||||
|
{file = "paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["pytest", "tox"]
|
||||||
|
lint = ["black"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "passlib"
|
name = "passlib"
|
||||||
version = "1.7.4"
|
version = "1.7.4"
|
||||||
@@ -949,22 +1136,19 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pydantic"
|
name = "pydantic"
|
||||||
version = "2.9.2"
|
version = "2.10.3"
|
||||||
description = "Data validation using Python type hints"
|
description = "Data validation using Python type hints"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"},
|
{file = "pydantic-2.10.3-py3-none-any.whl", hash = "sha256:be04d85bbc7b65651c5f8e6b9976ed9c6f41782a55524cef079a34a0bb82144d"},
|
||||||
{file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"},
|
{file = "pydantic-2.10.3.tar.gz", hash = "sha256:cb5ac360ce894ceacd69c403187900a02c4b20b693a9dd1d643e1effab9eadf9"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
annotated-types = ">=0.6.0"
|
annotated-types = ">=0.6.0"
|
||||||
pydantic-core = "2.23.4"
|
pydantic-core = "2.27.1"
|
||||||
typing-extensions = [
|
typing-extensions = ">=4.12.2"
|
||||||
{version = ">=4.12.2", markers = "python_version >= \"3.13\""},
|
|
||||||
{version = ">=4.6.1", markers = "python_version < \"3.13\""},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
email = ["email-validator (>=2.0.0)"]
|
email = ["email-validator (>=2.0.0)"]
|
||||||
@@ -972,105 +1156,130 @@ timezone = ["tzdata"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pydantic-core"
|
name = "pydantic-core"
|
||||||
version = "2.23.4"
|
version = "2.27.1"
|
||||||
description = "Core functionality for Pydantic validation and serialization"
|
description = "Core functionality for Pydantic validation and serialization"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b"},
|
{file = "pydantic_core-2.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:71a5e35c75c021aaf400ac048dacc855f000bdfed91614b4a726f7432f1f3d6a"},
|
||||||
{file = "pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166"},
|
{file = "pydantic_core-2.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f82d068a2d6ecfc6e054726080af69a6764a10015467d7d7b9f66d6ed5afa23b"},
|
||||||
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb"},
|
{file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:121ceb0e822f79163dd4699e4c54f5ad38b157084d97b34de8b232bcaad70278"},
|
||||||
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916"},
|
{file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4603137322c18eaf2e06a4495f426aa8d8388940f3c457e7548145011bb68e05"},
|
||||||
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07"},
|
{file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a33cd6ad9017bbeaa9ed78a2e0752c5e250eafb9534f308e7a5f7849b0b1bfb4"},
|
||||||
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232"},
|
{file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15cc53a3179ba0fcefe1e3ae50beb2784dede4003ad2dfd24f81bba4b23a454f"},
|
||||||
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2"},
|
{file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45d9c5eb9273aa50999ad6adc6be5e0ecea7e09dbd0d31bd0c65a55a2592ca08"},
|
||||||
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f"},
|
{file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8bf7b66ce12a2ac52d16f776b31d16d91033150266eb796967a7e4621707e4f6"},
|
||||||
{file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3"},
|
{file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:655d7dd86f26cb15ce8a431036f66ce0318648f8853d709b4167786ec2fa4807"},
|
||||||
{file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071"},
|
{file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:5556470f1a2157031e676f776c2bc20acd34c1990ca5f7e56f1ebf938b9ab57c"},
|
||||||
{file = "pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119"},
|
{file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f69ed81ab24d5a3bd93861c8c4436f54afdf8e8cc421562b0c7504cf3be58206"},
|
||||||
{file = "pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f"},
|
{file = "pydantic_core-2.27.1-cp310-none-win32.whl", hash = "sha256:f5a823165e6d04ccea61a9f0576f345f8ce40ed533013580e087bd4d7442b52c"},
|
||||||
{file = "pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8"},
|
{file = "pydantic_core-2.27.1-cp310-none-win_amd64.whl", hash = "sha256:57866a76e0b3823e0b56692d1a0bf722bffb324839bb5b7226a7dbd6c9a40b17"},
|
||||||
{file = "pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d"},
|
{file = "pydantic_core-2.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac3b20653bdbe160febbea8aa6c079d3df19310d50ac314911ed8cc4eb7f8cb8"},
|
||||||
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e"},
|
{file = "pydantic_core-2.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a5a8e19d7c707c4cadb8c18f5f60c843052ae83c20fa7d44f41594c644a1d330"},
|
||||||
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607"},
|
{file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f7059ca8d64fea7f238994c97d91f75965216bcbe5f695bb44f354893f11d52"},
|
||||||
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd"},
|
{file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bed0f8a0eeea9fb72937ba118f9db0cb7e90773462af7962d382445f3005e5a4"},
|
||||||
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea"},
|
{file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3cb37038123447cf0f3ea4c74751f6a9d7afef0eb71aa07bf5f652b5e6a132c"},
|
||||||
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e"},
|
{file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84286494f6c5d05243456e04223d5a9417d7f443c3b76065e75001beb26f88de"},
|
||||||
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b"},
|
{file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acc07b2cfc5b835444b44a9956846b578d27beeacd4b52e45489e93276241025"},
|
||||||
{file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0"},
|
{file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4fefee876e07a6e9aad7a8c8c9f85b0cdbe7df52b8a9552307b09050f7512c7e"},
|
||||||
{file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64"},
|
{file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:258c57abf1188926c774a4c94dd29237e77eda19462e5bb901d88adcab6af919"},
|
||||||
{file = "pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f"},
|
{file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:35c14ac45fcfdf7167ca76cc80b2001205a8d5d16d80524e13508371fb8cdd9c"},
|
||||||
{file = "pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3"},
|
{file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d1b26e1dff225c31897696cab7d4f0a315d4c0d9e8666dbffdb28216f3b17fdc"},
|
||||||
{file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"},
|
{file = "pydantic_core-2.27.1-cp311-none-win32.whl", hash = "sha256:2cdf7d86886bc6982354862204ae3b2f7f96f21a3eb0ba5ca0ac42c7b38598b9"},
|
||||||
{file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"},
|
{file = "pydantic_core-2.27.1-cp311-none-win_amd64.whl", hash = "sha256:3af385b0cee8df3746c3f406f38bcbfdc9041b5c2d5ce3e5fc6637256e60bbc5"},
|
||||||
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"},
|
{file = "pydantic_core-2.27.1-cp311-none-win_arm64.whl", hash = "sha256:81f2ec23ddc1b476ff96563f2e8d723830b06dceae348ce02914a37cb4e74b89"},
|
||||||
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"},
|
{file = "pydantic_core-2.27.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9cbd94fc661d2bab2bc702cddd2d3370bbdcc4cd0f8f57488a81bcce90c7a54f"},
|
||||||
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"},
|
{file = "pydantic_core-2.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5f8c4718cd44ec1580e180cb739713ecda2bdee1341084c1467802a417fe0f02"},
|
||||||
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"},
|
{file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15aae984e46de8d376df515f00450d1522077254ef6b7ce189b38ecee7c9677c"},
|
||||||
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"},
|
{file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ba5e3963344ff25fc8c40da90f44b0afca8cfd89d12964feb79ac1411a260ac"},
|
||||||
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"},
|
{file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:992cea5f4f3b29d6b4f7f1726ed8ee46c8331c6b4eed6db5b40134c6fe1768bb"},
|
||||||
{file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"},
|
{file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0325336f348dbee6550d129b1627cb8f5351a9dc91aad141ffb96d4937bd9529"},
|
||||||
{file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"},
|
{file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7597c07fbd11515f654d6ece3d0e4e5093edc30a436c63142d9a4b8e22f19c35"},
|
||||||
{file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"},
|
{file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3bbd5d8cc692616d5ef6fbbbd50dbec142c7e6ad9beb66b78a96e9c16729b089"},
|
||||||
{file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"},
|
{file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:dc61505e73298a84a2f317255fcc72b710b72980f3a1f670447a21efc88f8381"},
|
||||||
{file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"},
|
{file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:e1f735dc43da318cad19b4173dd1ffce1d84aafd6c9b782b3abc04a0d5a6f5bb"},
|
||||||
{file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"},
|
{file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f4e5658dbffe8843a0f12366a4c2d1c316dbe09bb4dfbdc9d2d9cd6031de8aae"},
|
||||||
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"},
|
{file = "pydantic_core-2.27.1-cp312-none-win32.whl", hash = "sha256:672ebbe820bb37988c4d136eca2652ee114992d5d41c7e4858cdd90ea94ffe5c"},
|
||||||
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"},
|
{file = "pydantic_core-2.27.1-cp312-none-win_amd64.whl", hash = "sha256:66ff044fd0bb1768688aecbe28b6190f6e799349221fb0de0e6f4048eca14c16"},
|
||||||
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"},
|
{file = "pydantic_core-2.27.1-cp312-none-win_arm64.whl", hash = "sha256:9a3b0793b1bbfd4146304e23d90045f2a9b5fd5823aa682665fbdaf2a6c28f3e"},
|
||||||
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"},
|
{file = "pydantic_core-2.27.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f216dbce0e60e4d03e0c4353c7023b202d95cbaeff12e5fd2e82ea0a66905073"},
|
||||||
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"},
|
{file = "pydantic_core-2.27.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a2e02889071850bbfd36b56fd6bc98945e23670773bc7a76657e90e6b6603c08"},
|
||||||
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"},
|
{file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b0e23f119b2b456d07ca91b307ae167cc3f6c846a7b169fca5326e32fdc6cf"},
|
||||||
{file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"},
|
{file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:764be71193f87d460a03f1f7385a82e226639732214b402f9aa61f0d025f0737"},
|
||||||
{file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"},
|
{file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c00666a3bd2f84920a4e94434f5974d7bbc57e461318d6bb34ce9cdbbc1f6b2"},
|
||||||
{file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"},
|
{file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ccaa88b24eebc0f849ce0a4d09e8a408ec5a94afff395eb69baf868f5183107"},
|
||||||
{file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"},
|
{file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c65af9088ac534313e1963443d0ec360bb2b9cba6c2909478d22c2e363d98a51"},
|
||||||
{file = "pydantic_core-2.23.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d4488a93b071c04dc20f5cecc3631fc78b9789dd72483ba15d423b5b3689b555"},
|
{file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:206b5cf6f0c513baffaeae7bd817717140770c74528f3e4c3e1cec7871ddd61a"},
|
||||||
{file = "pydantic_core-2.23.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:81965a16b675b35e1d09dd14df53f190f9129c0202356ed44ab2728b1c905658"},
|
{file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:062f60e512fc7fff8b8a9d680ff0ddaaef0193dba9fa83e679c0c5f5fbd018bc"},
|
||||||
{file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffa2ebd4c8530079140dd2d7f794a9d9a73cbb8e9d59ffe24c63436efa8f271"},
|
{file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:a0697803ed7d4af5e4c1adf1670af078f8fcab7a86350e969f454daf598c4960"},
|
||||||
{file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61817945f2fe7d166e75fbfb28004034b48e44878177fc54d81688e7b85a3665"},
|
{file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:58ca98a950171f3151c603aeea9303ef6c235f692fe555e883591103da709b23"},
|
||||||
{file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d2c342c4bc01b88402d60189f3df065fb0dda3654744d5a165a5288a657368"},
|
{file = "pydantic_core-2.27.1-cp313-none-win32.whl", hash = "sha256:8065914ff79f7eab1599bd80406681f0ad08f8e47c880f17b416c9f8f7a26d05"},
|
||||||
{file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e11661ce0fd30a6790e8bcdf263b9ec5988e95e63cf901972107efc49218b13"},
|
{file = "pydantic_core-2.27.1-cp313-none-win_amd64.whl", hash = "sha256:ba630d5e3db74c79300d9a5bdaaf6200172b107f263c98a0539eeecb857b2337"},
|
||||||
{file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d18368b137c6295db49ce7218b1a9ba15c5bc254c96d7c9f9e924a9bc7825ad"},
|
{file = "pydantic_core-2.27.1-cp313-none-win_arm64.whl", hash = "sha256:45cf8588c066860b623cd11c4ba687f8d7175d5f7ef65f7129df8a394c502de5"},
|
||||||
{file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec4e55f79b1c4ffb2eecd8a0cfba9955a2588497d96851f4c8f99aa4a1d39b12"},
|
{file = "pydantic_core-2.27.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:5897bec80a09b4084aee23f9b73a9477a46c3304ad1d2d07acca19723fb1de62"},
|
||||||
{file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:374a5e5049eda9e0a44c696c7ade3ff355f06b1fe0bb945ea3cac2bc336478a2"},
|
{file = "pydantic_core-2.27.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d0165ab2914379bd56908c02294ed8405c252250668ebcb438a55494c69f44ab"},
|
||||||
{file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5c364564d17da23db1106787675fc7af45f2f7b58b4173bfdd105564e132e6fb"},
|
{file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b9af86e1d8e4cfc82c2022bfaa6f459381a50b94a29e95dcdda8442d6d83864"},
|
||||||
{file = "pydantic_core-2.23.4-cp38-none-win32.whl", hash = "sha256:d7a80d21d613eec45e3d41eb22f8f94ddc758a6c4720842dc74c0581f54993d6"},
|
{file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f6c8a66741c5f5447e047ab0ba7a1c61d1e95580d64bce852e3df1f895c4067"},
|
||||||
{file = "pydantic_core-2.23.4-cp38-none-win_amd64.whl", hash = "sha256:5f5ff8d839f4566a474a969508fe1c5e59c31c80d9e140566f9a37bba7b8d556"},
|
{file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a42d6a8156ff78981f8aa56eb6394114e0dedb217cf8b729f438f643608cbcd"},
|
||||||
{file = "pydantic_core-2.23.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a4fa4fc04dff799089689f4fd502ce7d59de529fc2f40a2c8836886c03e0175a"},
|
{file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64c65f40b4cd8b0e049a8edde07e38b476da7e3aaebe63287c899d2cff253fa5"},
|
||||||
{file = "pydantic_core-2.23.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a7df63886be5e270da67e0966cf4afbae86069501d35c8c1b3b6c168f42cb36"},
|
{file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdcf339322a3fae5cbd504edcefddd5a50d9ee00d968696846f089b4432cf78"},
|
||||||
{file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcedcd19a557e182628afa1d553c3895a9f825b936415d0dbd3cd0bbcfd29b4b"},
|
{file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bf99c8404f008750c846cb4ac4667b798a9f7de673ff719d705d9b2d6de49c5f"},
|
||||||
{file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f54b118ce5de9ac21c363d9b3caa6c800341e8c47a508787e5868c6b79c9323"},
|
{file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8f1edcea27918d748c7e5e4d917297b2a0ab80cad10f86631e488b7cddf76a36"},
|
||||||
{file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d2f57d3e1379a9525c5ab067b27dbb8a0642fb5d454e17a9ac434f9ce523e3"},
|
{file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:159cac0a3d096f79ab6a44d77a961917219707e2a130739c64d4dd46281f5c2a"},
|
||||||
{file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de6d1d1b9e5101508cb37ab0d972357cac5235f5c6533d1071964c47139257df"},
|
{file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:029d9757eb621cc6e1848fa0b0310310de7301057f623985698ed7ebb014391b"},
|
||||||
{file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1278e0d324f6908e872730c9102b0112477a7f7cf88b308e4fc36ce1bdb6d58c"},
|
{file = "pydantic_core-2.27.1-cp38-none-win32.whl", hash = "sha256:a28af0695a45f7060e6f9b7092558a928a28553366519f64083c63a44f70e618"},
|
||||||
{file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a6b5099eeec78827553827f4c6b8615978bb4b6a88e5d9b93eddf8bb6790f55"},
|
{file = "pydantic_core-2.27.1-cp38-none-win_amd64.whl", hash = "sha256:2d4567c850905d5eaaed2f7a404e61012a51caf288292e016360aa2b96ff38d4"},
|
||||||
{file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e55541f756f9b3ee346b840103f32779c695a19826a4c442b7954550a0972040"},
|
{file = "pydantic_core-2.27.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e9386266798d64eeb19dd3677051f5705bf873e98e15897ddb7d76f477131967"},
|
||||||
{file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c7ba8ffb6d6f8f2ab08743be203654bb1aaa8c9dcb09f82ddd34eadb695605"},
|
{file = "pydantic_core-2.27.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4228b5b646caa73f119b1ae756216b59cc6e2267201c27d3912b592c5e323b60"},
|
||||||
{file = "pydantic_core-2.23.4-cp39-none-win32.whl", hash = "sha256:37b0fe330e4a58d3c58b24d91d1eb102aeec675a3db4c292ec3928ecd892a9a6"},
|
{file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3dfe500de26c52abe0477dde16192ac39c98f05bf2d80e76102d394bd13854"},
|
||||||
{file = "pydantic_core-2.23.4-cp39-none-win_amd64.whl", hash = "sha256:1498bec4c05c9c787bde9125cfdcc63a41004ff167f495063191b863399b1a29"},
|
{file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aee66be87825cdf72ac64cb03ad4c15ffef4143dbf5c113f64a5ff4f81477bf9"},
|
||||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5"},
|
{file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b748c44bb9f53031c8cbc99a8a061bc181c1000c60a30f55393b6e9c45cc5bd"},
|
||||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec"},
|
{file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ca038c7f6a0afd0b2448941b6ef9d5e1949e999f9e5517692eb6da58e9d44be"},
|
||||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480"},
|
{file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e0bd57539da59a3e4671b90a502da9a28c72322a4f17866ba3ac63a82c4498e"},
|
||||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068"},
|
{file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ac6c2c45c847bbf8f91930d88716a0fb924b51e0c6dad329b793d670ec5db792"},
|
||||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801"},
|
{file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b94d4ba43739bbe8b0ce4262bcc3b7b9f31459ad120fb595627eaeb7f9b9ca01"},
|
||||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728"},
|
{file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:00e6424f4b26fe82d44577b4c842d7df97c20be6439e8e685d0d715feceb9fb9"},
|
||||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433"},
|
{file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:38de0a70160dd97540335b7ad3a74571b24f1dc3ed33f815f0880682e6880131"},
|
||||||
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753"},
|
{file = "pydantic_core-2.27.1-cp39-none-win32.whl", hash = "sha256:7ccebf51efc61634f6c2344da73e366c75e735960b5654b63d7e6f69a5885fa3"},
|
||||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:78ddaaa81421a29574a682b3179d4cf9e6d405a09b99d93ddcf7e5239c742e21"},
|
{file = "pydantic_core-2.27.1-cp39-none-win_amd64.whl", hash = "sha256:a57847b090d7892f123726202b7daa20df6694cbd583b67a592e856bff603d6c"},
|
||||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:883a91b5dd7d26492ff2f04f40fbb652de40fcc0afe07e8129e8ae779c2110eb"},
|
{file = "pydantic_core-2.27.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3fa80ac2bd5856580e242dbc202db873c60a01b20309c8319b5c5986fbe53ce6"},
|
||||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88ad334a15b32a791ea935af224b9de1bf99bcd62fabf745d5f3442199d86d59"},
|
{file = "pydantic_core-2.27.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d950caa237bb1954f1b8c9227b5065ba6875ac9771bb8ec790d956a699b78676"},
|
||||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:233710f069d251feb12a56da21e14cca67994eab08362207785cf8c598e74577"},
|
{file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e4216e64d203e39c62df627aa882f02a2438d18a5f21d7f721621f7a5d3611d"},
|
||||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19442362866a753485ba5e4be408964644dd6a09123d9416c54cd49171f50744"},
|
{file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02a3d637bd387c41d46b002f0e49c52642281edacd2740e5a42f7017feea3f2c"},
|
||||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:624e278a7d29b6445e4e813af92af37820fafb6dcc55c012c834f9e26f9aaaef"},
|
{file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:161c27ccce13b6b0c8689418da3885d3220ed2eae2ea5e9b2f7f3d48f1d52c27"},
|
||||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f5ef8f42bec47f21d07668a043f077d507e5bf4e668d5c6dfe6aaba89de1a5b8"},
|
{file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:19910754e4cc9c63bc1c7f6d73aa1cfee82f42007e407c0f413695c2f7ed777f"},
|
||||||
{file = "pydantic_core-2.23.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:aea443fffa9fbe3af1a9ba721a87f926fe548d32cab71d188a6ede77d0ff244e"},
|
{file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:e173486019cc283dc9778315fa29a363579372fe67045e971e89b6365cc035ed"},
|
||||||
{file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"},
|
{file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:af52d26579b308921b73b956153066481f064875140ccd1dfd4e77db89dbb12f"},
|
||||||
|
{file = "pydantic_core-2.27.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:981fb88516bd1ae8b0cbbd2034678a39dedc98752f264ac9bc5839d3923fa04c"},
|
||||||
|
{file = "pydantic_core-2.27.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5fde892e6c697ce3e30c61b239330fc5d569a71fefd4eb6512fc6caec9dd9e2f"},
|
||||||
|
{file = "pydantic_core-2.27.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:816f5aa087094099fff7edabb5e01cc370eb21aa1a1d44fe2d2aefdfb5599b31"},
|
||||||
|
{file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c10c309e18e443ddb108f0ef64e8729363adbfd92d6d57beec680f6261556f3"},
|
||||||
|
{file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98476c98b02c8e9b2eec76ac4156fd006628b1b2d0ef27e548ffa978393fd154"},
|
||||||
|
{file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c3027001c28434e7ca5a6e1e527487051136aa81803ac812be51802150d880dd"},
|
||||||
|
{file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7699b1df36a48169cdebda7ab5a2bac265204003f153b4bd17276153d997670a"},
|
||||||
|
{file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1c39b07d90be6b48968ddc8c19e7585052088fd7ec8d568bb31ff64c70ae3c97"},
|
||||||
|
{file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:46ccfe3032b3915586e469d4972973f893c0a2bb65669194a5bdea9bacc088c2"},
|
||||||
|
{file = "pydantic_core-2.27.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:62ba45e21cf6571d7f716d903b5b7b6d2617e2d5d67c0923dc47b9d41369f840"},
|
||||||
|
{file = "pydantic_core-2.27.1.tar.gz", hash = "sha256:62a763352879b84aa31058fc931884055fd75089cccbd9d58bb6afd01141b235"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pygments"
|
||||||
|
version = "2.18.0"
|
||||||
|
description = "Pygments is a syntax highlighting package written in Python."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
|
||||||
|
{file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
windows-terminal = ["colorama (>=0.4.6)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pymdown-extensions"
|
name = "pymdown-extensions"
|
||||||
version = "10.12"
|
version = "10.12"
|
||||||
@@ -1179,6 +1388,130 @@ files = [
|
|||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
pyyaml = "*"
|
pyyaml = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "2024.11.6"
|
||||||
|
description = "Alternative regular expression module, to replace re."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-win32.whl", hash = "sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e"},
|
||||||
|
{file = "regex-2024.11.6-cp310-cp310-win_amd64.whl", hash = "sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"},
|
||||||
|
{file = "regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"},
|
||||||
|
{file = "regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff"},
|
||||||
|
{file = "regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-win32.whl", hash = "sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4"},
|
||||||
|
{file = "regex-2024.11.6-cp38-cp38-win_amd64.whl", hash = "sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-win32.whl", hash = "sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57"},
|
||||||
|
{file = "regex-2024.11.6-cp39-cp39-win_amd64.whl", hash = "sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983"},
|
||||||
|
{file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "requests"
|
||||||
|
version = "2.32.3"
|
||||||
|
description = "Python HTTP for Humans."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
|
||||||
|
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
certifi = ">=2017.4.17"
|
||||||
|
charset-normalizer = ">=2,<4"
|
||||||
|
idna = ">=2.5,<4"
|
||||||
|
urllib3 = ">=1.21.1,<3"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||||
|
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "six"
|
name = "six"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
@@ -1203,13 +1536,43 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tomli"
|
name = "tomli"
|
||||||
version = "2.1.0"
|
version = "2.2.1"
|
||||||
description = "A lil' TOML parser"
|
description = "A lil' TOML parser"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "tomli-2.1.0-py3-none-any.whl", hash = "sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391"},
|
{file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
|
||||||
{file = "tomli-2.1.0.tar.gz", hash = "sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8"},
|
{file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"},
|
||||||
|
{file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"},
|
||||||
|
{file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1234,15 +1597,32 @@ files = [
|
|||||||
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "urllib3"
|
||||||
|
version = "2.2.3"
|
||||||
|
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"},
|
||||||
|
{file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
|
||||||
|
h2 = ["h2 (>=4,<5)"]
|
||||||
|
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||||
|
zstd = ["zstandard (>=0.18.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtualenv"
|
name = "virtualenv"
|
||||||
version = "20.27.1"
|
version = "20.28.0"
|
||||||
description = "Virtual Python Environment builder"
|
description = "Virtual Python Environment builder"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "virtualenv-20.27.1-py3-none-any.whl", hash = "sha256:f11f1b8a29525562925f745563bfd48b189450f61fb34c4f9cc79dd5aa32a1f4"},
|
{file = "virtualenv-20.28.0-py3-none-any.whl", hash = "sha256:23eae1b4516ecd610481eda647f3a7c09aea295055337331bb4e6892ecce47b0"},
|
||||||
{file = "virtualenv-20.27.1.tar.gz", hash = "sha256:142c6be10212543b32c6c45d3d3893dff89112cc588b7d0879ae5a1ec03a47ba"},
|
{file = "virtualenv-20.28.0.tar.gz", hash = "sha256:2c9c3262bb8e7b87ea801d715fae4495e6032450c71d2309be9550e7364049aa"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -1318,4 +1698,4 @@ type = ["pytest-mypy"]
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.9"
|
python-versions = "^3.9"
|
||||||
content-hash = "0ae7d5fe3858e93c8a8715b11876be854ce8bf39685316ca1bee759bf0896ce6"
|
content-hash = "c0aa00dd5f3b52bbac53eb765be2bca2ec7f9429e835d6b2fe6bf207f2f39974"
|
||||||
|
|||||||
@@ -245,13 +245,13 @@ class MinerConfig(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_vnish(cls, web_settings: dict) -> "MinerConfig":
|
def from_vnish(cls, web_settings: dict, web_presets: list[dict]) -> "MinerConfig":
|
||||||
"""Constructs a MinerConfig object from web settings for VNish miners."""
|
"""Constructs a MinerConfig object from web settings for VNish miners."""
|
||||||
return cls(
|
return cls(
|
||||||
pools=PoolConfig.from_vnish(web_settings),
|
pools=PoolConfig.from_vnish(web_settings),
|
||||||
fan_mode=FanModeConfig.from_vnish(web_settings),
|
fan_mode=FanModeConfig.from_vnish(web_settings),
|
||||||
temperature=TemperatureConfig.from_vnish(web_settings),
|
temperature=TemperatureConfig.from_vnish(web_settings),
|
||||||
mining_mode=MiningModeConfig.from_vnish(web_settings),
|
mining_mode=MiningModeConfig.from_vnish(web_settings, web_presets),
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -299,3 +299,7 @@ class MinerConfig(BaseModel):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def from_hammer(cls, *args, **kwargs) -> "MinerConfig":
|
def from_hammer(cls, *args, **kwargs) -> "MinerConfig":
|
||||||
return cls.from_am_modern(*args, **kwargs)
|
return cls.from_am_modern(*args, **kwargs)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_hiveon_modern(cls, web_conf: dict) -> "MinerConfig":
|
||||||
|
return cls.from_am_modern(web_conf)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ from pyasic.web.braiins_os.proto.braiins.bos.v1 import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from .algo import TunerAlgo, TunerAlgoType
|
from .algo import TunerAlgo, TunerAlgoType
|
||||||
|
from .presets import MiningPreset
|
||||||
from .scaling import ScalingConfig
|
from .scaling import ScalingConfig
|
||||||
|
|
||||||
|
|
||||||
@@ -251,9 +252,9 @@ class MiningModeHashrateTune(MinerConfigValue):
|
|||||||
arbitrary_types_allowed = True
|
arbitrary_types_allowed = True
|
||||||
|
|
||||||
mode: str = field(init=False, default="hashrate_tuning")
|
mode: str = field(init=False, default="hashrate_tuning")
|
||||||
hashrate: int = None
|
hashrate: int | None = None
|
||||||
algo: TunerAlgoType = field(default_factory=TunerAlgo.default)
|
algo: TunerAlgoType = field(default_factory=TunerAlgo.default)
|
||||||
scaling: ScalingConfig = None
|
scaling: ScalingConfig | None = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, dict_conf: dict | None) -> "MiningModeHashrateTune":
|
def from_dict(cls, dict_conf: dict | None) -> "MiningModeHashrateTune":
|
||||||
@@ -344,6 +345,29 @@ class MiningModeHashrateTune(MinerConfigValue):
|
|||||||
return {"autotunerset": {"enabled": True}}
|
return {"autotunerset": {"enabled": True}}
|
||||||
|
|
||||||
|
|
||||||
|
class MiningModePreset(MinerConfigValue):
|
||||||
|
mode: str = field(init=False, default="preset")
|
||||||
|
|
||||||
|
active_preset: MiningPreset
|
||||||
|
available_presets: list[MiningPreset] = field(default_factory=list)
|
||||||
|
|
||||||
|
def as_vnish(self) -> dict:
|
||||||
|
return {"overclock": {**self.active_preset.as_vnish()}}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_vnish(
|
||||||
|
cls, web_overclock_settings: dict, web_presets: list[dict]
|
||||||
|
) -> "MiningModePreset":
|
||||||
|
active_preset = None
|
||||||
|
for preset in web_presets:
|
||||||
|
if preset["name"] == web_overclock_settings["preset"]:
|
||||||
|
active_preset = preset
|
||||||
|
return cls(
|
||||||
|
active_preset=MiningPreset.from_vnish(active_preset),
|
||||||
|
available_presets=[MiningPreset.from_vnish(p) for p in web_presets],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ManualBoardSettings(MinerConfigValue):
|
class ManualBoardSettings(MinerConfigValue):
|
||||||
freq: float
|
freq: float
|
||||||
volt: float
|
volt: float
|
||||||
@@ -382,9 +406,15 @@ class MiningModeManual(MinerConfigValue):
|
|||||||
return {"miner-mode": 0}
|
return {"miner-mode": 0}
|
||||||
|
|
||||||
def as_vnish(self) -> dict:
|
def as_vnish(self) -> dict:
|
||||||
|
chains = [b.as_vnish() for b in self.boards.values() if b.freq != 0]
|
||||||
return {
|
return {
|
||||||
"chains": [b.as_vnish() for b in self.boards.values() if b.freq != 0],
|
"overclock": {
|
||||||
"globals": {"freq": self.global_freq, "volt": self.global_volt},
|
"chains": chains if chains != [] else None,
|
||||||
|
"globals": {
|
||||||
|
"freq": int(self.global_freq),
|
||||||
|
"volt": int(self.global_volt),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -438,6 +468,7 @@ class MiningModeConfig(MinerConfigOption):
|
|||||||
sleep = MiningModeSleep
|
sleep = MiningModeSleep
|
||||||
power_tuning = MiningModePowerTune
|
power_tuning = MiningModePowerTune
|
||||||
hashrate_tuning = MiningModeHashrateTune
|
hashrate_tuning = MiningModeHashrateTune
|
||||||
|
preset = MiningModePreset
|
||||||
manual = MiningModeManual
|
manual = MiningModeManual
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -555,7 +586,7 @@ class MiningModeConfig(MinerConfigOption):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_vnish(cls, web_settings: dict):
|
def from_vnish(cls, web_settings: dict, web_presets: list[dict]):
|
||||||
try:
|
try:
|
||||||
mode_settings = web_settings["miner"]["overclock"]
|
mode_settings = web_settings["miner"]["overclock"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@@ -564,7 +595,7 @@ class MiningModeConfig(MinerConfigOption):
|
|||||||
if mode_settings["preset"] == "disabled":
|
if mode_settings["preset"] == "disabled":
|
||||||
return MiningModeManual.from_vnish(mode_settings)
|
return MiningModeManual.from_vnish(mode_settings)
|
||||||
else:
|
else:
|
||||||
return cls.power_tuning(power=int(mode_settings["preset"]))
|
return MiningModePreset.from_vnish(mode_settings, web_presets)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_boser(cls, grpc_miner_conf: dict):
|
def from_boser(cls, grpc_miner_conf: dict):
|
||||||
@@ -667,5 +698,6 @@ MiningMode = TypeVar(
|
|||||||
MiningModeManual,
|
MiningModeManual,
|
||||||
MiningModePowerTune,
|
MiningModePowerTune,
|
||||||
MiningModeHashrateTune,
|
MiningModeHashrateTune,
|
||||||
|
MiningModePreset,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
34
pyasic/config/mining/presets.py
Normal file
34
pyasic/config/mining/presets.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
from pyasic.config.base import MinerConfigValue
|
||||||
|
|
||||||
|
|
||||||
|
class MiningPreset(MinerConfigValue):
|
||||||
|
name: str | None = None
|
||||||
|
power: int | None = None
|
||||||
|
hashrate: int | None = None
|
||||||
|
tuned: bool | None = None
|
||||||
|
modded_psu: bool = False
|
||||||
|
|
||||||
|
def as_vnish(self) -> dict:
|
||||||
|
if self.name is not None:
|
||||||
|
return {"preset": self.name}
|
||||||
|
return {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_vnish(cls, web_preset: dict):
|
||||||
|
name = web_preset["name"]
|
||||||
|
hr_power_split = web_preset["pretty"].split("~")
|
||||||
|
if len(hr_power_split) == 1:
|
||||||
|
power = None
|
||||||
|
hashrate = None
|
||||||
|
else:
|
||||||
|
power = hr_power_split[0].replace("watt", "").strip()
|
||||||
|
hashrate = hr_power_split[1].replace("TH", "").replace(" LC", "").strip()
|
||||||
|
tuned = web_preset["status"] == "tuned"
|
||||||
|
modded_psu = web_preset["modded_psu_required"]
|
||||||
|
return cls(
|
||||||
|
name=name,
|
||||||
|
power=power,
|
||||||
|
hashrate=hashrate,
|
||||||
|
tuned=tuned,
|
||||||
|
modded_psu=modded_psu,
|
||||||
|
)
|
||||||
@@ -36,124 +36,93 @@ class Pool(MinerConfigValue):
|
|||||||
user: str
|
user: str
|
||||||
password: str
|
password: str
|
||||||
|
|
||||||
def as_am_modern(self, user_suffix: str = None) -> dict:
|
def as_am_modern(self, user_suffix: str | None = None) -> dict:
|
||||||
if user_suffix is not None:
|
return {
|
||||||
return {
|
"url": self.url,
|
||||||
"url": self.url,
|
"user": f"{self.user}{user_suffix or ''}",
|
||||||
"user": f"{self.user}{user_suffix}",
|
"pass": self.password,
|
||||||
"pass": self.password,
|
}
|
||||||
}
|
|
||||||
return {"url": self.url, "user": self.user, "pass": self.password}
|
|
||||||
|
|
||||||
def as_wm(self, idx: int = 1, user_suffix: str = None) -> dict:
|
def as_wm(self, idx: int = 1, user_suffix: str | None = None) -> dict:
|
||||||
if user_suffix is not None:
|
|
||||||
return {
|
|
||||||
f"pool_{idx}": self.url,
|
|
||||||
f"worker_{idx}": f"{self.user}{user_suffix}",
|
|
||||||
f"passwd_{idx}": self.password,
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
f"pool_{idx}": self.url,
|
f"pool_{idx}": self.url,
|
||||||
f"worker_{idx}": self.user,
|
f"worker_{idx}": f"{self.user}{user_suffix or ''}",
|
||||||
f"passwd_{idx}": self.password,
|
f"passwd_{idx}": self.password,
|
||||||
}
|
}
|
||||||
|
|
||||||
def as_am_old(self, idx: int = 1, user_suffix: str = None) -> dict:
|
def as_am_old(self, idx: int = 1, user_suffix: str | None = None) -> dict:
|
||||||
if user_suffix is not None:
|
|
||||||
return {
|
|
||||||
f"_ant_pool{idx}url": self.url,
|
|
||||||
f"_ant_pool{idx}user": f"{self.user}{user_suffix}",
|
|
||||||
f"_ant_pool{idx}pw": self.password,
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
f"_ant_pool{idx}url": self.url,
|
f"_ant_pool{idx}url": self.url,
|
||||||
f"_ant_pool{idx}user": self.user,
|
f"_ant_pool{idx}user": f"{self.user}{user_suffix or ''}",
|
||||||
f"_ant_pool{idx}pw": self.password,
|
f"_ant_pool{idx}pw": self.password,
|
||||||
}
|
}
|
||||||
|
|
||||||
def as_goldshell(self, user_suffix: str = None) -> dict:
|
def as_goldshell(self, user_suffix: str | None = None) -> dict:
|
||||||
if user_suffix is not None:
|
return {
|
||||||
return {
|
"url": self.url,
|
||||||
"url": self.url,
|
"user": f"{self.user}{user_suffix or ''}",
|
||||||
"user": f"{self.user}{user_suffix}",
|
"pass": self.password,
|
||||||
"pass": self.password,
|
}
|
||||||
}
|
|
||||||
return {"url": self.url, "user": self.user, "pass": self.password}
|
|
||||||
|
|
||||||
def as_avalon(self, user_suffix: str = None) -> str:
|
def as_avalon(self, user_suffix: str | None = None) -> str:
|
||||||
if user_suffix is not None:
|
return ",".join([self.url, f"{self.user}{user_suffix or ''}", self.password])
|
||||||
return ",".join([self.url, f"{self.user}{user_suffix}", self.password])
|
|
||||||
return ",".join([self.url, self.user, self.password])
|
|
||||||
|
|
||||||
def as_inno(self, idx: int = 1, user_suffix: str = None) -> dict:
|
def as_inno(self, idx: int = 1, user_suffix: str | None = None) -> dict:
|
||||||
if user_suffix is not None:
|
|
||||||
return {
|
|
||||||
f"Pool{idx}": self.url,
|
|
||||||
f"UserName{idx}": f"{self.user}{user_suffix}",
|
|
||||||
f"Password{idx}": self.password,
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
f"Pool{idx}": self.url,
|
f"Pool{idx}": self.url,
|
||||||
f"UserName{idx}": self.user,
|
f"UserName{idx}": f"{self.user}{user_suffix or ''}",
|
||||||
f"Password{idx}": self.password,
|
f"Password{idx}": self.password,
|
||||||
}
|
}
|
||||||
|
|
||||||
def as_bosminer(self, user_suffix: str = None) -> dict:
|
def as_bosminer(self, user_suffix: str | None = None) -> dict:
|
||||||
if user_suffix is not None:
|
return {
|
||||||
return {
|
"url": self.url,
|
||||||
"url": self.url,
|
"user": f"{self.user}{user_suffix or ''}",
|
||||||
"user": f"{self.user}{user_suffix}",
|
"password": self.password,
|
||||||
"password": self.password,
|
}
|
||||||
}
|
|
||||||
return {"url": self.url, "user": self.user, "password": self.password}
|
|
||||||
|
|
||||||
def as_auradine(self, user_suffix: str = None) -> dict:
|
def as_auradine(self, user_suffix: str | None = None) -> dict:
|
||||||
if user_suffix is not None:
|
return {
|
||||||
return {
|
"url": self.url,
|
||||||
"url": self.url,
|
"user": f"{self.user}{user_suffix or ''}",
|
||||||
"user": f"{self.user}{user_suffix}",
|
"pass": self.password,
|
||||||
"pass": self.password,
|
}
|
||||||
}
|
|
||||||
return {"url": self.url, "user": self.user, "pass": self.password}
|
|
||||||
|
|
||||||
def as_epic(self, user_suffix: str = None):
|
def as_epic(self, user_suffix: str | None = None):
|
||||||
if user_suffix is not None:
|
return {
|
||||||
return {
|
"pool": self.url,
|
||||||
"pool": self.url,
|
"login": f"{self.user}{user_suffix or ''}",
|
||||||
"login": f"{self.user}{user_suffix}",
|
"password": self.password,
|
||||||
"password": self.password,
|
}
|
||||||
}
|
|
||||||
return {"pool": self.url, "login": self.user, "password": self.password}
|
|
||||||
|
|
||||||
def as_mara(self, user_suffix: str = None) -> dict:
|
def as_mara(self, user_suffix: str | None = None) -> dict:
|
||||||
if user_suffix is not None:
|
return {
|
||||||
return {
|
"url": self.url,
|
||||||
"url": self.url,
|
"user": f"{self.user}{user_suffix or ''}",
|
||||||
"user": f"{self.user}{user_suffix}",
|
"pass": self.password,
|
||||||
"pass": self.password,
|
}
|
||||||
}
|
|
||||||
return {"url": self.url, "user": self.user, "pass": self.password}
|
|
||||||
|
|
||||||
def as_bitaxe(self, user_suffix: str = None) -> dict:
|
def as_bitaxe(self, user_suffix: str | None = None) -> dict:
|
||||||
return {
|
return {
|
||||||
"stratumURL": self.url,
|
"stratumURL": self.url,
|
||||||
"stratumUser": f"{self.user}{user_suffix}",
|
"stratumUser": f"{self.user}{user_suffix or ''}",
|
||||||
"stratumPassword": self.password,
|
"stratumPassword": self.password,
|
||||||
}
|
}
|
||||||
|
|
||||||
def as_boser(self) -> PoolConfiguration:
|
def as_boser(self, user_suffix: str | None = None) -> PoolConfiguration:
|
||||||
return PoolConfiguration(
|
return PoolConfiguration(
|
||||||
url=self.url, user=self.user, password=self.password, enabled=True
|
url=self.url,
|
||||||
|
user=f"{self.user}{user_suffix or ''}",
|
||||||
|
password=self.password,
|
||||||
|
enabled=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def as_vnish(self, user_suffix: str = None) -> dict:
|
def as_vnish(self, user_suffix: str | None = None) -> dict:
|
||||||
if user_suffix is not None:
|
return {
|
||||||
return {
|
"url": self.url,
|
||||||
"url": self.url,
|
"user": f"{self.user}{user_suffix or ''}",
|
||||||
"user": f"{self.user}{user_suffix}",
|
"pass": self.password,
|
||||||
"pass": self.password,
|
}
|
||||||
}
|
|
||||||
return {"url": self.url, "user": self.user, "pass": self.password}
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, dict_conf: dict | None) -> "Pool":
|
def from_dict(cls, dict_conf: dict | None) -> "Pool":
|
||||||
@@ -201,7 +170,7 @@ class Pool(MinerConfigValue):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def from_vnish(cls, web_pool: dict) -> "Pool":
|
def from_vnish(cls, web_pool: dict) -> "Pool":
|
||||||
return cls(
|
return cls(
|
||||||
url=web_pool["url"],
|
url="stratum+tcp://" + web_pool["url"],
|
||||||
user=web_pool["user"],
|
user=web_pool["user"],
|
||||||
password=web_pool["pass"],
|
password=web_pool["pass"],
|
||||||
)
|
)
|
||||||
@@ -255,7 +224,7 @@ class PoolGroup(MinerConfigValue):
|
|||||||
random.choice(string.ascii_uppercase + string.digits) for _ in range(6)
|
random.choice(string.ascii_uppercase + string.digits) for _ in range(6)
|
||||||
) # generate random pool group name in case it isn't set
|
) # generate random pool group name in case it isn't set
|
||||||
|
|
||||||
def as_am_modern(self, user_suffix: str = None) -> list:
|
def as_am_modern(self, user_suffix: str | None = None) -> list:
|
||||||
pools = []
|
pools = []
|
||||||
idx = 0
|
idx = 0
|
||||||
while idx < 3:
|
while idx < 3:
|
||||||
@@ -266,7 +235,7 @@ class PoolGroup(MinerConfigValue):
|
|||||||
idx += 1
|
idx += 1
|
||||||
return pools
|
return pools
|
||||||
|
|
||||||
def as_wm(self, user_suffix: str = None) -> dict:
|
def as_wm(self, user_suffix: str | None = None) -> dict:
|
||||||
pools = {}
|
pools = {}
|
||||||
idx = 0
|
idx = 0
|
||||||
while idx < 3:
|
while idx < 3:
|
||||||
@@ -279,7 +248,7 @@ class PoolGroup(MinerConfigValue):
|
|||||||
idx += 1
|
idx += 1
|
||||||
return pools
|
return pools
|
||||||
|
|
||||||
def as_am_old(self, user_suffix: str = None) -> dict:
|
def as_am_old(self, user_suffix: str | None = None) -> dict:
|
||||||
pools = {}
|
pools = {}
|
||||||
idx = 0
|
idx = 0
|
||||||
while idx < 3:
|
while idx < 3:
|
||||||
@@ -294,15 +263,15 @@ class PoolGroup(MinerConfigValue):
|
|||||||
idx += 1
|
idx += 1
|
||||||
return pools
|
return pools
|
||||||
|
|
||||||
def as_goldshell(self, user_suffix: str = None) -> list:
|
def as_goldshell(self, user_suffix: str | None = None) -> list:
|
||||||
return [pool.as_goldshell(user_suffix) for pool in self.pools]
|
return [pool.as_goldshell(user_suffix) for pool in self.pools]
|
||||||
|
|
||||||
def as_avalon(self, user_suffix: str = None) -> str:
|
def as_avalon(self, user_suffix: str | None = None) -> str:
|
||||||
if len(self.pools) > 0:
|
if len(self.pools) > 0:
|
||||||
return self.pools[0].as_avalon(user_suffix=user_suffix)
|
return self.pools[0].as_avalon(user_suffix=user_suffix)
|
||||||
return Pool(url="", user="", password="").as_avalon()
|
return Pool(url="", user="", password="").as_avalon()
|
||||||
|
|
||||||
def as_inno(self, user_suffix: str = None) -> dict:
|
def as_inno(self, user_suffix: str | None = None) -> dict:
|
||||||
pools = {}
|
pools = {}
|
||||||
idx = 0
|
idx = 0
|
||||||
while idx < 3:
|
while idx < 3:
|
||||||
@@ -315,7 +284,7 @@ class PoolGroup(MinerConfigValue):
|
|||||||
idx += 1
|
idx += 1
|
||||||
return pools
|
return pools
|
||||||
|
|
||||||
def as_bosminer(self, user_suffix: str = None) -> dict:
|
def as_bosminer(self, user_suffix: str | None = None) -> dict:
|
||||||
if len(self.pools) > 0:
|
if len(self.pools) > 0:
|
||||||
conf = {
|
conf = {
|
||||||
"name": self.name,
|
"name": self.name,
|
||||||
@@ -328,26 +297,26 @@ class PoolGroup(MinerConfigValue):
|
|||||||
return conf
|
return conf
|
||||||
return {"name": "Group", "pool": []}
|
return {"name": "Group", "pool": []}
|
||||||
|
|
||||||
def as_auradine(self, user_suffix: str = None) -> list:
|
def as_auradine(self, user_suffix: str | None = None) -> list:
|
||||||
return [p.as_auradine(user_suffix=user_suffix) for p in self.pools]
|
return [p.as_auradine(user_suffix=user_suffix) for p in self.pools]
|
||||||
|
|
||||||
def as_epic(self, user_suffix: str = None) -> list:
|
def as_epic(self, user_suffix: str | None = None) -> list:
|
||||||
return [p.as_epic(user_suffix=user_suffix) for p in self.pools]
|
return [p.as_epic(user_suffix=user_suffix) for p in self.pools]
|
||||||
|
|
||||||
def as_mara(self, user_suffix: str = None) -> list:
|
def as_mara(self, user_suffix: str | None = None) -> list:
|
||||||
return [p.as_mara(user_suffix=user_suffix) for p in self.pools]
|
return [p.as_mara(user_suffix=user_suffix) for p in self.pools]
|
||||||
|
|
||||||
def as_bitaxe(self, user_suffix: str = None) -> dict:
|
def as_bitaxe(self, user_suffix: str | None = None) -> dict:
|
||||||
return self.pools[0].as_bitaxe(user_suffix=user_suffix)
|
return self.pools[0].as_bitaxe(user_suffix=user_suffix)
|
||||||
|
|
||||||
def as_boser(self, user_suffix: str = None) -> PoolGroupConfiguration:
|
def as_boser(self, user_suffix: str | None = None) -> PoolGroupConfiguration:
|
||||||
return PoolGroupConfiguration(
|
return PoolGroupConfiguration(
|
||||||
name=self.name,
|
name=self.name,
|
||||||
quota=Quota(value=self.quota),
|
quota=Quota(value=self.quota),
|
||||||
pools=[p.as_boser() for p in self.pools],
|
pools=[p.as_boser() for p in self.pools],
|
||||||
)
|
)
|
||||||
|
|
||||||
def as_vnish(self, user_suffix: str = None) -> dict:
|
def as_vnish(self, user_suffix: str | None = None) -> dict:
|
||||||
return {"pools": [p.as_vnish(user_suffix=user_suffix) for p in self.pools]}
|
return {"pools": [p.as_vnish(user_suffix=user_suffix) for p in self.pools]}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -402,7 +371,9 @@ class PoolGroup(MinerConfigValue):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_vnish(cls, web_settings_pools: dict) -> "PoolGroup":
|
def from_vnish(cls, web_settings_pools: dict) -> "PoolGroup":
|
||||||
return cls(pools=[Pool.from_vnish(p) for p in web_settings_pools])
|
return cls(
|
||||||
|
pools=[Pool.from_vnish(p) for p in web_settings_pools if p["url"] != ""]
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_boser(cls, grpc_pool_group: dict) -> "PoolGroup":
|
def from_boser(cls, grpc_pool_group: dict) -> "PoolGroup":
|
||||||
@@ -460,44 +431,44 @@ class PoolConfig(MinerConfigValue):
|
|||||||
group_pools.append(pool)
|
group_pools.append(pool)
|
||||||
return cls(groups=[PoolGroup(pools=group_pools)])
|
return cls(groups=[PoolGroup(pools=group_pools)])
|
||||||
|
|
||||||
def as_am_modern(self, user_suffix: str = None) -> dict:
|
def as_am_modern(self, user_suffix: str | None = None) -> dict:
|
||||||
if len(self.groups) > 0:
|
if len(self.groups) > 0:
|
||||||
return {"pools": self.groups[0].as_am_modern(user_suffix=user_suffix)}
|
return {"pools": self.groups[0].as_am_modern(user_suffix=user_suffix)}
|
||||||
return {"pools": PoolGroup().as_am_modern()}
|
return {"pools": PoolGroup().as_am_modern()}
|
||||||
|
|
||||||
def as_wm(self, user_suffix: str = None) -> dict:
|
def as_wm(self, user_suffix: str | None = None) -> dict:
|
||||||
if len(self.groups) > 0:
|
if len(self.groups) > 0:
|
||||||
return {"pools": self.groups[0].as_wm(user_suffix=user_suffix)}
|
return {"pools": self.groups[0].as_wm(user_suffix=user_suffix)}
|
||||||
return {"pools": PoolGroup().as_wm()}
|
return {"pools": PoolGroup().as_wm()}
|
||||||
|
|
||||||
def as_am_old(self, user_suffix: str = None) -> dict:
|
def as_am_old(self, user_suffix: str | None = None) -> dict:
|
||||||
if len(self.groups) > 0:
|
if len(self.groups) > 0:
|
||||||
return self.groups[0].as_am_old(user_suffix=user_suffix)
|
return self.groups[0].as_am_old(user_suffix=user_suffix)
|
||||||
return PoolGroup().as_am_old()
|
return PoolGroup().as_am_old()
|
||||||
|
|
||||||
def as_goldshell(self, user_suffix: str = None) -> dict:
|
def as_goldshell(self, user_suffix: str | None = None) -> dict:
|
||||||
if len(self.groups) > 0:
|
if len(self.groups) > 0:
|
||||||
return {"pools": self.groups[0].as_goldshell(user_suffix=user_suffix)}
|
return {"pools": self.groups[0].as_goldshell(user_suffix=user_suffix)}
|
||||||
return {"pools": PoolGroup().as_goldshell()}
|
return {"pools": PoolGroup().as_goldshell()}
|
||||||
|
|
||||||
def as_avalon(self, user_suffix: str = None) -> dict:
|
def as_avalon(self, user_suffix: str | None = None) -> dict:
|
||||||
if len(self.groups) > 0:
|
if len(self.groups) > 0:
|
||||||
return {"pools": self.groups[0].as_avalon(user_suffix=user_suffix)}
|
return {"pools": self.groups[0].as_avalon(user_suffix=user_suffix)}
|
||||||
return {"pools": PoolGroup().as_avalon()}
|
return {"pools": PoolGroup().as_avalon()}
|
||||||
|
|
||||||
def as_inno(self, user_suffix: str = None) -> dict:
|
def as_inno(self, user_suffix: str | None = None) -> dict:
|
||||||
if len(self.groups) > 0:
|
if len(self.groups) > 0:
|
||||||
return self.groups[0].as_inno(user_suffix=user_suffix)
|
return self.groups[0].as_inno(user_suffix=user_suffix)
|
||||||
return PoolGroup().as_inno()
|
return PoolGroup().as_inno()
|
||||||
|
|
||||||
def as_bosminer(self, user_suffix: str = None) -> dict:
|
def as_bosminer(self, user_suffix: str | None = None) -> dict:
|
||||||
if len(self.groups) > 0:
|
if len(self.groups) > 0:
|
||||||
return {
|
return {
|
||||||
"group": [g.as_bosminer(user_suffix=user_suffix) for g in self.groups]
|
"group": [g.as_bosminer(user_suffix=user_suffix) for g in self.groups]
|
||||||
}
|
}
|
||||||
return {"group": [PoolGroup().as_bosminer()]}
|
return {"group": [PoolGroup().as_bosminer()]}
|
||||||
|
|
||||||
def as_boser(self, user_suffix: str = None) -> dict:
|
def as_boser(self, user_suffix: str | None = None) -> dict:
|
||||||
return {
|
return {
|
||||||
"set_pool_groups": SetPoolGroupsRequest(
|
"set_pool_groups": SetPoolGroupsRequest(
|
||||||
save_action=SaveAction.SAVE_AND_APPLY,
|
save_action=SaveAction.SAVE_AND_APPLY,
|
||||||
@@ -505,7 +476,7 @@ class PoolConfig(MinerConfigValue):
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
def as_auradine(self, user_suffix: str = None) -> dict:
|
def as_auradine(self, user_suffix: str | None = None) -> dict:
|
||||||
if len(self.groups) > 0:
|
if len(self.groups) > 0:
|
||||||
return {
|
return {
|
||||||
"updatepools": {
|
"updatepools": {
|
||||||
@@ -514,7 +485,7 @@ class PoolConfig(MinerConfigValue):
|
|||||||
}
|
}
|
||||||
return {"updatepools": {"pools": PoolGroup().as_auradine()}}
|
return {"updatepools": {"pools": PoolGroup().as_auradine()}}
|
||||||
|
|
||||||
def as_epic(self, user_suffix: str = None) -> dict:
|
def as_epic(self, user_suffix: str | None = None) -> dict:
|
||||||
if len(self.groups) > 0:
|
if len(self.groups) > 0:
|
||||||
return {
|
return {
|
||||||
"pools": {
|
"pools": {
|
||||||
@@ -531,18 +502,18 @@ class PoolConfig(MinerConfigValue):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def as_mara(self, user_suffix: str = None) -> dict:
|
def as_mara(self, user_suffix: str | None = None) -> dict:
|
||||||
if len(self.groups) > 0:
|
if len(self.groups) > 0:
|
||||||
return {"pools": self.groups[0].as_mara(user_suffix=user_suffix)}
|
return {"pools": self.groups[0].as_mara(user_suffix=user_suffix)}
|
||||||
return {"pools": []}
|
return {"pools": []}
|
||||||
|
|
||||||
def as_bitaxe(self, user_suffix: str = None) -> dict:
|
def as_bitaxe(self, user_suffix: str | None = None) -> dict:
|
||||||
return self.groups[0].as_bitaxe(user_suffix=user_suffix)
|
return self.groups[0].as_bitaxe(user_suffix=user_suffix)
|
||||||
|
|
||||||
def as_luxos(self, user_suffix: str = None) -> dict:
|
def as_luxos(self, user_suffix: str | None = None) -> dict:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def as_vnish(self, user_suffix: str = None) -> dict:
|
def as_vnish(self, user_suffix: str | None = None) -> dict:
|
||||||
return self.groups[0].as_vnish(user_suffix=user_suffix)
|
return self.groups[0].as_vnish(user_suffix=user_suffix)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -13,19 +13,20 @@
|
|||||||
# See the License for the specific language governing permissions and -
|
# See the License for the specific language governing permissions and -
|
||||||
# limitations under the License. -
|
# limitations under the License. -
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from typing import Any, List, Union
|
from typing import Any, List, Union
|
||||||
|
|
||||||
from pydantic import BaseModel, Field, computed_field, field_serializer
|
from pydantic import BaseModel, Field, computed_field
|
||||||
|
|
||||||
from pyasic.config import MinerConfig
|
from pyasic.config import MinerConfig
|
||||||
from pyasic.config.mining import MiningModePowerTune
|
from pyasic.config.mining import MiningModePowerTune
|
||||||
from pyasic.data.pools import PoolMetrics, Scheme
|
from pyasic.data.pools import PoolMetrics, Scheme
|
||||||
from pyasic.device.algorithm.hashrate import AlgoHashRateType
|
from pyasic.device.algorithm.hashrate import AlgoHashRateType
|
||||||
|
from pyasic.device.algorithm.hashrate.base import GenericHashrate
|
||||||
|
|
||||||
|
from ..device.algorithm.hashrate.unit.base import GenericUnit
|
||||||
from .boards import HashBoard
|
from .boards import HashBoard
|
||||||
from .device import DeviceInfo
|
from .device import DeviceInfo
|
||||||
from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error
|
from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error
|
||||||
@@ -96,7 +97,7 @@ class MinerData(BaseModel):
|
|||||||
expected_fans: int | None = None
|
expected_fans: int | None = None
|
||||||
|
|
||||||
# temperature
|
# temperature
|
||||||
env_temp: int | None = None
|
env_temp: float | None = None
|
||||||
|
|
||||||
# power
|
# power
|
||||||
wattage: int | None = None
|
wattage: int | None = None
|
||||||
@@ -135,9 +136,6 @@ class MinerData(BaseModel):
|
|||||||
def fields(cls):
|
def fields(cls):
|
||||||
return list(cls.model_fields.keys())
|
return list(cls.model_fields.keys())
|
||||||
|
|
||||||
def __post_init__(self):
|
|
||||||
self.raw_datetime = datetime.now(timezone.utc).astimezone()
|
|
||||||
|
|
||||||
def get(self, __key: str, default: Any = None):
|
def get(self, __key: str, default: Any = None):
|
||||||
try:
|
try:
|
||||||
val = self.__getitem__(__key)
|
val = self.__getitem__(__key)
|
||||||
@@ -198,35 +196,23 @@ class MinerData(BaseModel):
|
|||||||
|
|
||||||
@computed_field # type: ignore[misc]
|
@computed_field # type: ignore[misc]
|
||||||
@property
|
@property
|
||||||
def hashrate(self) -> AlgoHashRateType:
|
def hashrate(self) -> AlgoHashRateType | None:
|
||||||
if len(self.hashboards) > 0:
|
if len(self.hashboards) > 0:
|
||||||
hr_data = []
|
hr_data = []
|
||||||
for item in self.hashboards:
|
for item in self.hashboards:
|
||||||
if item.hashrate is not None:
|
if item.hashrate is not None:
|
||||||
hr_data.append(item.hashrate)
|
hr_data.append(item.hashrate)
|
||||||
if len(hr_data) > 0:
|
if len(hr_data) > 0:
|
||||||
return sum(hr_data, start=type(hr_data[0])(rate=0))
|
return sum(hr_data, start=self.device_info.algo.hashrate(rate=0))
|
||||||
return self.raw_hashrate
|
return self.raw_hashrate
|
||||||
|
|
||||||
@field_serializer("hashrate")
|
|
||||||
def serialize_hashrate(self, hashrate: AlgoHashRateType | None) -> float:
|
|
||||||
if hashrate is not None:
|
|
||||||
return float(hashrate)
|
|
||||||
|
|
||||||
@field_serializer("expected_hashrate")
|
|
||||||
def serialize_expected_hashrate(
|
|
||||||
self, expected_hashrate: AlgoHashRateType | None, _info
|
|
||||||
) -> float:
|
|
||||||
if expected_hashrate is not None:
|
|
||||||
return float(expected_hashrate)
|
|
||||||
|
|
||||||
@hashrate.setter
|
@hashrate.setter
|
||||||
def hashrate(self, val):
|
def hashrate(self, val):
|
||||||
self.raw_hashrate = val
|
self.raw_hashrate = val
|
||||||
|
|
||||||
@computed_field # type: ignore[misc]
|
@computed_field # type: ignore[misc]
|
||||||
@property
|
@property
|
||||||
def wattage_limit(self) -> int:
|
def wattage_limit(self) -> int | None:
|
||||||
if self.config is not None:
|
if self.config is not None:
|
||||||
if isinstance(self.config.mining_mode, MiningModePowerTune):
|
if isinstance(self.config.mining_mode, MiningModePowerTune):
|
||||||
return self.config.mining_mode.power
|
return self.config.mining_mode.power
|
||||||
|
|||||||
@@ -51,11 +51,6 @@ class HashBoard(BaseModel):
|
|||||||
active: bool | None = None
|
active: bool | None = None
|
||||||
voltage: float | None = None
|
voltage: float | None = None
|
||||||
|
|
||||||
@field_serializer("hashrate")
|
|
||||||
def serialize_hashrate(self, hashrate: AlgoHashRateType | None) -> float:
|
|
||||||
if hashrate is not None:
|
|
||||||
return float(hashrate)
|
|
||||||
|
|
||||||
def get(self, __key: str, default: Any = None):
|
def get(self, __key: str, default: Any = None):
|
||||||
try:
|
try:
|
||||||
val = self.__getitem__(__key)
|
val = self.__getitem__(__key)
|
||||||
|
|||||||
@@ -1,19 +1,42 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel, field_serializer
|
||||||
from typing_extensions import Self
|
from typing_extensions import Self
|
||||||
|
|
||||||
from .unit.base import AlgoHashRateUnitType
|
from .unit.base import AlgoHashRateUnitType, GenericUnit
|
||||||
|
|
||||||
|
|
||||||
class AlgoHashRateType(BaseModel, ABC):
|
class AlgoHashRateType(BaseModel, ABC):
|
||||||
unit: AlgoHashRateUnitType
|
unit: AlgoHashRateUnitType
|
||||||
rate: float
|
rate: float
|
||||||
|
|
||||||
|
@field_serializer("unit")
|
||||||
|
def serialize_unit(self, unit: AlgoHashRateUnitType):
|
||||||
|
return unit.model_dump()
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def into(self, other: "AlgoHashRateUnitType"):
|
def into(self, other: "AlgoHashRateUnitType"):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def auto_unit(self):
|
||||||
|
if 1 < self.rate // int(self.unit.H) < 1000:
|
||||||
|
return self.into(self.unit.H)
|
||||||
|
if 1 < self.rate // int(self.unit.MH) < 1000:
|
||||||
|
return self.into(self.unit.MH)
|
||||||
|
if 1 < self.rate // int(self.unit.GH) < 1000:
|
||||||
|
return self.into(self.unit.GH)
|
||||||
|
if 1 < self.rate // int(self.unit.TH) < 1000:
|
||||||
|
return self.into(self.unit.TH)
|
||||||
|
if 1 < self.rate // int(self.unit.PH) < 1000:
|
||||||
|
return self.into(self.unit.PH)
|
||||||
|
if 1 < self.rate // int(self.unit.EH) < 1000:
|
||||||
|
return self.into(self.unit.EH)
|
||||||
|
if 1 < self.rate // int(self.unit.ZH) < 1000:
|
||||||
|
return self.into(self.unit.ZH)
|
||||||
|
return self
|
||||||
|
|
||||||
def __float__(self):
|
def __float__(self):
|
||||||
return float(self.rate)
|
return float(self.rate)
|
||||||
|
|
||||||
@@ -27,36 +50,46 @@ class AlgoHashRateType(BaseModel, ABC):
|
|||||||
return round(self.rate, n)
|
return round(self.rate, n)
|
||||||
|
|
||||||
def __add__(self, other: Self | int | float) -> Self:
|
def __add__(self, other: Self | int | float) -> Self:
|
||||||
if isinstance(other, self.__class__):
|
if isinstance(other, AlgoHashRateType):
|
||||||
return self.__class__(
|
return self.__class__(
|
||||||
rate=self.rate + other.into(self.unit).rate, unit=self.unit
|
rate=self.rate + other.into(self.unit).rate, unit=self.unit
|
||||||
)
|
)
|
||||||
return self.__class__(rate=self.rate + other, unit=self.unit)
|
return self.__class__(rate=self.rate + other, unit=self.unit)
|
||||||
|
|
||||||
def __sub__(self, other: Self | int | float) -> Self:
|
def __sub__(self, other: Self | int | float) -> Self:
|
||||||
if isinstance(other, self.__class__):
|
if isinstance(other, AlgoHashRateType):
|
||||||
return self.__class__(
|
return self.__class__(
|
||||||
rate=self.rate - other.into(self.unit).rate, unit=self.unit
|
rate=self.rate - other.into(self.unit).rate, unit=self.unit
|
||||||
)
|
)
|
||||||
return self.__class__(rate=self.rate - other, unit=self.unit)
|
return self.__class__(rate=self.rate - other, unit=self.unit)
|
||||||
|
|
||||||
def __truediv__(self, other: Self | int | float) -> Self:
|
def __truediv__(self, other: Self | int | float) -> Self:
|
||||||
if isinstance(other, self.__class__):
|
if isinstance(other, AlgoHashRateType):
|
||||||
return self.__class__(
|
return self.__class__(
|
||||||
rate=self.rate / other.into(self.unit).rate, unit=self.unit
|
rate=self.rate / other.into(self.unit).rate, unit=self.unit
|
||||||
)
|
)
|
||||||
return self.__class__(rate=self.rate / other, unit=self.unit)
|
return self.__class__(rate=self.rate / other, unit=self.unit)
|
||||||
|
|
||||||
def __floordiv__(self, other: Self | int | float) -> Self:
|
def __floordiv__(self, other: Self | int | float) -> Self:
|
||||||
if isinstance(other, self.__class__):
|
if isinstance(other, AlgoHashRateType):
|
||||||
return self.__class__(
|
return self.__class__(
|
||||||
rate=self.rate // other.into(self.unit).rate, unit=self.unit
|
rate=self.rate // other.into(self.unit).rate, unit=self.unit
|
||||||
)
|
)
|
||||||
return self.__class__(rate=self.rate // other, unit=self.unit)
|
return self.__class__(rate=self.rate // other, unit=self.unit)
|
||||||
|
|
||||||
def __mul__(self, other: Self | int | float) -> Self:
|
def __mul__(self, other: Self | int | float) -> Self:
|
||||||
if isinstance(other, self.__class__):
|
if isinstance(other, AlgoHashRateType):
|
||||||
return self.__class__(
|
return self.__class__(
|
||||||
rate=self.rate * other.into(self.unit).rate, unit=self.unit
|
rate=self.rate * other.into(self.unit).rate, unit=self.unit
|
||||||
)
|
)
|
||||||
return self.__class__(rate=self.rate * other, unit=self.unit)
|
return self.__class__(rate=self.rate * other, unit=self.unit)
|
||||||
|
|
||||||
|
|
||||||
|
class GenericHashrate(AlgoHashRateType):
|
||||||
|
rate: float = 0
|
||||||
|
unit: GenericUnit = GenericUnit.H
|
||||||
|
|
||||||
|
def into(self, other: GenericUnit):
|
||||||
|
return self.__class__(
|
||||||
|
rate=self.rate / (other.value / self.unit.value), unit=other
|
||||||
|
)
|
||||||
|
|||||||
@@ -53,3 +53,19 @@ class AlgoHashRateUnitType(IntEnum):
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return str(self)
|
return str(self)
|
||||||
|
|
||||||
|
def model_dump(self):
|
||||||
|
return {"value": self.value, "suffix": str(self)}
|
||||||
|
|
||||||
|
|
||||||
|
class GenericUnit(AlgoHashRateUnitType):
|
||||||
|
H = 1
|
||||||
|
KH = int(H) * 1000
|
||||||
|
MH = int(KH) * 1000
|
||||||
|
GH = int(MH) * 1000
|
||||||
|
TH = int(GH) * 1000
|
||||||
|
PH = int(TH) * 1000
|
||||||
|
EH = int(PH) * 1000
|
||||||
|
ZH = int(EH) * 1000
|
||||||
|
|
||||||
|
default = H
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from enum import IntEnum
|
from .base import AlgoHashRateUnitType
|
||||||
|
|
||||||
|
|
||||||
class ScryptUnit(IntEnum):
|
class ScryptUnit(AlgoHashRateUnitType):
|
||||||
H = 1
|
H = 1
|
||||||
KH = int(H) * 1000
|
KH = int(H) * 1000
|
||||||
MH = int(KH) * 1000
|
MH = int(KH) * 1000
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class AntminerModels(MinerModelType):
|
|||||||
S9j = "S9j"
|
S9j = "S9j"
|
||||||
T9 = "T9"
|
T9 = "T9"
|
||||||
D9 = "D9"
|
D9 = "D9"
|
||||||
|
L9 = "L9"
|
||||||
Z15 = "Z15"
|
Z15 = "Z15"
|
||||||
Z15Pro = "Z15 Pro"
|
Z15Pro = "Z15 Pro"
|
||||||
S17 = "S17"
|
S17 = "S17"
|
||||||
@@ -295,6 +296,7 @@ class AvalonminerModels(MinerModelType):
|
|||||||
Avalon1047 = "Avalon 1047"
|
Avalon1047 = "Avalon 1047"
|
||||||
Avalon1066 = "Avalon 1066"
|
Avalon1066 = "Avalon 1066"
|
||||||
Avalon1166Pro = "Avalon 1166 Pro"
|
Avalon1166Pro = "Avalon 1166 Pro"
|
||||||
|
Avalon1126Pro = "Avalon 1126 Pro"
|
||||||
Avalon1246 = "Avalon 1246"
|
Avalon1246 = "Avalon 1246"
|
||||||
AvalonNano3 = "Avalon Nano 3"
|
AvalonNano3 = "Avalon Nano 3"
|
||||||
|
|
||||||
|
|||||||
22
pyasic/miners/antminer/bmminer/X9/L9.py
Normal file
22
pyasic/miners/antminer/bmminer/X9/L9.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Copyright 2022 Upstream Data Inc -
|
||||||
|
# -
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); -
|
||||||
|
# you may not use this file except in compliance with the License. -
|
||||||
|
# You may obtain a copy of the License at -
|
||||||
|
# -
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 -
|
||||||
|
# -
|
||||||
|
# Unless required by applicable law or agreed to in writing, software -
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, -
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
|
||||||
|
# See the License for the specific language governing permissions and -
|
||||||
|
# limitations under the License. -
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
from pyasic.miners.backends import AntminerModern
|
||||||
|
from pyasic.miners.device.models import L9
|
||||||
|
|
||||||
|
|
||||||
|
class BMMinerL9(AntminerModern, L9):
|
||||||
|
pass
|
||||||
@@ -16,5 +16,6 @@
|
|||||||
|
|
||||||
from .D9 import BMMinerD9
|
from .D9 import BMMinerD9
|
||||||
from .E9 import BMMinerE9Pro
|
from .E9 import BMMinerE9Pro
|
||||||
|
from .L9 import BMMinerL9
|
||||||
from .S9 import BMMinerS9, BMMinerS9i, BMMinerS9j
|
from .S9 import BMMinerS9, BMMinerS9i, BMMinerS9j
|
||||||
from .T9 import BMMinerT9
|
from .T9 import BMMinerT9
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
# limitations under the License. -
|
# limitations under the License. -
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
from pyasic.miners.backends import Hiveon
|
from pyasic.miners.backends import HiveonModern
|
||||||
from pyasic.miners.device.models import (
|
from pyasic.miners.device.models import (
|
||||||
S19,
|
S19,
|
||||||
S19L,
|
S19L,
|
||||||
@@ -35,65 +35,65 @@ from pyasic.miners.device.models import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19(Hiveon, S19):
|
class HiveonS19(HiveonModern, S19):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19Plus(Hiveon, S19Plus):
|
class HiveonS19Plus(HiveonModern, S19Plus):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19i(Hiveon, S19i):
|
class HiveonS19i(HiveonModern, S19i):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19Pro(Hiveon, S19Pro):
|
class HiveonS19Pro(HiveonModern, S19Pro):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19ProPlus(Hiveon, S19ProPlus):
|
class HiveonS19ProPlus(HiveonModern, S19ProPlus):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19XP(Hiveon, S19XP):
|
class HiveonS19XP(HiveonModern, S19XP):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19a(Hiveon, S19a):
|
class HiveonS19a(HiveonModern, S19a):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19aPro(Hiveon, S19aPro):
|
class HiveonS19aPro(HiveonModern, S19aPro):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19j(Hiveon, S19j):
|
class HiveonS19j(HiveonModern, S19j):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19jNoPIC(Hiveon, S19jNoPIC):
|
class HiveonS19jNoPIC(HiveonModern, S19jNoPIC):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19jPro(Hiveon, S19jPro):
|
class HiveonS19jPro(HiveonModern, S19jPro):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19L(Hiveon, S19L):
|
class HiveonS19L(HiveonModern, S19L):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19ProHydro(Hiveon, S19ProHydro):
|
class HiveonS19ProHydro(HiveonModern, S19ProHydro):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19Hydro(Hiveon, S19Hydro):
|
class HiveonS19Hydro(HiveonModern, S19Hydro):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19ProPlusHydro(Hiveon, S19ProPlusHydro):
|
class HiveonS19ProPlusHydro(HiveonModern, S19ProPlusHydro):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HiveonS19KPro(Hiveon, S19KPro):
|
class HiveonS19KPro(HiveonModern, S19KPro):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -14,9 +14,9 @@
|
|||||||
# limitations under the License. -
|
# limitations under the License. -
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
from pyasic.miners.backends import Hiveon
|
from pyasic.miners.backends import HiveonModern
|
||||||
from pyasic.miners.device.models import T19
|
from pyasic.miners.device.models import T19
|
||||||
|
|
||||||
|
|
||||||
class HiveonT19(Hiveon, T19):
|
class HiveonT19(HiveonModern, T19):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import asyncssh
|
|||||||
from pyasic.data import HashBoard
|
from pyasic.data import HashBoard
|
||||||
from pyasic.device.algorithm import AlgoHashRate, HashUnit
|
from pyasic.device.algorithm import AlgoHashRate, HashUnit
|
||||||
from pyasic.errors import APIError
|
from pyasic.errors import APIError
|
||||||
from pyasic.miners.backends import Hiveon
|
from pyasic.miners.backends import HiveonOld
|
||||||
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
|
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
|
||||||
from pyasic.miners.device.models import T9
|
from pyasic.miners.device.models import T9
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ HIVEON_T9_DATA_LOC = DataLocations(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class HiveonT9(Hiveon, T9):
|
class HiveonT9(HiveonOld, T9):
|
||||||
data_locations = HIVEON_T9_DATA_LOC
|
data_locations = HIVEON_T9_DATA_LOC
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ from pyasic.miners.device.models import (
|
|||||||
S19aPro,
|
S19aPro,
|
||||||
S19j,
|
S19j,
|
||||||
S19jPro,
|
S19jPro,
|
||||||
|
S19kPro,
|
||||||
S19NoPIC,
|
S19NoPIC,
|
||||||
S19Pro,
|
S19Pro,
|
||||||
S19ProHydro,
|
S19ProHydro,
|
||||||
@@ -62,3 +63,7 @@ class VNishS19jPro(VNish, S19jPro):
|
|||||||
|
|
||||||
class VNishS19ProHydro(VNish, S19ProHydro):
|
class VNishS19ProHydro(VNish, S19ProHydro):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class VNishS19kPro(VNish, S19kPro):
|
||||||
|
pass
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ from .S19 import (
|
|||||||
VNishS19aPro,
|
VNishS19aPro,
|
||||||
VNishS19j,
|
VNishS19j,
|
||||||
VNishS19jPro,
|
VNishS19jPro,
|
||||||
|
VNishS19kPro,
|
||||||
VNishS19NoPIC,
|
VNishS19NoPIC,
|
||||||
VNishS19Pro,
|
VNishS19Pro,
|
||||||
VNishS19ProHydro,
|
VNishS19ProHydro,
|
||||||
|
|||||||
22
pyasic/miners/avalonminer/cgminer/A11X/A1126.py
Normal file
22
pyasic/miners/avalonminer/cgminer/A11X/A1126.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Copyright 2022 Upstream Data Inc -
|
||||||
|
# -
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); -
|
||||||
|
# you may not use this file except in compliance with the License. -
|
||||||
|
# You may obtain a copy of the License at -
|
||||||
|
# -
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 -
|
||||||
|
# -
|
||||||
|
# Unless required by applicable law or agreed to in writing, software -
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, -
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
|
||||||
|
# See the License for the specific language governing permissions and -
|
||||||
|
# limitations under the License. -
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
from pyasic.miners.backends import AvalonMiner
|
||||||
|
from pyasic.miners.device.models import Avalon1126Pro
|
||||||
|
|
||||||
|
|
||||||
|
class CGMinerAvalon1126Pro(AvalonMiner, Avalon1126Pro):
|
||||||
|
pass
|
||||||
@@ -14,4 +14,5 @@
|
|||||||
# limitations under the License. -
|
# limitations under the License. -
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
from .A1126 import CGMinerAvalon1126Pro
|
||||||
from .A1166 import CGMinerAvalon1166Pro
|
from .A1166 import CGMinerAvalon1166Pro
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from .cgminer import CGMiner
|
|||||||
from .epic import ePIC
|
from .epic import ePIC
|
||||||
from .goldshell import GoldshellMiner
|
from .goldshell import GoldshellMiner
|
||||||
from .hammer import BlackMiner
|
from .hammer import BlackMiner
|
||||||
from .hiveon import Hiveon
|
from .hiveon import HiveonModern, HiveonOld
|
||||||
from .iceriver import IceRiver
|
from .iceriver import IceRiver
|
||||||
from .innosilicon import Innosilicon
|
from .innosilicon import Innosilicon
|
||||||
from .luxminer import LUXMiner
|
from .luxminer import LUXMiner
|
||||||
|
|||||||
@@ -623,7 +623,7 @@ class BOSMiner(BraiinsOSFirmware):
|
|||||||
pass
|
pass
|
||||||
return pools_data
|
return pools_data
|
||||||
|
|
||||||
async def upgrade_firmware(self, file: Path):
|
async def upgrade_firmware(self, file: Path) -> str:
|
||||||
"""
|
"""
|
||||||
Upgrade the firmware of the BOSMiner device.
|
Upgrade the firmware of the BOSMiner device.
|
||||||
|
|
||||||
@@ -631,7 +631,7 @@ class BOSMiner(BraiinsOSFirmware):
|
|||||||
file (Path): The local file path of the firmware to be uploaded.
|
file (Path): The local file path of the firmware to be uploaded.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: Confirmation message after upgrading the firmware.
|
Confirmation message after upgrading the firmware.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
logging.info("Starting firmware upgrade process.")
|
logging.info("Starting firmware upgrade process.")
|
||||||
@@ -746,7 +746,7 @@ class BOSer(BraiinsOSFirmware):
|
|||||||
"""Handler for new versions of BraiinsOS+ (post-gRPC)"""
|
"""Handler for new versions of BraiinsOS+ (post-gRPC)"""
|
||||||
|
|
||||||
_rpc_cls = BOSMinerRPCAPI
|
_rpc_cls = BOSMinerRPCAPI
|
||||||
web: BOSMinerRPCAPI
|
rpc: BOSMinerRPCAPI
|
||||||
_web_cls = BOSerWebAPI
|
_web_cls = BOSerWebAPI
|
||||||
web: BOSerWebAPI
|
web: BOSerWebAPI
|
||||||
|
|
||||||
|
|||||||
@@ -692,7 +692,7 @@ class BTMiner(StockFirmware):
|
|||||||
pass
|
pass
|
||||||
return pools_data
|
return pools_data
|
||||||
|
|
||||||
async def upgrade_firmware(self, file: Path):
|
async def upgrade_firmware(self, file: Path) -> str:
|
||||||
"""
|
"""
|
||||||
Upgrade the firmware of the Whatsminer device.
|
Upgrade the firmware of the Whatsminer device.
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,28 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from pyasic import APIError
|
from pyasic import APIError
|
||||||
|
from pyasic.config import MinerConfig, MiningModeConfig
|
||||||
from pyasic.miners.backends import BMMiner
|
from pyasic.miners.backends import BMMiner
|
||||||
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
|
from pyasic.miners.data import (
|
||||||
|
DataFunction,
|
||||||
|
DataLocations,
|
||||||
|
DataOptions,
|
||||||
|
RPCAPICommand,
|
||||||
|
WebAPICommand,
|
||||||
|
)
|
||||||
from pyasic.miners.device.firmware import HiveonFirmware
|
from pyasic.miners.device.firmware import HiveonFirmware
|
||||||
|
from pyasic.web.hiveon import HiveonWebAPI
|
||||||
|
|
||||||
HIVEON_DATA_LOC = DataLocations(
|
HIVEON_MODERN_DATA_LOC = DataLocations(
|
||||||
**{
|
**{
|
||||||
|
str(DataOptions.MAC): DataFunction(
|
||||||
|
"_get_mac",
|
||||||
|
[WebAPICommand("web_get_system_info", "get_system_info")],
|
||||||
|
),
|
||||||
|
str(DataOptions.HOSTNAME): DataFunction(
|
||||||
|
"_get_hostname",
|
||||||
|
[WebAPICommand("web_get_system_info", "get_system_info")],
|
||||||
|
),
|
||||||
str(DataOptions.API_VERSION): DataFunction(
|
str(DataOptions.API_VERSION): DataFunction(
|
||||||
"_get_api_ver",
|
"_get_api_ver",
|
||||||
[RPCAPICommand("rpc_version", "version")],
|
[RPCAPICommand("rpc_version", "version")],
|
||||||
@@ -58,12 +74,193 @@ HIVEON_DATA_LOC = DataLocations(
|
|||||||
"_get_pools",
|
"_get_pools",
|
||||||
[RPCAPICommand("rpc_pools", "pools")],
|
[RPCAPICommand("rpc_pools", "pools")],
|
||||||
),
|
),
|
||||||
|
str(DataOptions.FAULT_LIGHT): DataFunction(
|
||||||
|
"_get_fault_light",
|
||||||
|
[WebAPICommand("web_get_blink_status", "get_blink_status")],
|
||||||
|
),
|
||||||
|
str(DataOptions.IS_MINING): DataFunction(
|
||||||
|
"_is_mining",
|
||||||
|
[WebAPICommand("web_get_conf", "get_miner_conf")],
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Hiveon(BMMiner, HiveonFirmware):
|
class HiveonModern(HiveonFirmware, BMMiner):
|
||||||
data_locations = HIVEON_DATA_LOC
|
data_locations = HIVEON_MODERN_DATA_LOC
|
||||||
|
|
||||||
|
web: HiveonWebAPI
|
||||||
|
_web_cls = HiveonWebAPI
|
||||||
|
|
||||||
|
async def get_config(self) -> MinerConfig:
|
||||||
|
data = await self.web.get_miner_conf()
|
||||||
|
if data:
|
||||||
|
self.config = MinerConfig.from_hiveon_modern(data)
|
||||||
|
return self.config
|
||||||
|
|
||||||
|
async def fault_light_on(self) -> bool:
|
||||||
|
data = await self.web.blink(blink=True)
|
||||||
|
if data:
|
||||||
|
if data.get("code") == "B000":
|
||||||
|
self.light = True
|
||||||
|
return self.light
|
||||||
|
|
||||||
|
async def fault_light_off(self) -> bool:
|
||||||
|
data = await self.web.blink(blink=False)
|
||||||
|
if data:
|
||||||
|
if data.get("code") == "B100":
|
||||||
|
self.light = False
|
||||||
|
return self.light
|
||||||
|
|
||||||
|
async def reboot(self) -> bool:
|
||||||
|
data = await self.web.reboot()
|
||||||
|
if data:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def stop_mining(self) -> bool:
|
||||||
|
cfg = await self.get_config()
|
||||||
|
cfg.miner_mode = MiningModeConfig.sleep()
|
||||||
|
await self.send_config(cfg)
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def resume_mining(self) -> bool:
|
||||||
|
cfg = await self.get_config()
|
||||||
|
cfg.miner_mode = MiningModeConfig.normal()
|
||||||
|
await self.send_config(cfg)
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def _get_wattage(self, rpc_stats: dict = None) -> Optional[int]:
|
||||||
|
if not rpc_stats:
|
||||||
|
try:
|
||||||
|
rpc_stats = await self.rpc.stats()
|
||||||
|
except APIError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if rpc_stats:
|
||||||
|
boards = rpc_stats.get("STATS")
|
||||||
|
try:
|
||||||
|
wattage_raw = boards[1]["chain_power"]
|
||||||
|
except (KeyError, IndexError):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# parse wattage position out of raw data
|
||||||
|
return round(float(wattage_raw.split(" ")[0]))
|
||||||
|
|
||||||
|
async def _get_hostname(self, web_get_system_info: dict = None) -> Optional[str]:
|
||||||
|
if web_get_system_info is None:
|
||||||
|
try:
|
||||||
|
web_get_system_info = await self.web.get_system_info()
|
||||||
|
except APIError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if web_get_system_info is not None:
|
||||||
|
try:
|
||||||
|
return web_get_system_info["hostname"]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def _get_mac(self, web_get_system_info: dict = None) -> Optional[str]:
|
||||||
|
if web_get_system_info is None:
|
||||||
|
try:
|
||||||
|
web_get_system_info = await self.web.get_system_info()
|
||||||
|
except APIError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if web_get_system_info is not None:
|
||||||
|
try:
|
||||||
|
return web_get_system_info["macaddr"]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = await self.web.get_network_info()
|
||||||
|
if data:
|
||||||
|
return data["macaddr"]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def _get_fault_light(
|
||||||
|
self, web_get_blink_status: dict = None
|
||||||
|
) -> Optional[bool]:
|
||||||
|
if self.light:
|
||||||
|
return self.light
|
||||||
|
|
||||||
|
if web_get_blink_status is None:
|
||||||
|
try:
|
||||||
|
web_get_blink_status = await self.web.get_blink_status()
|
||||||
|
except APIError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if web_get_blink_status is not None:
|
||||||
|
try:
|
||||||
|
self.light = web_get_blink_status["blink"]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
return self.light
|
||||||
|
|
||||||
|
async def _is_mining(self, web_get_conf: dict = None) -> Optional[bool]:
|
||||||
|
if web_get_conf is None:
|
||||||
|
try:
|
||||||
|
web_get_conf = await self.web.get_miner_conf()
|
||||||
|
except APIError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if web_get_conf is not None:
|
||||||
|
try:
|
||||||
|
if str(web_get_conf["bitmain-work-mode"]).isdigit():
|
||||||
|
return (
|
||||||
|
False if int(web_get_conf["bitmain-work-mode"]) == 1 else True
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
except LookupError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
HIVEON_OLD_DATA_LOC = DataLocations(
|
||||||
|
**{
|
||||||
|
str(DataOptions.API_VERSION): DataFunction(
|
||||||
|
"_get_api_ver",
|
||||||
|
[RPCAPICommand("rpc_version", "version")],
|
||||||
|
),
|
||||||
|
str(DataOptions.FW_VERSION): DataFunction(
|
||||||
|
"_get_fw_ver",
|
||||||
|
[RPCAPICommand("rpc_version", "version")],
|
||||||
|
),
|
||||||
|
str(DataOptions.HASHRATE): DataFunction(
|
||||||
|
"_get_hashrate",
|
||||||
|
[RPCAPICommand("rpc_summary", "summary")],
|
||||||
|
),
|
||||||
|
str(DataOptions.EXPECTED_HASHRATE): DataFunction(
|
||||||
|
"_get_expected_hashrate",
|
||||||
|
[RPCAPICommand("rpc_stats", "stats")],
|
||||||
|
),
|
||||||
|
str(DataOptions.HASHBOARDS): DataFunction(
|
||||||
|
"_get_hashboards",
|
||||||
|
[RPCAPICommand("rpc_stats", "stats")],
|
||||||
|
),
|
||||||
|
str(DataOptions.FANS): DataFunction(
|
||||||
|
"_get_fans",
|
||||||
|
[RPCAPICommand("rpc_stats", "stats")],
|
||||||
|
),
|
||||||
|
str(DataOptions.UPTIME): DataFunction(
|
||||||
|
"_get_uptime",
|
||||||
|
[RPCAPICommand("rpc_stats", "stats")],
|
||||||
|
),
|
||||||
|
str(DataOptions.POOLS): DataFunction(
|
||||||
|
"_get_pools",
|
||||||
|
[RPCAPICommand("rpc_pools", "pools")],
|
||||||
|
),
|
||||||
|
str(DataOptions.WATTAGE): DataFunction(
|
||||||
|
"_get_wattage",
|
||||||
|
[RPCAPICommand("rpc_stats", "stats")],
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class HiveonOld(HiveonFirmware, BMMiner):
|
||||||
|
data_locations = HIVEON_OLD_DATA_LOC
|
||||||
|
|
||||||
async def _get_wattage(self, rpc_stats: dict = None) -> Optional[int]:
|
async def _get_wattage(self, rpc_stats: dict = None) -> Optional[int]:
|
||||||
if not rpc_stats:
|
if not rpc_stats:
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
# limitations under the License. -
|
# limitations under the License. -
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import logging
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from pyasic import MinerConfig
|
from pyasic import MinerConfig
|
||||||
@@ -95,6 +96,8 @@ class VNish(VNishFirmware, BMMiner):
|
|||||||
web: VNishWebAPI
|
web: VNishWebAPI
|
||||||
|
|
||||||
supports_shutdown = True
|
supports_shutdown = True
|
||||||
|
supports_presets = True
|
||||||
|
supports_autotuning = True
|
||||||
|
|
||||||
data_locations = VNISH_DATA_LOC
|
data_locations = VNISH_DATA_LOC
|
||||||
|
|
||||||
@@ -266,7 +269,32 @@ class VNish(VNishFirmware, BMMiner):
|
|||||||
async def get_config(self) -> MinerConfig:
|
async def get_config(self) -> MinerConfig:
|
||||||
try:
|
try:
|
||||||
web_settings = await self.web.settings()
|
web_settings = await self.web.settings()
|
||||||
|
web_presets = await self.web.autotune_presets()
|
||||||
except APIError:
|
except APIError:
|
||||||
return self.config
|
return self.config
|
||||||
self.config = MinerConfig.from_vnish(web_settings)
|
self.config = MinerConfig.from_vnish(web_settings, web_presets)
|
||||||
return self.config
|
return self.config
|
||||||
|
|
||||||
|
async def set_power_limit(self, wattage: int) -> bool:
|
||||||
|
config = await self.get_config()
|
||||||
|
valid_presets = [
|
||||||
|
preset.power
|
||||||
|
for preset in config.mining_mode.available_presets
|
||||||
|
if preset.tuned and preset.power <= wattage
|
||||||
|
]
|
||||||
|
new_wattage = max(valid_presets)
|
||||||
|
|
||||||
|
# Set power to highest preset <= wattage
|
||||||
|
try:
|
||||||
|
await self.web.set_power_limit(new_wattage)
|
||||||
|
updated_settings = await self.web.settings()
|
||||||
|
except APIError:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
logging.warning(f"{self} - Failed to set power limit: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if int(updated_settings["miner"]["overclock"]["preset"]) == new_wattage:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ class MinerProtocol(Protocol):
|
|||||||
|
|
||||||
supports_shutdown: bool = False
|
supports_shutdown: bool = False
|
||||||
supports_power_modes: bool = False
|
supports_power_modes: bool = False
|
||||||
|
supports_presets: bool = False
|
||||||
supports_autotuning: bool = False
|
supports_autotuning: bool = False
|
||||||
|
|
||||||
api_ver: str = None
|
api_ver: str = None
|
||||||
@@ -98,6 +99,11 @@ class MinerProtocol(Protocol):
|
|||||||
return self.rpc
|
return self.rpc
|
||||||
|
|
||||||
async def check_light(self) -> bool:
|
async def check_light(self) -> bool:
|
||||||
|
"""Get the status of the fault light as a boolean.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A boolean value representing the fault light status.
|
||||||
|
"""
|
||||||
return await self.get_fault_light()
|
return await self.get_fault_light()
|
||||||
|
|
||||||
async def fault_light_on(self) -> bool:
|
async def fault_light_on(self) -> bool:
|
||||||
@@ -177,6 +183,27 @@ class MinerProtocol(Protocol):
|
|||||||
"""
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
async def upgrade_firmware(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
file: str = None,
|
||||||
|
url: str = None,
|
||||||
|
version: str = None,
|
||||||
|
keep_settings: bool = True,
|
||||||
|
) -> bool:
|
||||||
|
"""Upgrade the firmware of the miner.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
file: The file path to the firmware to upgrade from. Must be a valid file path if provided.
|
||||||
|
url: The URL to download the firmware from. Must be a valid URL if provided.
|
||||||
|
version: The version of the firmware to upgrade to. If None, the version will be inferred from the file or URL.
|
||||||
|
keep_settings: Whether to keep the current settings during the upgrade. Defaults to True.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A boolean value of the success of the firmware upgrade.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
### DATA GATHERING FUNCTIONS (get_{some_data}) ###
|
### DATA GATHERING FUNCTIONS (get_{some_data}) ###
|
||||||
##################################################
|
##################################################
|
||||||
@@ -346,7 +373,7 @@ class MinerProtocol(Protocol):
|
|||||||
async def get_pools(self) -> List[PoolMetrics]:
|
async def get_pools(self) -> List[PoolMetrics]:
|
||||||
"""Get the pools information from Miner.
|
"""Get the pools information from Miner.
|
||||||
|
|
||||||
Return:
|
Returns:
|
||||||
The pool information of the miner.
|
The pool information of the miner.
|
||||||
"""
|
"""
|
||||||
return await self._get_pools()
|
return await self._get_pools()
|
||||||
@@ -565,26 +592,5 @@ class BaseMiner(MinerProtocol):
|
|||||||
if self._ssh_cls is not None:
|
if self._ssh_cls is not None:
|
||||||
self.ssh = self._ssh_cls(ip)
|
self.ssh = self._ssh_cls(ip)
|
||||||
|
|
||||||
async def upgrade_firmware(
|
|
||||||
self,
|
|
||||||
*,
|
|
||||||
file: str = None,
|
|
||||||
url: str = None,
|
|
||||||
version: str = None,
|
|
||||||
keep_settings: bool = True,
|
|
||||||
) -> bool:
|
|
||||||
"""Upgrade the firmware of the miner.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
file (str, optional): The file path to the firmware to upgrade from. Must be a valid file path if provided.
|
|
||||||
url (str, optional): The URL to download the firmware from. Must be a valid URL if provided.
|
|
||||||
version (str, optional): The version of the firmware to upgrade to. If None, the version will be inferred from the file or URL.
|
|
||||||
keep_settings (bool, optional): Whether to keep the current settings during the upgrade. Defaults to True.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A boolean value of the success of the firmware upgrade.
|
|
||||||
"""
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
AnyMiner = TypeVar("AnyMiner", bound=BaseMiner)
|
AnyMiner = TypeVar("AnyMiner", bound=BaseMiner)
|
||||||
|
|||||||
27
pyasic/miners/device/models/antminer/X9/L9.py
Normal file
27
pyasic/miners/device/models/antminer/X9/L9.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Copyright 2022 Upstream Data Inc -
|
||||||
|
# -
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); -
|
||||||
|
# you may not use this file except in compliance with the License. -
|
||||||
|
# You may obtain a copy of the License at -
|
||||||
|
# -
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 -
|
||||||
|
# -
|
||||||
|
# Unless required by applicable law or agreed to in writing, software -
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, -
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
|
||||||
|
# See the License for the specific language governing permissions and -
|
||||||
|
# limitations under the License. -
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
from pyasic.device.algorithm import MinerAlgo
|
||||||
|
from pyasic.device.models import MinerModel
|
||||||
|
from pyasic.miners.device.makes import AntMinerMake
|
||||||
|
|
||||||
|
|
||||||
|
class L9(AntMinerMake):
|
||||||
|
raw_model = MinerModel.ANTMINER.L9
|
||||||
|
|
||||||
|
expected_chips = 110
|
||||||
|
expected_hashboards = 3
|
||||||
|
expected_fans = 4
|
||||||
|
algo = MinerAlgo.SCRYPT
|
||||||
@@ -16,5 +16,6 @@
|
|||||||
|
|
||||||
from .D9 import D9
|
from .D9 import D9
|
||||||
from .E9 import E9Pro
|
from .E9 import E9Pro
|
||||||
|
from .L9 import L9
|
||||||
from .S9 import S9, S9i, S9j
|
from .S9 import S9, S9i, S9j
|
||||||
from .T9 import T9
|
from .T9 import T9
|
||||||
|
|||||||
27
pyasic/miners/device/models/avalonminer/A11X/A1126.py
Normal file
27
pyasic/miners/device/models/avalonminer/A11X/A1126.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Copyright 2022 Upstream Data Inc -
|
||||||
|
# -
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); -
|
||||||
|
# you may not use this file except in compliance with the License. -
|
||||||
|
# You may obtain a copy of the License at -
|
||||||
|
# -
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 -
|
||||||
|
# -
|
||||||
|
# Unless required by applicable law or agreed to in writing, software -
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, -
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
|
||||||
|
# See the License for the specific language governing permissions and -
|
||||||
|
# limitations under the License. -
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
from pyasic.device.algorithm import MinerAlgo
|
||||||
|
from pyasic.device.models import MinerModel
|
||||||
|
from pyasic.miners.device.makes import AvalonMinerMake
|
||||||
|
|
||||||
|
|
||||||
|
class Avalon1126Pro(AvalonMinerMake):
|
||||||
|
raw_model = MinerModel.AVALONMINER.Avalon1126Pro
|
||||||
|
|
||||||
|
expected_chips = 120
|
||||||
|
expected_fans = 4
|
||||||
|
expected_hashboards = 3
|
||||||
|
algo = MinerAlgo.SHA256
|
||||||
@@ -15,4 +15,5 @@
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
from .A1126 import Avalon1126Pro
|
||||||
from .A1166 import Avalon1166Pro
|
from .A1166 import Avalon1166Pro
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ MINER_CLASSES = {
|
|||||||
"ANTMINER S9I": BMMinerS9i,
|
"ANTMINER S9I": BMMinerS9i,
|
||||||
"ANTMINER S9J": BMMinerS9j,
|
"ANTMINER S9J": BMMinerS9j,
|
||||||
"ANTMINER T9": BMMinerT9,
|
"ANTMINER T9": BMMinerT9,
|
||||||
|
"ANTMINER L9": BMMinerL9,
|
||||||
"ANTMINER Z15": CGMinerZ15,
|
"ANTMINER Z15": CGMinerZ15,
|
||||||
"ANTMINER Z15 PRO": BMMinerZ15Pro,
|
"ANTMINER Z15 PRO": BMMinerZ15Pro,
|
||||||
"ANTMINER S17": BMMinerS17,
|
"ANTMINER S17": BMMinerS17,
|
||||||
@@ -339,6 +340,7 @@ MINER_CLASSES = {
|
|||||||
"AVALONMINER 1026": CGMinerAvalon1026,
|
"AVALONMINER 1026": CGMinerAvalon1026,
|
||||||
"AVALONMINER 1047": CGMinerAvalon1047,
|
"AVALONMINER 1047": CGMinerAvalon1047,
|
||||||
"AVALONMINER 1066": CGMinerAvalon1066,
|
"AVALONMINER 1066": CGMinerAvalon1066,
|
||||||
|
"AVALONMINER 1126PRO": CGMinerAvalon1126Pro,
|
||||||
"AVALONMINER 1166PRO": CGMinerAvalon1166Pro,
|
"AVALONMINER 1166PRO": CGMinerAvalon1166Pro,
|
||||||
"AVALONMINER 1246": CGMinerAvalon1246,
|
"AVALONMINER 1246": CGMinerAvalon1246,
|
||||||
"AVALONMINER NANO3": CGMinerAvalonNano3,
|
"AVALONMINER NANO3": CGMinerAvalonNano3,
|
||||||
@@ -405,6 +407,7 @@ MINER_CLASSES = {
|
|||||||
"ANTMINER S19A": VNishS19a,
|
"ANTMINER S19A": VNishS19a,
|
||||||
"ANTMINER S19A PRO": VNishS19aPro,
|
"ANTMINER S19A PRO": VNishS19aPro,
|
||||||
"ANTMINER S19 PRO HYD.": VNishS19ProHydro,
|
"ANTMINER S19 PRO HYD.": VNishS19ProHydro,
|
||||||
|
"ANTMINER S19K PRO": VNishS19kPro,
|
||||||
"ANTMINER T19": VNishT19,
|
"ANTMINER T19": VNishT19,
|
||||||
"ANTMINER S21": VNishS21,
|
"ANTMINER S21": VNishS21,
|
||||||
},
|
},
|
||||||
@@ -424,9 +427,10 @@ MINER_CLASSES = {
|
|||||||
"BLOCKMINER 720I": ePICBlockMiner720i,
|
"BLOCKMINER 720I": ePICBlockMiner720i,
|
||||||
},
|
},
|
||||||
MinerTypes.HIVEON: {
|
MinerTypes.HIVEON: {
|
||||||
None: Hiveon,
|
None: HiveonModern,
|
||||||
"ANTMINER T9": HiveonT9,
|
"ANTMINER T9": HiveonT9,
|
||||||
"ANTMINER S19JPRO": HiveonS19jPro,
|
"ANTMINER S19JPRO": HiveonS19jPro,
|
||||||
|
"ANTMINER S19": HiveonS19,
|
||||||
},
|
},
|
||||||
MinerTypes.LUX_OS: {
|
MinerTypes.LUX_OS: {
|
||||||
None: LUXMiner,
|
None: LUXMiner,
|
||||||
@@ -631,7 +635,6 @@ class MinerFactory:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_web_type(web_text: str, web_resp: httpx.Response) -> MinerTypes | None:
|
def _parse_web_type(web_text: str, web_resp: httpx.Response) -> MinerTypes | None:
|
||||||
print(web_resp.headers)
|
|
||||||
if web_resp.status_code == 401 and 'realm="antMiner' in web_resp.headers.get(
|
if web_resp.status_code == 401 and 'realm="antMiner' in web_resp.headers.get(
|
||||||
"www-authenticate", ""
|
"www-authenticate", ""
|
||||||
):
|
):
|
||||||
@@ -865,7 +868,7 @@ class MinerFactory:
|
|||||||
miner_type: MinerTypes | None,
|
miner_type: MinerTypes | None,
|
||||||
) -> AnyMiner | None:
|
) -> AnyMiner | None:
|
||||||
# special case since hiveon miners return web results copying the antminer stock FW
|
# special case since hiveon miners return web results copying the antminer stock FW
|
||||||
if "HIVEON" in str(miner_model).upper() and miner_type == MinerTypes.ANTMINER:
|
if "HIVEON" in str(miner_model).upper():
|
||||||
miner_model = str(miner_model).upper().replace(" HIVEON", "")
|
miner_model = str(miner_model).upper().replace(" HIVEON", "")
|
||||||
miner_type = MinerTypes.HIVEON
|
miner_type = MinerTypes.HIVEON
|
||||||
try:
|
try:
|
||||||
@@ -874,7 +877,7 @@ class MinerFactory:
|
|||||||
if miner_type in MINER_CLASSES:
|
if miner_type in MINER_CLASSES:
|
||||||
if miner_model is not None:
|
if miner_model is not None:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
f"Partially supported miner found: {miner_model}, please open an issue with miner data "
|
f"Partially supported miner found: {miner_model}, type: {miner_type}, please open an issue with miner data "
|
||||||
f"and this model on GitHub (https://github.com/UpstreamData/pyasic/issues)."
|
f"and this model on GitHub (https://github.com/UpstreamData/pyasic/issues)."
|
||||||
)
|
)
|
||||||
return MINER_CLASSES[miner_type][None](ip)
|
return MINER_CLASSES[miner_type][None](ip)
|
||||||
|
|||||||
@@ -560,17 +560,21 @@ class BTMinerRPCAPI(BaseMinerRPCAPI):
|
|||||||
"""
|
"""
|
||||||
return await self.send_privileged_command("set_normal_power")
|
return await self.send_privileged_command("set_normal_power")
|
||||||
|
|
||||||
async def update_firmware(self, firmware: bytes):
|
async def update_firmware(self, firmware: bytes) -> bool:
|
||||||
"""Upgrade the firmware running on the miner and using the firmware passed in bytes.
|
"""Upgrade the firmware running on the miner and using the firmware passed in bytes.
|
||||||
|
<details>
|
||||||
|
<summary>Expand</summary>
|
||||||
|
|
||||||
|
Set the LED on the miner using the API, only works after
|
||||||
|
changing the password of the miner using the Whatsminer tool.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
firmware (bytes): The firmware binary data to be uploaded.
|
firmware (bytes): The firmware binary data to be uploaded.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: A boolean indicating the success of the firmware upgrade.
|
A boolean indicating the success of the firmware upgrade.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
APIError: If the miner is not ready for firmware update.
|
APIError: If the miner is not ready for firmware update.
|
||||||
|
</details>
|
||||||
"""
|
"""
|
||||||
ready = await self.send_privileged_command("upgrade_firmware")
|
ready = await self.send_privileged_command("upgrade_firmware")
|
||||||
if not ready.get("Msg") == "ready":
|
if not ready.get("Msg") == "ready":
|
||||||
@@ -796,10 +800,8 @@ class BTMinerRPCAPI(BaseMinerRPCAPI):
|
|||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
complete: check whether pre power on is complete.
|
complete: check whether pre power on is complete.
|
||||||
msg: ## the message to check.
|
msg: the message to check.
|
||||||
* `wait for adjust temp`
|
|
||||||
* `adjust complete`
|
|
||||||
* `adjust continue`
|
|
||||||
Returns:
|
Returns:
|
||||||
A reply informing of the status of pre power on.
|
A reply informing of the status of pre power on.
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ _settings = { # defaults
|
|||||||
"default_goldshell_web_password": "123456789",
|
"default_goldshell_web_password": "123456789",
|
||||||
"default_auradine_web_password": "admin",
|
"default_auradine_web_password": "admin",
|
||||||
"default_epic_web_password": "letmein",
|
"default_epic_web_password": "letmein",
|
||||||
"default_hive_web_password": "admin",
|
"default_hive_web_password": "root",
|
||||||
"default_iceriver_web_password": "12345678",
|
"default_iceriver_web_password": "12345678",
|
||||||
"default_antminer_ssh_password": "miner",
|
"default_antminer_ssh_password": "miner",
|
||||||
"default_bosminer_ssh_password": "root",
|
"default_bosminer_ssh_password": "root",
|
||||||
|
|||||||
214
pyasic/web/hiveon.py
Normal file
214
pyasic/web/hiveon.py
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Copyright 2022 Upstream Data Inc -
|
||||||
|
# -
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); -
|
||||||
|
# you may not use this file except in compliance with the License. -
|
||||||
|
# You may obtain a copy of the License at -
|
||||||
|
# -
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 -
|
||||||
|
# -
|
||||||
|
# Unless required by applicable law or agreed to in writing, software -
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, -
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
|
||||||
|
# See the License for the specific language governing permissions and -
|
||||||
|
# limitations under the License. -
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import aiofiles
|
||||||
|
import httpx
|
||||||
|
|
||||||
|
from pyasic import settings
|
||||||
|
from pyasic.web.base import BaseWebAPI
|
||||||
|
|
||||||
|
|
||||||
|
class HiveonWebAPI(BaseWebAPI):
|
||||||
|
def __init__(self, ip: str) -> None:
|
||||||
|
"""Initialize the old Antminer API client with a specific IP address.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ip (str): IP address of the Antminer device.
|
||||||
|
"""
|
||||||
|
super().__init__(ip)
|
||||||
|
self.username = "root"
|
||||||
|
self.pwd = settings.get("default_hive_web_password", "root")
|
||||||
|
|
||||||
|
async def send_command(
|
||||||
|
self,
|
||||||
|
command: str | bytes,
|
||||||
|
ignore_errors: bool = False,
|
||||||
|
allow_warning: bool = True,
|
||||||
|
privileged: bool = False,
|
||||||
|
**parameters: Any,
|
||||||
|
) -> dict:
|
||||||
|
"""Send a command to the Antminer device using HTTP digest authentication.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
command (str | bytes): The CGI command to send.
|
||||||
|
ignore_errors (bool): If True, ignore any HTTP errors.
|
||||||
|
allow_warning (bool): If True, proceed with warnings.
|
||||||
|
privileged (bool): If set to True, requires elevated privileges.
|
||||||
|
**parameters: Arbitrary keyword arguments to be sent as parameters in the request.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: The JSON response from the device or an empty dictionary if an error occurs.
|
||||||
|
"""
|
||||||
|
url = f"http://{self.ip}:{self.port}/cgi-bin/{command}.cgi"
|
||||||
|
auth = httpx.DigestAuth(self.username, self.pwd)
|
||||||
|
try:
|
||||||
|
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||||
|
if parameters:
|
||||||
|
data = await client.post(
|
||||||
|
url,
|
||||||
|
data=parameters,
|
||||||
|
auth=auth,
|
||||||
|
timeout=settings.get("api_function_timeout", 3),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
data = await client.get(url, auth=auth)
|
||||||
|
except httpx.HTTPError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if data.status_code == 200:
|
||||||
|
try:
|
||||||
|
return data.json()
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def multicommand(
|
||||||
|
self, *commands: str, ignore_errors: bool = False, allow_warning: bool = True
|
||||||
|
) -> dict:
|
||||||
|
"""Execute multiple commands simultaneously.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*commands (str): Multiple command strings to be executed.
|
||||||
|
ignore_errors (bool): If True, ignore any HTTP errors.
|
||||||
|
allow_warning (bool): If True, proceed with warnings.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A dictionary containing the results of all commands executed.
|
||||||
|
"""
|
||||||
|
data = {k: None for k in commands}
|
||||||
|
auth = httpx.DigestAuth(self.username, self.pwd)
|
||||||
|
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||||
|
for command in commands:
|
||||||
|
try:
|
||||||
|
url = f"http://{self.ip}/cgi-bin/{command}.cgi"
|
||||||
|
ret = await client.get(url, auth=auth)
|
||||||
|
except httpx.HTTPError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if ret.status_code == 200:
|
||||||
|
try:
|
||||||
|
json_data = ret.json()
|
||||||
|
data[command] = json_data
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
pass
|
||||||
|
return data
|
||||||
|
|
||||||
|
async def get_system_info(self) -> dict:
|
||||||
|
"""Retrieve system information from the miner.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A dictionary containing system information of the miner.
|
||||||
|
"""
|
||||||
|
return await self.send_command("get_system_info")
|
||||||
|
|
||||||
|
async def get_network_info(self) -> dict:
|
||||||
|
"""Retrieve system information from the miner.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A dictionary containing system information of the miner.
|
||||||
|
"""
|
||||||
|
return await self.send_command("get_network_info")
|
||||||
|
|
||||||
|
async def blink(self, blink: bool) -> dict:
|
||||||
|
"""Control the blinking of the LED on the miner device.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
blink (bool): True to start blinking, False to stop.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A dictionary response from the device after the command execution.
|
||||||
|
"""
|
||||||
|
if blink:
|
||||||
|
return await self.send_command("blink", action="startBlink")
|
||||||
|
return await self.send_command("blink", action="stopBlink")
|
||||||
|
|
||||||
|
async def reboot(self) -> dict:
|
||||||
|
"""Reboot the miner device.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A dictionary response from the device confirming the reboot command.
|
||||||
|
"""
|
||||||
|
return await self.send_command("reboot")
|
||||||
|
|
||||||
|
async def get_blink_status(self) -> dict:
|
||||||
|
"""Check the status of the LED blinking on the miner.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A dictionary indicating whether the LED is currently blinking.
|
||||||
|
"""
|
||||||
|
return await self.send_command("blink", action="onPageLoaded")
|
||||||
|
|
||||||
|
async def get_miner_conf(self) -> dict:
|
||||||
|
"""Retrieve the miner configuration from the Antminer device.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A dictionary containing the current configuration of the miner.
|
||||||
|
"""
|
||||||
|
return await self.send_command("get_miner_conf")
|
||||||
|
|
||||||
|
async def set_miner_conf(self, conf: dict) -> dict:
|
||||||
|
"""Set the configuration for the miner.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
conf (dict): A dictionary of configuration settings to apply to the miner.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A dictionary response from the device after setting the configuration.
|
||||||
|
"""
|
||||||
|
return await self.send_command("set_miner_conf", **conf)
|
||||||
|
|
||||||
|
async def stats(self) -> dict:
|
||||||
|
"""Retrieve detailed statistical data of the mining operation.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: Detailed statistics of the miner's operation.
|
||||||
|
"""
|
||||||
|
return await self.send_command("miner_stats")
|
||||||
|
|
||||||
|
async def summary(self) -> dict:
|
||||||
|
"""Get a summary of the miner's status and performance.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A summary of the miner's current operational status.
|
||||||
|
"""
|
||||||
|
return await self.send_command("miner_summary")
|
||||||
|
|
||||||
|
async def pools(self) -> dict:
|
||||||
|
"""Retrieve current pool information associated with the miner.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: Information about the mining pools configured in the miner.
|
||||||
|
"""
|
||||||
|
return await self.send_command("miner_pools")
|
||||||
|
|
||||||
|
async def update_firmware(self, file: Path, keep_settings: bool = True) -> dict:
|
||||||
|
"""Perform a system update by uploading a firmware file and sending a command to initiate the update."""
|
||||||
|
|
||||||
|
async with aiofiles.open(file, "rb") as firmware:
|
||||||
|
file_content = await firmware.read()
|
||||||
|
|
||||||
|
parameters = {
|
||||||
|
"file": (file.name, file_content, "application/octet-stream"),
|
||||||
|
"filename": file.name,
|
||||||
|
"keep_settings": keep_settings,
|
||||||
|
}
|
||||||
|
|
||||||
|
return await self.send_command(command="upgrade", **parameters)
|
||||||
@@ -138,6 +138,15 @@ class VNishWebAPI(BaseWebAPI):
|
|||||||
async def settings(self) -> dict:
|
async def settings(self) -> dict:
|
||||||
return await self.send_command("settings")
|
return await self.send_command("settings")
|
||||||
|
|
||||||
|
async def set_power_limit(self, wattage: int) -> bool:
|
||||||
|
# Can only set power limit to tuned preset
|
||||||
|
settings = await self.settings()
|
||||||
|
settings["miner"]["overclock"]["preset"] = str(wattage)
|
||||||
|
new_settings = {"miner": {"overclock": settings["miner"]["overclock"]}}
|
||||||
|
|
||||||
|
# response will always be {"restart_required":false,"reboot_required":false} even if unsuccessful
|
||||||
|
return await self.send_command("settings", privileged=True, **new_settings)
|
||||||
|
|
||||||
async def autotune_presets(self) -> dict:
|
async def autotune_presets(self) -> dict:
|
||||||
return await self.send_command("autotune/presets")
|
return await self.send_command("autotune/presets")
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "pyasic"
|
name = "pyasic"
|
||||||
version = "0.64.6"
|
version = "0.67.1"
|
||||||
description = "A simplified and standardized interface for Bitcoin ASICs."
|
description = "A simplified and standardized interface for Bitcoin ASICs."
|
||||||
authors = ["UpstreamData <brett@upstreamdata.ca>"]
|
authors = ["UpstreamData <brett@upstreamdata.ca>"]
|
||||||
repository = "https://github.com/UpstreamData/pyasic"
|
repository = "https://github.com/UpstreamData/pyasic"
|
||||||
@@ -30,8 +30,9 @@ isort = "^5.12.0"
|
|||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[tool.poetry.group.docs.dependencies]
|
[tool.poetry.group.docs.dependencies]
|
||||||
mkdocs = "^1.4.2"
|
mkdocs = "^1.6.1"
|
||||||
mkdocstrings = {extras = ["python"], version = "^0.20.0"}
|
mkdocstrings = {extras = ["python"], version = "^0.26.1"}
|
||||||
|
mkdocs-material = "^9.5.39"
|
||||||
|
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
|
|||||||
Reference in New Issue
Block a user