Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(core): update pydantic in uagents #419

Merged
merged 3 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,704 changes: 1,148 additions & 556 deletions python/poetry.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ readme = "README.md"

[tool.poetry.dependencies]
python = ">=3.9,<3.13"
pydantic = "^1.10.2"
pydantic = "~2.7"
msgpack = "^1.0.4"
bech32 = "^1.2.0"
ecdsa = "^0.18.0"
apispec = "^6.0.2"
uvicorn = "^0.20.0"
uvicorn = "~0.30.1"
aiohttp = "^3.8.3"
cosmpy = "^0.9.2"
websockets = "^10.4"
Expand All @@ -28,7 +28,7 @@ fetchai-babble = { version = "^0.4.1", optional = true }
tortoise-orm = { version = "^0.19.2", optional = true }
geopy = { version = "^2.3.0", optional = true }
pyngrok = { version = "^5.2.3", optional = true }
fastapi = { version = "^0.97.0", optional = true }
fastapi = { version = "^0.111.0", optional = true }

[tool.poetry.group.dev.dependencies]
aioresponses = "^0.7.4"
Expand Down
4 changes: 3 additions & 1 deletion python/src/uagents/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,9 @@ async def __call__(self, scope, receive, send): # pylint: disable=too-many-bra
if (env.expires is not None) and (
datetime.now() > datetime.fromtimestamp(env.expires)
):
response_msg = ErrorMessage(error="Query envelope expired").json()
response_msg = ErrorMessage(
error="Query envelope expired"
).model_dump_json()
schema_digest = ERROR_MESSAGE_DIGEST
sender = env.target
target = env.sender
Expand Down
8 changes: 4 additions & 4 deletions python/src/uagents/communication.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,13 @@ async def send_exchange_envelope(
async with session.post(
endpoint,
headers=headers,
data=envelope.json(),
data=envelope.model_dump_json(),
) as resp:
success = resp.status == 200
if success:
if sync:
return await dispatch_sync_response_envelope(
Envelope.parse_obj(await resp.json())
Envelope.model_validate(await resp.json())
)
return MsgStatus(
status=DeliveryStatus.DELIVERED,
Expand Down Expand Up @@ -260,7 +260,7 @@ async def send_sync_message(
schema_digest=Model.build_schema_digest(message),
expires=int(time()) + timeout,
)
env.encode_payload(message.json())
env.encode_payload(message.model_dump_json())
env.sign(sender.sign_digest)

response = await send_exchange_envelope(
Expand All @@ -271,6 +271,6 @@ async def send_sync_message(
if isinstance(response, Envelope):
json_message = response.decode_payload()
if response_type:
return response_type.parse_raw(json_message)
return response_type.model_validate_json(json_message)
return json_message
return response
4 changes: 2 additions & 2 deletions python/src/uagents/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ async def send(
"""
self._session = None
schema_digest = Model.build_schema_digest(message)
message_body = message.json()
message_body = message.model_dump_json()

if not self._is_valid_interval_message(schema_digest):
log(self.logger, logging.ERROR, f"Invalid interval message: {message}")
Expand Down Expand Up @@ -673,7 +673,7 @@ async def send(
return await self.send_raw(
destination,
schema_digest,
message.json(),
message.model_dump_json(),
sync=sync,
timeout=timeout,
protocol_digest=self._protocol[0],
Expand Down
4 changes: 2 additions & 2 deletions python/src/uagents/experimental/dialogues/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ def _pre_handle_hook(self, ctx: Context, sender: str, message: Type[Model]) -> b
schema_digest=schema_digest,
sender=ctx.agent.address,
receiver=sender,
content=message.json(), # type: ignore
content=message.model_dump_json(), # type: ignore
)
return is_valid

Expand Down Expand Up @@ -677,7 +677,7 @@ async def start_dialogue(
schema_digest=message_schema_digest,
sender=ctx.agent.address,
receiver=status.destination,
content=message.json(),
content=message.model_dump_json(),
)
self.update_state(message_schema_digest, status.session)

Expand Down
8 changes: 5 additions & 3 deletions python/src/uagents/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import hashlib
import json
from typing import Type, Union

from pydantic import BaseModel
Expand All @@ -7,10 +8,9 @@
class Model(BaseModel):
@staticmethod
def build_schema_digest(model: Union["Model", Type["Model"]]) -> str:
schema = model.model_json_schema()
digest = (
hashlib.sha256(
model.schema_json(indent=None, sort_keys=True).encode("utf8")
)
hashlib.sha256(json.dumps(schema, sort_keys=True).encode("utf8"))
.digest()
.hex()
)
Expand All @@ -19,4 +19,6 @@ def build_schema_digest(model: Union["Model", Type["Model"]]) -> str:


class ErrorMessage(Model):
"""Error message model"""

error: str
12 changes: 7 additions & 5 deletions python/src/uagents/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ async def query(
resolver = GlobalResolver()

# convert the message into object form
json_message = message.json()
json_message = message.model_dump_json()
schema_digest = Model.build_schema_digest(message)

# resolve the endpoint
Expand Down Expand Up @@ -74,14 +74,14 @@ async def query(
"content-type": "application/json",
"x-uagents-connection": "sync",
},
data=env.json(),
data=env.model_dump_json(),
timeout=timeout,
) as response,
):
success = response.status == 200

if success:
return Envelope.parse_obj(await response.json())
return Envelope.model_validate(await response.json())
except aiohttp.ClientConnectorError as ex:
LOGGER.warning(f"Failed to connect to {endpoint}: {ex}")
except Exception as ex:
Expand All @@ -108,7 +108,9 @@ def enclose_response(
str: The JSON representation of the response envelope.
"""
schema_digest = Model.build_schema_digest(message)
return enclose_response_raw(message.json(), schema_digest, sender, session, target)
return enclose_response_raw(
message.model_dump_json(), schema_digest, sender, session, target
)


def enclose_response_raw(
Expand Down Expand Up @@ -139,4 +141,4 @@ def enclose_response_raw(
schema_digest=schema_digest,
)
response_env.encode_payload(json_message)
return response_env.json()
return response_env.model_dump_json()
2 changes: 1 addition & 1 deletion python/tests/test_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ async def test_send_resolve_sync_query(self):
session=context.session,
)

self.assertEqual(future.result(), (msg.json(), msg_digest))
self.assertEqual(future.result(), (msg.model_dump_json(), msg_digest))
self.assertEqual(result, exp_msg_status)
self.assertEqual(len(context._queries), 0, "Query not removed from context")

Expand Down
40 changes: 20 additions & 20 deletions python/tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ async def mock_process_sync_message(self, sender: str, msg: Model):
while True:
if sender in self.agent._server._queries:
self.agent._server._queries[sender].set_result(
(msg.json(), Model.build_schema_digest(msg))
(msg.model_dump_json(), Model.build_schema_digest(msg))
)
return

Expand All @@ -38,12 +38,12 @@ async def test_message_success(self):
session=uuid.uuid4(),
schema_digest=Model.build_schema_digest(message),
)
env.encode_payload(message.json())
env.encode_payload(message.model_dump_json())
env.sign(self.bob._identity.sign_digest)

mock_send = AsyncMock()
with patch("uagents.asgi._read_asgi_body") as mock_receive:
mock_receive.return_value = env.json().encode()
mock_receive.return_value = env.model_dump_json().encode()
await self.agent._server(
scope={
"type": "http",
Expand Down Expand Up @@ -83,11 +83,11 @@ async def test_message_success_unsigned(self):
session=session,
schema_digest=Model.build_schema_digest(message),
)
env.encode_payload(message.json())
env.encode_payload(message.model_dump_json())

mock_send = AsyncMock()
with patch("uagents.asgi._read_asgi_body") as mock_receive:
mock_receive.return_value = env.json().encode()
mock_receive.return_value = env.model_dump_json().encode()
await self.agent._server(
scope={
"type": "http",
Expand Down Expand Up @@ -128,10 +128,10 @@ async def test_message_success_sync(self):
session=session,
schema_digest=Model.build_schema_digest(message),
)
env.encode_payload(message.json())
env.encode_payload(message.model_dump_json())
mock_send = AsyncMock()
with patch("uagents.asgi._read_asgi_body") as mock_receive:
mock_receive.return_value = env.json().encode()
mock_receive.return_value = env.model_dump_json().encode()
await asyncio.gather(
asyncio.create_task(
self.agent._server(
Expand Down Expand Up @@ -180,11 +180,11 @@ async def test_message_success_sync_signed(self):
session=session,
schema_digest=Model.build_schema_digest(message),
)
env.encode_payload(message.json())
env.encode_payload(message.model_dump_json())
env.sign(self.bob._identity.sign_digest)
mock_send = AsyncMock()
with patch("uagents.asgi._read_asgi_body") as mock_receive:
mock_receive.return_value = env.json().encode()
mock_receive.return_value = env.model_dump_json().encode()
await asyncio.gather(
asyncio.create_task(
self.agent._server(
Expand Down Expand Up @@ -235,12 +235,12 @@ async def test_message_fail_wrong_path(self):
session=uuid.uuid4(),
schema_digest=Model.build_schema_digest(message),
)
env.encode_payload(message.json())
env.encode_payload(message.model_dump_json())
env.sign(self.bob._identity.sign_digest)

mock_send = AsyncMock()
with patch("uagents.asgi._read_asgi_body") as mock_receive:
mock_receive.return_value = env.json().encode()
mock_receive.return_value = env.model_dump_json().encode()
await self.agent._server(
scope={
"type": "http",
Expand Down Expand Up @@ -278,12 +278,12 @@ async def test_message_fail_wrong_headers(self):
session=uuid.uuid4(),
schema_digest=Model.build_schema_digest(message),
)
env.encode_payload(message.json())
env.encode_payload(message.model_dump_json())
env.sign(self.bob._identity.sign_digest)

mock_send = AsyncMock()
with patch("uagents.asgi._read_asgi_body") as mock_receive:
mock_receive.return_value = env.json().encode()
mock_receive.return_value = env.model_dump_json().encode()
await self.agent._server(
scope={
"type": "http",
Expand Down Expand Up @@ -316,7 +316,7 @@ async def test_message_fail_bad_data(self):
message = Message(message="hello")
mock_send = AsyncMock()
with patch("uagents.asgi._read_asgi_body") as mock_receive:
mock_receive.return_value = message.json().encode()
mock_receive.return_value = message.model_dump_json().encode()
await self.agent._server(
scope={
"type": "http",
Expand Down Expand Up @@ -354,11 +354,11 @@ async def test_message_fail_unsigned(self):
session=uuid.uuid4(),
schema_digest=Model.build_schema_digest(message),
)
env.encode_payload(message.json())
env.encode_payload(message.model_dump_json())

mock_send = AsyncMock()
with patch("uagents.asgi._read_asgi_body") as mock_receive:
mock_receive.return_value = env.json().encode()
mock_receive.return_value = env.model_dump_json().encode()
await self.agent._server(
scope={
"type": "http",
Expand Down Expand Up @@ -396,12 +396,12 @@ async def test_message_fail_verify(self):
session=uuid.uuid4(),
schema_digest=Model.build_schema_digest(message),
)
env.encode_payload(message.json())
env.encode_payload(message.model_dump_json())
env.sign(self.agent._identity.sign_digest)

mock_send = AsyncMock()
with patch("uagents.asgi._read_asgi_body") as mock_receive:
mock_receive.return_value = env.json().encode()
mock_receive.return_value = env.model_dump_json().encode()
await self.agent._server(
scope={
"type": "http",
Expand Down Expand Up @@ -439,12 +439,12 @@ async def test_message_fail_dispatch(self):
session=uuid.uuid4(),
schema_digest=Model.build_schema_digest(message),
)
env.encode_payload(message.json())
env.encode_payload(message.model_dump_json())
env.sign(self.bob._identity.sign_digest)

mock_send = AsyncMock()
with patch("uagents.asgi._read_asgi_body") as mock_receive:
mock_receive.return_value = env.json().encode()
mock_receive.return_value = env.model_dump_json().encode()
await self.agent._server(
scope={
"type": "http",
Expand Down
Loading