Skip to content

Commit c07ce1b

Browse files
authored
Merge branch 'staging' into master
2 parents 27eef20 + 9919f6a commit c07ce1b

File tree

11 files changed

+88
-21
lines changed

11 files changed

+88
-21
lines changed

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
fi
4646
4747
- name: Upload artifact
48-
uses: actions/upload-artifact@v3
48+
uses: actions/upload-artifact@v4
4949
with:
5050
name: dist
5151
path: dist/
@@ -60,7 +60,7 @@ jobs:
6060

6161
steps:
6262
- name: Download artifact
63-
uses: actions/download-artifact@v3
63+
uses: actions/download-artifact@v4
6464
with:
6565
name: dist
6666
path: dist/

bittensor/core/axon.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,6 @@ def run_in_thread(self):
142142
self.should_exit = True
143143
thread.join()
144144

145-
def _wrapper_run(self):
146-
"""
147-
A wrapper method for the :func:`run_in_thread` context manager. This method is used internally by the ``start`` method to initiate the server's execution in a separate thread.
148-
"""
149-
with self.run_in_thread():
150-
while not self.should_exit:
151-
time.sleep(1e-3)
152-
153145
def start(self):
154146
"""
155147
Starts the FastAPI server in a separate thread if it is not already running. This method sets up the server to handle HTTP requests concurrently, enabling the Axon server to efficiently manage incoming network requests.
@@ -158,7 +150,7 @@ def start(self):
158150
"""
159151
if not self.is_running:
160152
self.should_exit = False
161-
thread = threading.Thread(target=self._wrapper_run, daemon=True)
153+
thread = threading.Thread(target=self.run, daemon=True)
162154
thread.start()
163155
self.is_running = True
164156

