Skip to content

Commit 7099594

Browse files
Merge pull request #5 from opentensor/release/1.0.0rc2
Release/1.0.0rc2
2 parents fe622cd + a3ae910 commit 7099594

File tree

5 files changed

+172
-24
lines changed

5 files changed

+172
-24
lines changed

CHANGELOG.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
## 1.0.0rc1 /2025-01-13
1+
# Changelog
2+
3+
## 1.0.0rc2 /2025-01-15
4+
5+
## What's Changed
6+
* Improve ScaleObj by @roman-opentensor in https://github.com/opentensor/async-substrate-interface/pull/2
7+
8+
## 1.0.0rc1 /2025-01-15
29

310
## What's Changed
411
* New Async Substrate Interface by @thewhaleking and @roman-opentensor in https://github.com/opentensor/async-substrate-interface/tree/main

async_substrate_interface/substrate_interface.py

+103-19
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import ssl
1313
import time
1414
from collections import defaultdict
15+
from collections.abc import Iterable
1516
from dataclasses import dataclass
1617
from datetime import datetime
1718
from hashlib import blake2b
@@ -51,29 +52,117 @@
5152

5253

5354
class ScaleObj:
54-
def __new__(cls, value):
55-
if isinstance(value, (dict, str, int)):
56-
return value
57-
return super().__new__(cls)
55+
"""Bittensor representation of Scale Object."""
5856

5957
def __init__(self, value):
6058
self.value = list(value) if isinstance(value, tuple) else value
6159

60+
def __new__(cls, value):
61+
return super().__new__(cls)
62+
6263
def __str__(self):
6364
return f"BittensorScaleType(value={self.value})>"
6465

66+
def __bool__(self):
67+
if self.value:
68+
return True
69+
else:
70+
return False
71+
6572
def __repr__(self):
66-
return repr(self.value)
73+
return repr(f"BittensorScaleType(value={self.value})>")
6774

