Skip to content
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
33 changes: 15 additions & 18 deletions packages/polywrap-client/polywrap_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,19 @@

from dataclasses import dataclass
from textwrap import dedent
from typing import Any, List, Optional, Union, cast
from typing import Any, Dict, List, Optional, Union, cast

from polywrap_core import (
Client,
ClientConfig,
Env,
GetEnvsOptions,
GetFileOptions,
GetManifestOptions,
GetUriResolversOptions,
InterfaceImplementations,
InvokerOptions,
IUriResolutionContext,
IUriResolver,
TryResolveUriOptions,
Env,
Uri,
UriPackage,
UriPackageOrWrapper,
Expand Down Expand Up @@ -51,24 +49,25 @@ def get_uri_resolver(
) -> IUriResolver:
return self._config.resolver

def get_envs(self, options: Optional[GetEnvsOptions] = None) -> List[Env]:
return self._config.envs
def get_envs(self) -> Dict[Uri, Env]:
envs: Dict[Uri, Env] = self._config.envs
return envs

def get_interfaces(self) -> List[InterfaceImplementations]:
return self._config.interfaces
def get_interfaces(self) -> Dict[Uri, List[Uri]]:
interfaces: Dict[Uri, List[Uri]] = self._config.interfaces
return interfaces

def get_implementations(self, uri: Uri) -> Result[List[Uri]]:
if interface_implementations := next(
filter(lambda x: x.interface == uri, self._config.interfaces), None
):
return Ok(interface_implementations.implementations)
def get_implementations(self, uri: Uri) -> Result[Union[List[Uri], None]]:
interfaces: Dict[Uri, List[Uri]] = self.get_interfaces()
if interfaces.get(uri):
return Ok(interfaces.get(uri))
else:
return Err.from_str(f"Unable to find implementations for uri: {uri}")

def get_env_by_uri(
self, uri: Uri, options: Optional[GetEnvsOptions] = None
self, uri: Uri
) -> Union[Env, None]:
return next(filter(lambda env: env.uri == uri, self.get_envs()), None)
return self._config.envs.get(uri)

async def get_file(
self, uri: Uri, options: GetFileOptions
Expand Down Expand Up @@ -139,9 +138,7 @@ async def invoke(self, options: InvokerOptions) -> Result[Any]:
if wrapper_result.is_err():
return cast(Err, wrapper_result)
wrapper = wrapper_result.unwrap()

env = self.get_env_by_uri(options.uri)
options.env = options.env or (env.env if env else None)
options.env = options.env or self.get_env_by_uri(options.uri)

result = await wrapper.invoke(options, invoker=self)
if result.is_err():
Expand Down
39 changes: 26 additions & 13 deletions packages/polywrap-client/tests/test_client.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from pathlib import Path

import pytest
from polywrap_client import PolywrapClient
from polywrap_core import Uri, InvokerOptions, InterfaceImplementations, Env
from polywrap_core import Uri, InvokerOptions
from polywrap_uri_resolvers import BaseUriResolver, SimpleFileReader

from polywrap_result import Ok
from polywrap_client.client import PolywrapClientConfig


Expand Down Expand Up @@ -31,7 +31,7 @@ async def test_subinvoke():
},
)

client = PolywrapClient(config=PolywrapClientConfig(envs=[], resolver=uri_resolver))
client = PolywrapClient(config=PolywrapClientConfig(resolver=uri_resolver))
uri = Uri(
f'fs/{Path(__file__).parent.joinpath("cases", "simple-subinvoke", "invoke").absolute()}'
)
Expand All @@ -48,19 +48,15 @@ async def test_interface_implementation():
redirects={},
)

interface_uri = Uri("ens/interface.eth")
impl_uri = Uri(
f'fs/{Path(__file__).parent.joinpath("cases", "simple-interface", "implementation").absolute()}'
)

client = PolywrapClient(
config=PolywrapClientConfig(
envs=[],
resolver=uri_resolver,
interfaces=[
InterfaceImplementations(
interface=Uri("ens/interface.eth"), implementations=[impl_uri]
)
],
interfaces= {interface_uri : [impl_uri]}
)
)
uri = Uri(
Expand All @@ -71,10 +67,26 @@ async def test_interface_implementation():
uri=uri, method="moduleMethod", args=args, encode_result=False
)
result = await client.invoke(options)

assert client.get_implementations(interface_uri) == Ok([impl_uri])
assert result.unwrap() == {"str": "hello", "uint8": 2}


def test_get_env_by_uri():
uri_resolver = BaseUriResolver(
file_reader=SimpleFileReader(),
redirects={},
)
uri = Uri(f'fs/{Path(__file__).parent.joinpath("cases", "simple-env").absolute()}')
env = {"externalArray": [1, 2, 3], "externalString": "hello"}

client = PolywrapClient(
config=PolywrapClientConfig(
envs={uri: env},
resolver=uri_resolver,
)
)
assert client.get_env_by_uri(uri) == env