@@ -377,7 +369,11 @@ def __init__(
377369
self.app = FastAPI()
378370
log_level = "trace" if logging.__trace_on__ else "critical"
379371
self.fast_config = uvicorn.Config(
380-
self.app, host="0.0.0.0", port=self.config.axon.port, log_level=log_level
372+
self.app,
373+
host="0.0.0.0",
374+
log_level=log_level,
375+
loop="none",
376+
port=self.config.axon.port,
381377
)
382378
self.fast_server = FastAPIThreadedServer(config=self.fast_config)
383379
self.router = APIRouter()

bittensor/core/extrinsics/async_commit_reveal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ async def commit_reveal_v3_extrinsic(
143143
return False, message
144144

145145
logging.success(
146-
f"[green]Finalized![/green] Weights commited with reveal round [blue]{reveal_round}[/blue]."
146+
f"[green]Finalized![/green] Weights committed with reveal round [blue]{reveal_round}[/blue]."
147147
)
148148
return True, f"reveal_round:{reveal_round}"
149149

bittensor/core/extrinsics/commit_reveal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def commit_reveal_v3_extrinsic(
145145

146146
if success is True:
147147
logging.success(
148-
f"[green]Finalized![/green] Weights commited with reveal round [blue]{reveal_round}[/blue]."
148+
f"[green]Finalized![/green] Weights committed with reveal round [blue]{reveal_round}[/blue]."
149149
)
150150
return True, f"reveal_round:{reveal_round}"
151151
else:

bittensor/core/metagraph.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ def sync(
554554
NOTE:
555555
If attempting to access data beyond the previous 300 blocks, you **must** use the ``archive`` network for subtensor. Light nodes are configured only to store the previous 300 blocks if connecting to finney or test networks.
556556
557-
For example::
557+
For example:
558558
559559
from bittensor.core.subtensor import Subtensor
560560
@@ -1112,7 +1112,7 @@ def load_from_path(self, dir_path: str) -> "Metagraph":
11121112
Returns:
11131113
metagraph (bittensor.core.metagraph.Metagraph): The current metagraph instance with the loaded state.
11141114
1115-
Example::
1115+
Example:
11161116
11171117
from bittensor.core.metagraph import Metagraph
11181118

bittensor/utils/btlogging/loggingmachine.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,10 @@ def get_level(self) -> int:
582582
"""Returns Logging level."""
583583
return self._logger.level
584584

585+
def setLevel(self, level):
586+
"""Set the specified level on the underlying logger."""
587+
self._logger.setLevel(level)
588+
585589
def check_config(self, config: "Config"):
586590
assert config.logging
587591

bittensor/utils/networking.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def int_to_ip(int_val: int) -> str:
3434
def ip_to_int(str_val: str) -> int:
3535
"""Maps an ip-string to a unique integer.
3636
arg:
37-
str_val (:tyep:`str`, `required):
37+
str_val (:type:`str`, `required):
3838
The string representation of an ip. Of form *.*.*.* for ipv4 or *::*:*:*:* for ipv6
3939
4040
Returns:
@@ -51,7 +51,7 @@ def ip_to_int(str_val: str) -> int:
5151
def ip_version(str_val: str) -> int:
5252
"""Returns the ip version (IPV4 or IPV6).
5353
arg:
54-
str_val (:tyep:`str`, `required):
54+
str_val (:type:`str`, `required):
5555
The string representation of an ip. Of form *.*.*.* for ipv4 or *::*:*:*:* for ipv6
5656
5757
Returns:

requirements/dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ flake8==7.0.0
1212
mypy==1.8.0
1313
types-retry==0.9.9.4
1414
freezegun==1.5.0
15-
torch>=1.13.1
15+
torch==2.5.1
1616
httpx==0.27.0
1717
ruff==0.4.7
1818
aioresponses==0.7.6

requirements/torch.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
torch>=1.13.1
1+
torch==2.5.1

tests/unit_tests/test_axon.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,23 @@
1717

1818

1919
import re
20+
import threading
2021
import time
2122
from dataclasses import dataclass
2223
from typing import Any, Optional, Tuple
2324
from unittest import IsolatedAsyncioTestCase
2425
from unittest.mock import AsyncMock, MagicMock, patch
2526

27+
import aiohttp
2628
import fastapi
2729
import netaddr
2830
import pydantic
2931
import pytest
32+
import uvicorn
3033
from fastapi.testclient import TestClient
3134
from starlette.requests import Request
3235

33-
from bittensor.core.axon import AxonMiddleware, Axon
36+
from bittensor.core.axon import Axon, AxonMiddleware, FastAPIThreadedServer
3437
from bittensor.core.errors import RunException
3538
from bittensor.core.settings import version_as_int
3639
from bittensor.core.stream import StreamingSynapse
@@ -785,3 +788,45 @@ async def forward_fn(synapse: streaming_synapse_cls):
785788
"computed_body_hash": "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a",
786789
},
787790
)
791+
792+
793+
@pytest.mark.asyncio
794+
async def test_threaded_fastapi():
795+
server_started = threading.Event()
796+
server_stopped = threading.Event()
797+
798+
async def lifespan(app):
799+
server_started.set()
800+
yield
801+
server_stopped.set()
802+
803+
app = fastapi.FastAPI(
804+
lifespan=lifespan,
805+
)
806+
app.get("/")(lambda: "Hello World")
807+
808+
server = FastAPIThreadedServer(
809+
uvicorn.Config(
810+
app,
811+
),
812+
)
813+
server.start()
814+
815+
server_started.wait()
816+
817+
assert server.is_running is True
818+
819+
async with aiohttp.ClientSession(
820+
base_url="http://127.0.0.1:8000",
821+
) as session:
822+
async with session.get("/") as response:
823+
assert await response.text() == '"Hello World"'
824+
825+
server.stop()
826+
827+
assert server.should_exit is True
828+
829+
server_stopped.wait()
830+
831+
with pytest.raises(aiohttp.ClientConnectorError):
832+
await session.get("/")

0 commit comments

Comments
 (0)