6875
def __eq__(self, other):
69-
return self.value == other
76+
return self.value == (other.value if isinstance(other, ScaleObj) else other)
77+
78+
def __lt__(self, other):
79+
return self.value < (other.value if isinstance(other, ScaleObj) else other)
80+
81+
def __gt__(self, other):
82+
return self.value > (other.value if isinstance(other, ScaleObj) else other)
83+
84+
def __le__(self, other):
85+
return self.value <= (other.value if isinstance(other, ScaleObj) else other)
86+
87+
def __ge__(self, other):
88+
return self.value >= (other.value if isinstance(other, ScaleObj) else other)
89+
90+
def __add__(self, other):
91+
if isinstance(other, ScaleObj):
92+
return ScaleObj(self.value + other.value)
93+
return ScaleObj(self.value + other)
94+
95+
def __radd__(self, other):
96+
return ScaleObj(other + self.value)
97+
98+
def __sub__(self, other):
99+
if isinstance(other, ScaleObj):
100+
return ScaleObj(self.value - other.value)
101+
return ScaleObj(self.value - other)
102+
103+
def __rsub__(self, other):
104+
return ScaleObj(other - self.value)
105+
106+
def __mul__(self, other):
107+
if isinstance(other, ScaleObj):
108+
return ScaleObj(self.value * other.value)
109+
return ScaleObj(self.value * other)
110+
111+
def __rmul__(self, other):
112+
return ScaleObj(other * self.value)
113+
114+
def __truediv__(self, other):
115+
if isinstance(other, ScaleObj):
116+
return ScaleObj(self.value / other.value)
117+
return ScaleObj(self.value / other)
118+
119+
def __rtruediv__(self, other):
120+
return ScaleObj(other / self.value)
121+
122+
def __floordiv__(self, other):
123+
if isinstance(other, ScaleObj):
124+
return ScaleObj(self.value // other.value)
125+
return ScaleObj(self.value // other)
126+
127+
def __rfloordiv__(self, other):
128+
return ScaleObj(other // self.value)
129+
130+
def __mod__(self, other):
131+
if isinstance(other, ScaleObj):
132+
return ScaleObj(self.value % other.value)
133+
return ScaleObj(self.value % other)
134+
135+
def __rmod__(self, other):
136+
return ScaleObj(other % self.value)
137+
138+
def __pow__(self, other):
139+
if isinstance(other, ScaleObj):
140+
return ScaleObj(self.value**other.value)
141+
return ScaleObj(self.value**other)
142+
143+
def __rpow__(self, other):
144+
return ScaleObj(other**self.value)
145+
146+
def __getitem__(self, key):
147+
if isinstance(self.value, (list, tuple, dict, str)):
148+
return self.value[key]
149+
raise TypeError(
150+
f"Object of type '{type(self.value).__name__}' does not support indexing"
151+
)
70152

71153
def __iter__(self):
72-
for item in self.value:
73-
yield item
154+
if isinstance(self.value, Iterable):
155+
return iter(self.value)
156+
raise TypeError(f"Object of type '{type(self.value).__name__}' is not iterable")
74157

75-
def __getitem__(self, item):
76-
return self.value[item]
158+
def __len__(self):
159+
return len(self.value)
160+
161+
def serialize(self):
162+
return self.value
163+
164+
def decode(self):
165+
return self.value
77166

78167

79168
class AsyncExtrinsicReceipt:
@@ -998,10 +1087,7 @@ def __init__(
9981087
)
9991088
if pre_initialize:
10001089
if not _mock:
1001-
execute_coroutine(
1002-
coroutine=self.initialize(),
1003-
event_loop=self.event_loop,
1004-
)
1090+
self.event_loop.create_task(self.initialize())
10051091
else:
10061092
self.reload_type_registry()
10071093

@@ -3478,9 +3564,9 @@ async def query(
34783564
raw_storage_key: Optional[bytes] = None,
34793565
subscription_handler=None,
34803566
reuse_block_hash: bool = False,
3481-
) -> "ScaleType":
3567+
) -> Optional[Union["ScaleObj", Any]]:
34823568
"""
3483-
Queries subtensor. This should only be used when making a single request. For multiple requests,
3569+
Queries substrate. This should only be used when making a single request. For multiple requests,
34843570
you should use ``self.query_multiple``
34853571
"""
34863572
block_hash = await self._get_current_block_hash(block_hash, reuse_block_hash)
@@ -3524,7 +3610,7 @@ async def query_map(
35243610
page_size: int = 100,
35253611
ignore_decoding_errors: bool = False,
35263612
reuse_block_hash: bool = False,
3527-
) -> "QueryMapResult":
3613+
) -> QueryMapResult:
35283614
"""
35293615
Iterates over all key-pairs located at the given module and storage_function. The storage
35303616
item must be a map.
@@ -3686,9 +3772,7 @@ def concat_hash_len(key_hasher: str) -> int:
36863772
if not ignore_decoding_errors:
36873773
raise
36883774
item_value = None
3689-
36903775
result.append([item_key, item_value])
3691-
36923776
return QueryMapResult(
36933777
records=result,
36943778
page_size=page_size,

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "async-substrate-interface"
3-
version = "1.0.0rc1"
3+
version = "1.0.0rc2"
44
description = "Asyncio library for interacting with substrate. Mostly API-compatible with py-substrate-interface"
55
readme = "README.md"
66
license = { file = "LICENSE" }

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name="async-substrate-interface",
5-
version="1.0.0rc1",
5+
version="1.0.0rc2",
66
description="Asyncio library for interacting with substrate.",
77
long_description=open("README.md").read(),
88
long_description_content_type="text/markdown",
+59-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,68 @@
1+
import asyncio
12
import pytest
23
from websockets.exceptions import InvalidURI
34

4-
from async_substrate_interface.substrate_interface import AsyncSubstrateInterface
5+
from async_substrate_interface.substrate_interface import (
6+
AsyncSubstrateInterface,
7+
ScaleObj,
8+
)
59

610

711
@pytest.mark.asyncio
812
async def test_invalid_url_raises_exception():
913
"""Test that invalid URI raises an InvalidURI exception."""
1014
with pytest.raises(InvalidURI):
11-
AsyncSubstrateInterface("non_existent_entry_point")
15+
async with AsyncSubstrateInterface("non_existent_entry_point"):
16+
pass
17+
18+
19+
def test_scale_object():
20+
"""Verifies that the instance can be subject to various operations."""
21+
# Preps
22+
inst_int = ScaleObj(100)
23+
24+
# Asserts
25+
assert inst_int + 1 == 101
26+
assert 1 + inst_int == 101
27+
assert inst_int - 1 == 99
28+
assert 101 - inst_int == 1
29+
assert inst_int * 2 == 200
30+
assert 2 * inst_int == 200
31+
assert inst_int / 2 == 50
32+
assert 100 / inst_int == 1
33+
assert inst_int // 2 == 50
34+
assert 1001 // inst_int == 10
35+
assert inst_int % 3 == 1
36+
assert 1002 % inst_int == 2
37+
assert inst_int >= 99
38+
assert inst_int <= 101
39+
40+
# Preps
41+
inst_str = ScaleObj("test")
42+
43+
# Asserts
44+
assert inst_str + "test1" == "testtest1"
45+
assert "test1" + inst_str == "test1test"
46+
assert inst_str * 2 == "testtest"
47+
assert 2 * inst_str == "testtest"
48+
assert inst_str >= "test"
49+
assert inst_str <= "testtest"
50+
assert inst_str[0] == "t"
51+
assert [i for i in inst_str] == ["t", "e", "s", "t"]
52+
53+
# Preps
54+
inst_list = ScaleObj([1, 2, 3])
55+
56+
# Asserts
57+
assert inst_list[0] == 1
58+
assert inst_list[-1] == 3
59+
assert inst_list * 2 == inst_list + inst_list
60+
assert [i for i in inst_list] == [1, 2, 3]
61+
assert inst_list >= [1, 2]
62+
assert inst_list <= [1, 2, 3, 4]
63+
assert len(inst_list) == 3
64+
65+
inst_dict = ScaleObj({"a": 1, "b": 2})
66+
assert inst_dict["a"] == 1
67+
assert inst_dict["b"] == 2
68+
assert [i for i in inst_dict] == ["a", "b"]

0 commit comments

Comments
 (0)