async def test_env():
uri_resolver = BaseUriResolver(
file_reader=SimpleFileReader(),
Expand All @@ -86,13 +98,14 @@ async def test_env():

client = PolywrapClient(
config=PolywrapClientConfig(
envs=[Env(uri=uri, env=env)],
envs={uri: env},
resolver=uri_resolver,
)
)
options = InvokerOptions(
uri=uri, method="externalEnvMethod", args={}, encode_result=False
uri=uri, method="externalEnvMethod", args={}, encode_result=False,
)

result = await client.invoke(options)

assert result.unwrap() == env
2 changes: 0 additions & 2 deletions packages/polywrap-client/tests/test_sha3.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ async def test_invoke_sha3_512():
result = await client.invoke(options)
s = hashlib.sha512()
s.update(b"hello polywrap!")
print(result)
assert result.result == s.digest()

@pytest.mark.skip(reason="can't invoke sha3 wrapper due to an error related to wasmtime")
Expand Down Expand Up @@ -90,7 +89,6 @@ async def test_invoke_hex_keccak_256():
async def test_invoke_buffer_keccak_256():
options = InvokerOptions(uri=uri, method="buffer_keccak_256", args=args, encode_result=False)
result = await client.invoke(options)
print(result)
# TODO: Not sure exactly what this function `buffer_keccak_256` is doing in order to assert it properly
assert result.result == False

Expand Down
1 change: 0 additions & 1 deletion packages/polywrap-core/polywrap_core/types/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from .client import *
from .env import *
from .file_reader import *
from .invoke import *
from .uri import *
Expand Down
21 changes: 7 additions & 14 deletions packages/polywrap-core/polywrap_core/types/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,24 @@

from abc import abstractmethod
from dataclasses import dataclass, field
from typing import List, Optional, Union
from typing import List, Optional, Union, Dict

from polywrap_manifest import AnyWrapManifest, DeserializeManifestOptions
from polywrap_result import Result

from .env import Env
from .interface_implementation import InterfaceImplementations
from .invoke import Invoker
from .uri import Uri
from .env import Env
from .uri_resolver import IUriResolver
from .uri_resolver_handler import UriResolverHandler


@dataclass(slots=True, kw_only=True)
class ClientConfig:
envs: List[Env] = field(default_factory=list)
interfaces: List[InterfaceImplementations] = field(default_factory=list)
envs: Dict[Uri, Env] = field(default_factory=dict)
interfaces: Dict[Uri, List[Uri]] = field(default_factory=dict)
resolver: IUriResolver


@dataclass(slots=True, kw_only=True)
class GetEnvsOptions:
pass


@dataclass(slots=True, kw_only=True)
class GetUriResolversOptions:
pass
Expand All @@ -45,16 +38,16 @@ class GetManifestOptions(DeserializeManifestOptions):

class Client(Invoker, UriResolverHandler):
@abstractmethod
def get_interfaces(self) -> List[InterfaceImplementations]:
def get_interfaces(self) -> Dict[Uri, List[Uri]]:
pass

@abstractmethod
def get_envs(self, options: Optional[GetEnvsOptions] = None) -> List[Env]:
def get_envs(self) -> Dict[Uri, Env]:
pass

@abstractmethod
def get_env_by_uri(
self, uri: Uri, options: Optional[GetEnvsOptions] = None
self, uri: Uri
) -> Union[Env, None]:
pass

Expand Down
19 changes: 1 addition & 18 deletions packages/polywrap-core/polywrap_core/types/env.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,3 @@
from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Dict

from .uri import Uri


@dataclass(slots=True, kw_only=True)
class Env:
"""
this type can be used to set env for a wrapper in the client

Args:
uri: Uri of wrapper
env: env variables used by the module
"""

uri: Uri
env: Dict[str, Any] = field(default_factory=dict)
Env = Dict[str, Any]

This file was deleted.

5 changes: 3 additions & 2 deletions packages/polywrap-core/polywrap_core/types/invoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from polywrap_result import Result

from .uri import Uri
from .env import Env
from .uri_resolution_context import IUriResolutionContext


Expand All @@ -26,7 +27,7 @@ class InvokeOptions:
uri: Uri
method: str
args: Optional[Union[Dict[str, Any], bytes]] = field(default_factory=dict)
env: Optional[Dict[str, Any]] = None
env: Optional[Env] = None
resolution_context: Optional[IUriResolutionContext] = None


Expand Down Expand Up @@ -55,7 +56,7 @@ async def invoke(self, options: InvokerOptions) -> Result[Any]:
pass

@abstractmethod
def get_implementations(self, uri: Uri) -> Result[List[Uri]]:
def get_implementations(self, uri: Uri) -> Result[Union[List[Uri], None]]:
pass


Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from typing import List, Union
from typing import List, Union, Dict, Any

from ..types import Client, Env, Uri


def get_env_from_uri_history(
uri_history: List[Uri], client: Client
) -> Union[Env, None]:
) -> Union[Dict[str, Any], None]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use the Env type here? It helps me better understand what this code is doing.

for uri in uri_history:
return client.get_env_by_uri(uri)
7 changes: 1 addition & 6 deletions packages/polywrap-msgpack/polywrap_msgpack/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,7 @@ def sanitize(value: Any) -> Any:
if isinstance(value, dict):
dictionary: Dict[Any, Any] = value
for key, val in dictionary.items():
if isinstance(key, str):
dictionary[key] = sanitize(val)
else:
raise ValueError(
f"expected dict key to be str received {key} with type {type(key)}"
)
dictionary[str(key)] = sanitize(val)
return dictionary
if isinstance(value, list):
array: List[Any] = value
Expand Down