diff --git a/packages/polywrap-client/tests/test_plugin_wrapper.py b/packages/polywrap-client/tests/test_plugin_wrapper.py new file mode 100644 index 00000000..9906e2b8 --- /dev/null +++ b/packages/polywrap-client/tests/test_plugin_wrapper.py @@ -0,0 +1 @@ +# Encode - Decode need to be tested \ No newline at end of file diff --git a/packages/polywrap-client/tests/test_wasm_wrapper.py b/packages/polywrap-client/tests/test_wasm_wrapper.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-core/poetry.lock b/packages/polywrap-core/poetry.lock index 97622e7a..80d92f84 100644 --- a/packages/polywrap-core/poetry.lock +++ b/packages/polywrap-core/poetry.lock @@ -1,15 +1,15 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry and should not be changed by hand. [[package]] name = "astroid" -version = "2.15.4" +version = "2.15.5" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false python-versions = ">=3.7.2" files = [ - {file = "astroid-2.15.4-py3-none-any.whl", hash = "sha256:a1b8543ef9d36ea777194bc9b17f5f8678d2c56ee6a45b2c2f17eec96f242347"}, - {file = "astroid-2.15.4.tar.gz", hash = "sha256:c81e1c7fbac615037744d067a9bb5f9aeb655edf59b63ee8b59585475d6f80d8"}, + {file = "astroid-2.15.5-py3-none-any.whl", hash = "sha256:078e5212f9885fa85fbb0cf0101978a336190aadea6e13305409d099f71b2324"}, + {file = "astroid-2.15.5.tar.gz", hash = "sha256:1039262575027b441137ab4a62a793a9b43defb42c32d5670f38686207cd780f"}, ] [package.dependencies] @@ -455,14 +455,14 @@ files = [ [[package]] name = "nodeenv" -version = "1.7.0" +version = "1.8.0" description = "Node.js virtual environment builder" category = "dev" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" files = [ - {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, - {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, ] [package.dependencies] @@ -506,18 +506,18 @@ files = [ [[package]] name = "platformdirs" -version = "3.5.0" +version = "3.5.1" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.5.0-py3-none-any.whl", hash = "sha256:47692bc24c1958e8b0f13dd727307cff1db103fca36399f457da8e05f222fdc4"}, - {file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"}, + {file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"}, + {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"}, ] [package.extras] -docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] @@ -655,21 +655,6 @@ typing-extensions = ">=4.2.0" dotenv = ["python-dotenv (>=0.10.4)"] email = ["email-validator (>=1.0.3)"] -[[package]] -name = "pydeps" -version = "1.12.3" -description = "Display module dependencies" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "pydeps-1.12.3-py3-none-any.whl", hash = "sha256:d828ab178244f147119a4aa3757a0ffa062e2069b1ac3c244f3013bfdfe0aa5e"}, - {file = "pydeps-1.12.3.tar.gz", hash = "sha256:3f14f2d5ef04df050317a6ed4747e7fefd14399f9decfe5114271541b1b8ffe7"}, -] - -[package.dependencies] -stdlib-list = "*" - [[package]] name = "pydocstyle" version = "6.3.0" @@ -734,14 +719,14 @@ testutils = ["gitpython (>3)"] [[package]] name = "pyright" -version = "1.1.306" +version = "1.1.309" description = "Command line wrapper for pyright" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pyright-1.1.306-py3-none-any.whl", hash = "sha256:008eb2a29584ae274a154d749cf81476a3073fb562a462eac8d43a753378b9db"}, - {file = "pyright-1.1.306.tar.gz", hash = "sha256:16d5d198be64de497d5f9002000a271176c381e21b977ca5566cf779b643c9ed"}, + {file = "pyright-1.1.309-py3-none-any.whl", hash = "sha256:a8b052c1997f7334e80074998ea0f93bd149550e8cf27ccb5481d3b2e1aad161"}, + {file = "pyright-1.1.309.tar.gz", hash = "sha256:1abcfa83814d792a5d70b38621cc6489acfade94ebb2279e55ba1f394d54296c"}, ] [package.dependencies] @@ -774,24 +759,6 @@ tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] -[[package]] -name = "pytest-asyncio" -version = "0.19.0" -description = "Pytest support for asyncio" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pytest-asyncio-0.19.0.tar.gz", hash = "sha256:ac4ebf3b6207259750bc32f4c1d8fcd7e79739edbc67ad0c58dd150b1d072fed"}, - {file = "pytest_asyncio-0.19.0-py3-none-any.whl", hash = "sha256:7a97e37cfe1ed296e2e84941384bdd37c376453912d397ed39293e0916f521fa"}, -] - -[package.dependencies] -pytest = ">=6.1.0" - -[package.extras] -testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] - [[package]] name = "pyyaml" version = "6.0" @@ -863,19 +830,19 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "setuptools" -version = "67.7.2" +version = "67.8.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "setuptools-67.7.2-py3-none-any.whl", hash = "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b"}, - {file = "setuptools-67.7.2.tar.gz", hash = "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"}, + {file = "setuptools-67.8.0-py3-none-any.whl", hash = "sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f"}, + {file = "setuptools-67.8.0.tar.gz", hash = "sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] @@ -914,31 +881,16 @@ files = [ {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, ] -[[package]] -name = "stdlib-list" -version = "0.8.0" -description = "A list of Python Standard Libraries (2.6-7, 3.2-9)." -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "stdlib-list-0.8.0.tar.gz", hash = "sha256:a1e503719720d71e2ed70ed809b385c60cd3fb555ba7ec046b96360d30b16d9f"}, - {file = "stdlib_list-0.8.0-py3-none-any.whl", hash = "sha256:2ae0712a55b68f3fbbc9e58d6fa1b646a062188f49745b495f94d3310a9fdd3e"}, -] - -[package.extras] -develop = ["sphinx"] - [[package]] name = "stevedore" -version = "5.0.0" +version = "5.1.0" description = "Manage dynamic plugins for Python applications" category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "stevedore-5.0.0-py3-none-any.whl", hash = "sha256:bd5a71ff5e5e5f5ea983880e4a1dd1bb47f8feebbb3d95b592398e2f02194771"}, - {file = "stevedore-5.0.0.tar.gz", hash = "sha256:2c428d2338976279e8eb2196f7a94910960d9f7ba2f41f3988511e95ca447021"}, + {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"}, + {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"}, ] [package.dependencies] @@ -1049,14 +1001,14 @@ test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6. [[package]] name = "typing-extensions" -version = "4.5.0" +version = "4.6.0" description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, - {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, + {file = "typing_extensions-4.6.0-py3-none-any.whl", hash = "sha256:6ad00b63f849b7dcc313b70b6b304ed67b2b2963b3098a33efe18056b1a9a223"}, + {file = "typing_extensions-4.6.0.tar.gz", hash = "sha256:ff6b238610c747e44c268aa4bb23c8c735d665a63726df3f9431ce707f2aa768"}, ] [[package]] @@ -1184,4 +1136,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "60e51d986fcb9814b054fb0b6c5a6eea0c84829dc8db4e5cf3c592ade9f5353c" +content-hash = "bd0557df35270b1dcdb727e3505fbd3bdd1afaed488458de3346783456248e00" diff --git a/packages/polywrap-core/polywrap_core/types/__init__.py b/packages/polywrap-core/polywrap_core/types/__init__.py index 219b5d5f..1ce2c342 100644 --- a/packages/polywrap-core/polywrap_core/types/__init__.py +++ b/packages/polywrap-core/polywrap_core/types/__init__.py @@ -1,16 +1,12 @@ """This module contains all the core types used in the various polywrap packages.""" from .client import * from .config import * -from .env import * from .errors import * from .file_reader import * from .invocable import * -from .invoke_args import * from .invoker import * from .invoker_client import * -from .options import * from .uri import * -from .uri_like import * from .uri_package import * from .uri_package_wrapper import * from .uri_resolution_context import * diff --git a/packages/polywrap-core/polywrap_core/types/client.py b/packages/polywrap-core/polywrap_core/types/client.py index b73fa72c..5df1f119 100644 --- a/packages/polywrap-core/polywrap_core/types/client.py +++ b/packages/polywrap-core/polywrap_core/types/client.py @@ -1,25 +1,19 @@ """This module contains the Client interface.""" from __future__ import annotations -from abc import abstractmethod -from typing import Dict, List, Optional, Union +from typing import Any, Dict, List, Optional, Protocol, Union -from polywrap_manifest import AnyWrapManifest +from polywrap_manifest import AnyWrapManifest, DeserializeManifestOptions -from .env import Env from .invoker_client import InvokerClient -from .options.file_options import GetFileOptions -from .options.manifest_options import GetManifestOptions from .uri import Uri -from .uri_package_wrapper import UriPackageOrWrapper from .uri_resolver import UriResolver -class Client(InvokerClient[UriPackageOrWrapper]): +class Client(InvokerClient, Protocol): """Client interface defines core set of functionalities\ for interacting with a wrapper.""" - @abstractmethod def get_interfaces(self) -> Dict[Uri, List[Uri]]: """Get dictionary of interfaces and their implementations. @@ -27,57 +21,64 @@ def get_interfaces(self) -> Dict[Uri, List[Uri]]: Dict[Uri, List[Uri]]: Dictionary of interfaces and their implementations where\ key is interface URI and value is list of implementation uris. """ + ... - @abstractmethod - def get_envs(self) -> Dict[Uri, Env]: + def get_envs(self) -> Dict[Uri, Any]: """Get dictionary of environments. Returns: - Dict[Uri, Env]: Dictionary of environments where key is URI and value is env. + Dict[Uri, Any]: Dictionary of environments where key is URI and value is env. """ + ... - @abstractmethod - def get_env_by_uri(self, uri: Uri) -> Union[Env, None]: + def get_env_by_uri(self, uri: Uri) -> Union[Any, None]: """Get environment by URI. Args: uri (Uri): URI of the Wrapper. Returns: - Union[Env, None]: env if found, otherwise None. + Union[Any, None]: env if found, otherwise None. """ + ... - @abstractmethod def get_uri_resolver(self) -> UriResolver: """Get URI resolver. Returns: - IUriResolver: URI resolver. + UriResolver: URI resolver. """ + ... - @abstractmethod - async def get_file(self, uri: Uri, options: GetFileOptions) -> Union[bytes, str]: + def get_file( + self, uri: Uri, path: str, encoding: Optional[str] = "utf-8" + ) -> Union[bytes, str]: """Get file from URI. Args: uri (Uri): URI of the wrapper. - options (GetFileOptions): Options for getting file from the wrapper. + path (str): Path to the file. + encoding (Optional[str]): Encoding of the file. Returns: Union[bytes, str]]: file contents. """ + ... - @abstractmethod - async def get_manifest( - self, uri: Uri, options: Optional[GetManifestOptions] = None + def get_manifest( + self, uri: Uri, options: Optional[DeserializeManifestOptions] = None ) -> AnyWrapManifest: """Get manifest from URI. Args: uri (Uri): URI of the wrapper. - options (Optional[GetManifestOptions]): \ + options (Optional[DeserializeManifestOptions]): \ Options for getting manifest from the wrapper. Returns: AnyWrapManifest: Manifest of the wrapper. """ + ... + + +__all__ = ["Client"] diff --git a/packages/polywrap-core/polywrap_core/types/config.py b/packages/polywrap-core/polywrap_core/types/config.py index 97afe12c..4b124877 100644 --- a/packages/polywrap-core/polywrap_core/types/config.py +++ b/packages/polywrap-core/polywrap_core/types/config.py @@ -2,9 +2,8 @@ from __future__ import annotations from dataclasses import dataclass, field -from typing import Dict, List +from typing import Any, Dict, List -from .env import Env from .uri import Uri from .uri_resolver import UriResolver @@ -14,7 +13,7 @@ class ClientConfig: """Client configuration. Attributes: - envs (Dict[Uri, Env]): Dictionary of environments \ + envs (Dict[Uri, Any]): Dictionary of environments \ where key is URI and value is env. interfaces (Dict[Uri, List[Uri]]): Dictionary of interfaces \ and their implementations where key is interface URI \ @@ -22,6 +21,9 @@ class ClientConfig: resolver (UriResolver): URI resolver. """ - envs: Dict[Uri, Env] = field(default_factory=dict) + envs: Dict[Uri, Any] = field(default_factory=dict) interfaces: Dict[Uri, List[Uri]] = field(default_factory=dict) resolver: UriResolver + + +__all__ = ["ClientConfig"] diff --git a/packages/polywrap-core/polywrap_core/types/env.py b/packages/polywrap-core/polywrap_core/types/env.py deleted file mode 100644 index 7949d5eb..00000000 --- a/packages/polywrap-core/polywrap_core/types/env.py +++ /dev/null @@ -1,4 +0,0 @@ -"""This module defines Env type.""" -from typing import Any, Dict - -Env = Dict[str, Any] diff --git a/packages/polywrap-core/polywrap_core/types/errors.py b/packages/polywrap-core/polywrap_core/types/errors.py index f445b191..e89e9ea0 100644 --- a/packages/polywrap-core/polywrap_core/types/errors.py +++ b/packages/polywrap-core/polywrap_core/types/errors.py @@ -1,22 +1,31 @@ """This module contains the core wrap errors.""" +# pylint: disable=too-many-arguments + +from __future__ import annotations import json from textwrap import dedent -from typing import Generic, TypeVar +from typing import Any, Optional, cast + +from polywrap_msgpack import GenericMap, msgpack_decode -from polywrap_msgpack import msgpack_decode +from .invoke_options import InvokeOptions +from .uri import Uri -from .options.invoke_options import InvokeOptions -from .uri_like import UriLike -TUriLike = TypeVar("TUriLike", bound=UriLike) +def _default_encoder(obj: Any) -> Any: + if isinstance(obj, bytes): + return list(obj) + if isinstance(obj, (Uri, GenericMap)): + return repr(cast(Any, obj)) + raise TypeError(f"Object of type '{type(obj).__name__}' is not JSON serializable") class WrapError(Exception): """Base class for all exceptions related to wrappers.""" -class WrapAbortError(Generic[TUriLike], WrapError): +class WrapAbortError(WrapError): """Raises when a wrapper aborts execution. Attributes: @@ -25,35 +34,40 @@ class WrapAbortError(Generic[TUriLike], WrapError): message: The message provided by the wrapper. """ - invoke_options: InvokeOptions[TUriLike] + uri: Uri + method: str message: str + invoke_args: Optional[str] = None + invoke_env: Optional[str] = None - # pylint: disable=too-many-arguments def __init__( self, - invoke_options: InvokeOptions[TUriLike], + invoke_options: InvokeOptions, message: str, ): """Initialize a new instance of WasmAbortError.""" - self.invoke_options = invoke_options + self.uri = invoke_options.uri + self.method = invoke_options.method self.message = message - invoke_args = ( + self.invoke_args = ( json.dumps( msgpack_decode(invoke_options.args) if isinstance(invoke_options.args, bytes) else invoke_options.args, indent=2, + default=_default_encoder, ) if invoke_options.args is not None else None ) - invoke_env = ( + self.invoke_env = ( json.dumps( msgpack_decode(invoke_options.env) if isinstance(invoke_options.env, bytes) else invoke_options.env, indent=2, + default=_default_encoder, ) if invoke_options.env is not None else None @@ -65,15 +79,15 @@ def __init__( WrapAbortError: The following wrapper aborted execution with the given message: URI: {invoke_options.uri} Method: {invoke_options.method} - Args: {invoke_args} - env: {invoke_env} + Args: {self.invoke_args} + env: {self.invoke_env} Message: {message} """ ) ) -class WrapInvocationError(WrapAbortError[TUriLike]): +class WrapInvocationError(WrapAbortError): """Raises when there is an error invoking a wrapper. Attributes: @@ -81,3 +95,39 @@ class WrapInvocationError(WrapAbortError[TUriLike]): that was aborted. message: The message provided by the wrapper. """ + + +class WrapGetImplementationsError(WrapError): + """Raises when there is an error getting implementations of an interface. + + Attributes: + uri (Uri): URI of the interface. + message: The message provided by the wrapper. + """ + + uri: Uri + message: str + + def __init__(self, uri: Uri, message: str): + """Initialize a new instance of WrapGetImplementationsError.""" + self.uri = uri + self.message = message + + super().__init__( + dedent( + f""" + WrapGetImplementationsError: Failed to get implementations of \ + the following interface URI with the given message: + URI: {uri} + Message: {message} + """ + ) + ) + + +__all__ = [ + "WrapError", + "WrapAbortError", + "WrapInvocationError", + "WrapGetImplementationsError", +] diff --git a/packages/polywrap-core/polywrap_core/types/file_reader.py b/packages/polywrap-core/polywrap_core/types/file_reader.py index 6067d0cf..848c69fd 100644 --- a/packages/polywrap-core/polywrap_core/types/file_reader.py +++ b/packages/polywrap-core/polywrap_core/types/file_reader.py @@ -1,14 +1,13 @@ """This module contains file reader interface.""" from __future__ import annotations -from abc import ABC, abstractmethod +from typing import Protocol -class FileReader(ABC): +class FileReader(Protocol): """File reader interface.""" - @abstractmethod - async def read_file(self, file_path: str) -> bytes: + def read_file(self, file_path: str) -> bytes: """Read a file from the given file path. Args: @@ -20,3 +19,7 @@ async def read_file(self, file_path: str) -> bytes: Returns: bytes: The file contents. """ + ... + + +__all__ = ["FileReader"] diff --git a/packages/polywrap-core/polywrap_core/types/invocable.py b/packages/polywrap-core/polywrap_core/types/invocable.py index 12c3d44f..847cfdae 100644 --- a/packages/polywrap-core/polywrap_core/types/invocable.py +++ b/packages/polywrap-core/polywrap_core/types/invocable.py @@ -1,15 +1,14 @@ """This module contains the interface for invoking any invocables.""" +# pylint: disable=too-many-arguments + from __future__ import annotations -from abc import ABC, abstractmethod from dataclasses import dataclass -from typing import Any, Generic, Optional, TypeVar - -from .invoker import Invoker -from .options.invoke_options import InvokeOptions -from .uri_like import UriLike +from typing import Any, Optional, Protocol -TUriLike = TypeVar("TUriLike", bound=UriLike) +from .invoker_client import InvokerClient +from .uri import Uri +from .uri_resolution_context import UriResolutionContext @dataclass(slots=True, kw_only=True) @@ -17,29 +16,43 @@ class InvocableResult: """Result of a wrapper invocation. Args: - result (Optional[Any]): Invocation result. The type of this value is \ + result (Any): Invocation result. The type of this value is \ the return type of the method. encoded (Optional[bool]): It will be set true if result is encoded """ - result: Optional[Any] = None + result: Any encoded: Optional[bool] = None -class Invocable(ABC, Generic[TUriLike]): +class Invocable(Protocol): """Invocable interface.""" - @abstractmethod - async def invoke( - self, options: InvokeOptions[TUriLike], invoker: Invoker[TUriLike] + def invoke( + self, + uri: Uri, + method: str, + args: Optional[Any] = None, + env: Optional[Any] = None, + resolution_context: Optional[UriResolutionContext] = None, + client: Optional[InvokerClient] = None, ) -> InvocableResult: """Invoke the Wrapper based on the provided InvokeOptions. Args: - options (InvokeOptions): InvokeOptions for this invocation. - invoker (Invoker): The invoker instance requesting this invocation.\ - This invoker will be used for any subinvocation that may occur. + uri (Uri): Uri of the wrapper + method (str): Method to be executed + args (Optional[Any]) : Arguments for the method, structured as a dictionary + env (Optional[Any]): Override the client's config for all invokes within this invoke. + resolution_context (Optional[UriResolutionContext]): A URI resolution context + client (Optional[InvokerClient]): The invoker client instance requesting\ + this invocation. This invoker client will be used for any subinvocation\ + that may occur. Returns: InvocableResult: Result of the invocation. """ + ... + + +__all__ = ["Invocable", "InvocableResult"] diff --git a/packages/polywrap-core/polywrap_core/types/invoke_args.py b/packages/polywrap-core/polywrap_core/types/invoke_args.py deleted file mode 100644 index d0d074e3..00000000 --- a/packages/polywrap-core/polywrap_core/types/invoke_args.py +++ /dev/null @@ -1,4 +0,0 @@ -"""This module defines InvokeArgs type.""" -from typing import Any, Dict, Union - -InvokeArgs = Union[Dict[str, Any], bytes, None] diff --git a/packages/polywrap-core/polywrap_core/types/invoke_options.py b/packages/polywrap-core/polywrap_core/types/invoke_options.py new file mode 100644 index 00000000..8cab91d6 --- /dev/null +++ b/packages/polywrap-core/polywrap_core/types/invoke_options.py @@ -0,0 +1,34 @@ +"""This module defines the InvokeOptions protocol.""" +from typing import Any, Optional, Protocol + +from .uri import Uri +from .uri_resolution_context import UriResolutionContext + + +class InvokeOptions(Protocol): + """InvokeOptions holds the options for an invocation.""" + + @property + def uri(self) -> Uri: + """The URI of the wrapper.""" + ... + + @property + def method(self) -> str: + """The method to invoke.""" + ... + + @property + def args(self) -> Any: + """The arguments to pass to the method.""" + ... + + @property + def env(self) -> Any: + """The environment variables to set for the invocation.""" + ... + + @property + def resolution_context(self) -> Optional[UriResolutionContext]: + """A URI resolution context.""" + ... diff --git a/packages/polywrap-core/polywrap_core/types/invoker.py b/packages/polywrap-core/polywrap_core/types/invoker.py index b81cb2ca..16083a5c 100644 --- a/packages/polywrap-core/polywrap_core/types/invoker.py +++ b/packages/polywrap-core/polywrap_core/types/invoker.py @@ -1,49 +1,54 @@ """This module contains the interface for invoking any invocables.""" +# pylint: disable=too-many-arguments + from __future__ import annotations -from abc import ABC, abstractmethod -from dataclasses import dataclass -from typing import Any, Generic, List, Optional, TypeVar, Union +from typing import Any, List, Optional, Protocol -from .options.invoke_options import InvokeOptions from .uri import Uri -from .uri_like import UriLike - -TUriLike = TypeVar("TUriLike", bound=UriLike) - - -@dataclass(slots=True, kw_only=True) -class InvokerOptions(Generic[TUriLike], InvokeOptions[TUriLike]): - """Options for invoking a wrapper using an invoker. +from .uri_resolution_context import UriResolutionContext - Attributes: - encode_result (Optional[bool]): If true, the result will be encoded. - """ - encode_result: Optional[bool] = False - - -class Invoker(ABC, Generic[TUriLike]): +class Invoker(Protocol): """Invoker interface defines the methods for invoking a wrapper.""" - @abstractmethod - async def invoke(self, options: InvokerOptions[TUriLike]) -> Any: + def invoke( + self, + uri: Uri, + method: str, + args: Optional[Any] = None, + env: Optional[Any] = None, + resolution_context: Optional[UriResolutionContext] = None, + encode_result: Optional[bool] = False, + ) -> Any: """Invoke the Wrapper based on the provided InvokerOptions. Args: - options (InvokerOptions): InvokerOptions for this invocation. + uri (Uri): Uri of the wrapper + method (str): Method to be executed + args (Optional[Any]) : Arguments for the method, structured as a dictionary + env (Optional[Any]): Override the client's config for all invokes within this invoke. + resolution_context (Optional[UriResolutionContext]): A URI resolution context + encode_result (Optional[bool]): If True, the result will be encoded Returns: Any: invocation result. """ + ... - @abstractmethod - def get_implementations(self, uri: Uri) -> Union[List[Uri], None]: + def get_implementations( + self, uri: Uri, apply_resolution: bool = True + ) -> Optional[List[Uri]]: """Get implementations of an interface with its URI. Args: uri (Uri): URI of the interface. + apply_resolution (bool): If True, apply resolution to the URI and interfaces. Returns: - Union[List[Uri], None]: List of implementations or None if not found. + Optional[List[Uri]]: List of implementations or None if not found. """ + ... + + +__all__ = ["Invoker"] diff --git a/packages/polywrap-core/polywrap_core/types/invoker_client.py b/packages/polywrap-core/polywrap_core/types/invoker_client.py index 245e3af4..66d3eaff 100644 --- a/packages/polywrap-core/polywrap_core/types/invoker_client.py +++ b/packages/polywrap-core/polywrap_core/types/invoker_client.py @@ -1,15 +1,15 @@ """This module contains the InvokerClient interface.""" from __future__ import annotations -from typing import Generic, TypeVar +from typing import Protocol from .invoker import Invoker -from .uri_like import UriLike from .uri_resolver_handler import UriResolverHandler -TUriLike = TypeVar("TUriLike", bound=UriLike) - -class InvokerClient(Generic[TUriLike], Invoker[TUriLike], UriResolverHandler[TUriLike]): +class InvokerClient(Invoker, UriResolverHandler, Protocol): """InvokerClient interface defines core set of functionalities\ for resolving and invoking a wrapper.""" + + +__all__ = ["InvokerClient"] diff --git a/packages/polywrap-core/polywrap_core/types/options/__init__.py b/packages/polywrap-core/polywrap_core/types/options/__init__.py deleted file mode 100644 index 1c08b389..00000000 --- a/packages/polywrap-core/polywrap_core/types/options/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -"""This module contains the options for various client methods.""" -from .file_options import * -from .invoke_options import * -from .manifest_options import * -from .uri_resolver_options import * diff --git a/packages/polywrap-core/polywrap_core/types/options/file_options.py b/packages/polywrap-core/polywrap_core/types/options/file_options.py deleted file mode 100644 index 614fc3e8..00000000 --- a/packages/polywrap-core/polywrap_core/types/options/file_options.py +++ /dev/null @@ -1,18 +0,0 @@ -"""This module contains GetFileOptions type.""" -from __future__ import annotations - -from dataclasses import dataclass -from typing import Optional - - -@dataclass(slots=True, kw_only=True) -class GetFileOptions: - """Options for getting a file from a wrapper. - - Attributes: - path (str): Path to the file. - encoding (Optional[str]): Encoding of the file. - """ - - path: str - encoding: Optional[str] = "utf-8" diff --git a/packages/polywrap-core/polywrap_core/types/options/invoke_options.py b/packages/polywrap-core/polywrap_core/types/options/invoke_options.py deleted file mode 100644 index afe3a1d3..00000000 --- a/packages/polywrap-core/polywrap_core/types/options/invoke_options.py +++ /dev/null @@ -1,32 +0,0 @@ -"""This module contains the interface for invoking any invocables.""" -from __future__ import annotations - -from dataclasses import dataclass, field -from typing import Generic, Optional, TypeVar - -from ..env import Env -from ..invoke_args import InvokeArgs -from ..uri import Uri -from ..uri_like import UriLike -from ..uri_resolution_context import IUriResolutionContext - -TUriLike = TypeVar("TUriLike", bound=UriLike) - - -@dataclass(slots=True, kw_only=True) -class InvokeOptions(Generic[TUriLike]): - """Options required for a wrapper invocation. - - Args: - uri (Uri): Uri of the wrapper - method (str): Method to be executed - args (Optional[InvokeArgs]) : Arguments for the method, structured as a dictionary - env (Optional[Env]): Override the client's config for all invokes within this invoke. - resolution_context (Optional[IUriResolutionContext]): A URI resolution context - """ - - uri: Uri - method: str - args: Optional[InvokeArgs] = field(default_factory=dict) - env: Optional[Env] = None - resolution_context: Optional[IUriResolutionContext[TUriLike]] = None diff --git a/packages/polywrap-core/polywrap_core/types/options/manifest_options.py b/packages/polywrap-core/polywrap_core/types/options/manifest_options.py deleted file mode 100644 index 521218df..00000000 --- a/packages/polywrap-core/polywrap_core/types/options/manifest_options.py +++ /dev/null @@ -1,11 +0,0 @@ -"""This module contains GetManifestOptions type.""" -from __future__ import annotations - -from dataclasses import dataclass - -from polywrap_manifest import DeserializeManifestOptions - - -@dataclass(slots=True, kw_only=True) -class GetManifestOptions(DeserializeManifestOptions): - """Options for getting a manifest from a wrapper.""" diff --git a/packages/polywrap-core/polywrap_core/types/options/uri_resolver_options.py b/packages/polywrap-core/polywrap_core/types/options/uri_resolver_options.py deleted file mode 100644 index 9d897d0d..00000000 --- a/packages/polywrap-core/polywrap_core/types/options/uri_resolver_options.py +++ /dev/null @@ -1,24 +0,0 @@ -"""This module contains the TryResolveUriOptions type.""" -from __future__ import annotations - -from dataclasses import dataclass -from typing import Generic, Optional, TypeVar - -from ..uri import Uri -from ..uri_like import UriLike -from ..uri_resolution_context import IUriResolutionContext - -TUriLike = TypeVar("TUriLike", bound=UriLike) - - -@dataclass(slots=True, kw_only=True) -class TryResolveUriOptions(Generic[TUriLike]): - """Options for resolving a uri. - - Args: - uri (Uri): Uri of the wrapper to resolve. - resolution_context (Optional[IUriResolutionContext]): A URI resolution context - """ - - uri: Uri - resolution_context: Optional[IUriResolutionContext[TUriLike]] = None diff --git a/packages/polywrap-core/polywrap_core/types/uri.py b/packages/polywrap-core/polywrap_core/types/uri.py index f6390bf2..425b7a9a 100644 --- a/packages/polywrap-core/polywrap_core/types/uri.py +++ b/packages/polywrap-core/polywrap_core/types/uri.py @@ -2,12 +2,12 @@ from __future__ import annotations import re +from functools import total_ordering from typing import Union -from .uri_like import UriLike - -class Uri(UriLike): +@total_ordering +class Uri: """Defines a wrapper URI and provides utilities for parsing and validating them. wrapper URIs are used to identify and resolve Polywrap wrappers. They are \ @@ -54,6 +54,7 @@ class Uri(UriLike): r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?" ) # https://www.rfc-editor.org/rfc/rfc3986#appendix-B + scheme = "wrap" _authority: str _path: str @@ -61,8 +62,8 @@ def __init__(self, authority: str, path: str): """Initialize a new instance of a wrapper URI. Args: - authority: The authority of the URI. - path: The path of the URI. + authority (str): The authority of the URI. + path (str): The path of the URI. """ self._authority = authority self._path = path @@ -150,3 +151,29 @@ def from_str(cls, uri: str) -> Uri: raise ValueError("The provided URI has an invalid path") return cls(authority, path) + + def __str__(self) -> str: + """Return the URI as a string.""" + return self.uri + + def __repr__(self) -> str: + """Return the string URI representation.""" + return f'Uri("{self._authority}", "{self._path}")' + + def __hash__(self) -> int: + """Return the hash of the URI.""" + return hash(self.uri) + + def __eq__(self, obj: object) -> bool: + """Return true if the provided object is a Uri and has the same URI.""" + return self.uri == obj.uri if isinstance(obj, Uri) else False + + def __lt__(self, uri: object) -> bool: + """Return true if the provided Uri has a URI that is lexicographically\ + less than this Uri.""" + if not isinstance(uri, Uri): + raise TypeError(f"Cannot compare Uri to {type(uri)}") + return self.uri < uri.uri + + +__all__ = ["Uri"] diff --git a/packages/polywrap-core/polywrap_core/types/uri_like.py b/packages/polywrap-core/polywrap_core/types/uri_like.py deleted file mode 100644 index 39014221..00000000 --- a/packages/polywrap-core/polywrap_core/types/uri_like.py +++ /dev/null @@ -1,64 +0,0 @@ -"""This module contains the utility for sanitizing and parsing Wrapper URIs.""" -from __future__ import annotations - -from abc import ABC, abstractmethod -from functools import total_ordering - - -@total_ordering -class UriLike(ABC): - """Defines the interface for a URI-like object. - - Examples: - - Uri - - UriWrapper - - UriPackage - """ - - @property - def scheme(self) -> str: - """Return the scheme of the URI.""" - return "wrap" - - @property - @abstractmethod - def authority(self) -> str: - """Return the authority of the URI.""" - - @property - @abstractmethod - def path(self) -> str: - """Return the path of the URI.""" - - @property - @abstractmethod - def uri(self) -> str: - """Return the URI as a string.""" - - @staticmethod - @abstractmethod - def is_canonical_uri(uri: str) -> bool: - """Return true if the provided URI is canonical.""" - - def __str__(self) -> str: - """Return the URI as a string.""" - return self.uri - - def __repr__(self) -> str: - """Return the string URI representation.""" - return f"Uri({self.uri})" - - def __hash__(self) -> int: - """Return the hash of the URI.""" - return hash(self.uri) - - def __eq__(self, obj: object) -> bool: - """Return true if the provided object is a Uri and has the same URI.""" - return self.uri == obj.uri if isinstance(obj, UriLike) else False - - def __lt__(self, uri: object) -> bool: - """Return true if the provided Uri has a URI that is lexicographically\ - less than this Uri.""" - if not isinstance(uri, UriLike): - raise TypeError(f"Cannot compare Uri to {type(uri)}") - return self.uri < uri.uri diff --git a/packages/polywrap-core/polywrap_core/types/uri_package.py b/packages/polywrap-core/polywrap_core/types/uri_package.py index 8d84f5d3..63b61948 100644 --- a/packages/polywrap-core/polywrap_core/types/uri_package.py +++ b/packages/polywrap-core/polywrap_core/types/uri_package.py @@ -1,35 +1,23 @@ """This module contains the UriPackage type.""" from __future__ import annotations -from typing import Generic, TypeVar +from dataclasses import dataclass from .uri import Uri -from .uri_like import UriLike from .wrap_package import WrapPackage -TUriLike = TypeVar("TUriLike", bound=UriLike) - -class UriPackage(Generic[TUriLike], Uri): - """UriPackage is a dataclass that contains a URI and a wrap package. +@dataclass(slots=True, kw_only=True) +class UriPackage: + """UriPackage is a dataclass that contains a URI and a package. Attributes: - package (WrapPackage): The wrap package. + uri (Uri): The URI. + package (Package): The package. """ - _package: WrapPackage[TUriLike] - - def __init__(self, uri: Uri, package: WrapPackage[TUriLike]) -> None: - """Initialize a new instance of UriPackage. + uri: Uri + package: WrapPackage - Args: - uri (Uri): The URI. - package (WrapPackage): The wrap package. - """ - super().__init__(uri.authority, uri.path) - self._package = package - @property - def package(self) -> WrapPackage[TUriLike]: - """Return the wrap package.""" - return self._package +__all__ = ["UriPackage"] diff --git a/packages/polywrap-core/polywrap_core/types/uri_package_wrapper.py b/packages/polywrap-core/polywrap_core/types/uri_package_wrapper.py index 8351aac8..a4c3e5da 100644 --- a/packages/polywrap-core/polywrap_core/types/uri_package_wrapper.py +++ b/packages/polywrap-core/polywrap_core/types/uri_package_wrapper.py @@ -7,6 +7,6 @@ from .uri_package import UriPackage from .uri_wrapper import UriWrapper -UriPackageOrWrapper = Union[ - Uri, UriWrapper["UriPackageOrWrapper"], UriPackage["UriPackageOrWrapper"] -] +UriPackageOrWrapper = Union[Uri, UriWrapper, UriPackage] + +__all__ = ["UriPackageOrWrapper"] diff --git a/packages/polywrap-core/polywrap_core/types/uri_resolution_context.py b/packages/polywrap-core/polywrap_core/types/uri_resolution_context.py index 3909a36e..4b852595 100644 --- a/packages/polywrap-core/polywrap_core/types/uri_resolution_context.py +++ b/packages/polywrap-core/polywrap_core/types/uri_resolution_context.py @@ -1,20 +1,48 @@ -"""This module contains the interface for a URI resolution context.""" -from __future__ import annotations - -from abc import ABC, abstractmethod -from typing import Generic, List, TypeVar +"""This module contains implementation of IUriResolutionContext interface.""" +from typing import List, Optional, Set from .uri import Uri -from .uri_like import UriLike -from .uri_resolution_step import IUriResolutionStep +from .uri_resolution_step import UriResolutionStep + + +class UriResolutionContext: + """Represents the context of a uri resolution. -TUriLike = TypeVar("TUriLike", bound=UriLike) + Attributes: + resolving_uri_set (Set[Uri]): A set of uris that\ + are currently being resolved. + resolution_path (List[Uri]): A list of uris in the order that\ + they are being resolved. + history (List[UriResolutionStep]): A list of steps \ + that have been taken to resolve the uri. + """ + resolving_uri_set: Set[Uri] + resolution_path: List[Uri] + history: List[UriResolutionStep] -class IUriResolutionContext(ABC, Generic[TUriLike]): - """Defines the interface for a URI resolution context.""" + __slots__ = ("resolving_uri_set", "resolution_path", "history") + + def __init__( + self, + resolving_uri_set: Optional[Set[Uri]] = None, + resolution_path: Optional[List[Uri]] = None, + history: Optional[List[UriResolutionStep]] = None, + ): + """Initialize a new instance of UriResolutionContext. + + Args: + resolving_uri_set (Optional[Set[Uri]]): A set of uris that\ + are currently being resolved. + resolution_path (Optional[List[Uri]]): A list of uris in the order that\ + they are being resolved. + history (Optional[List[UriResolutionStep]]): A list of steps \ + that have been taken to resolve the uri. + """ + self.resolving_uri_set = resolving_uri_set or set() + self.resolution_path = resolution_path or [] + self.history = history or [] - @abstractmethod def is_resolving(self, uri: Uri) -> bool: """Check if the given uri is currently being resolved. @@ -24,8 +52,8 @@ def is_resolving(self, uri: Uri) -> bool: Returns: bool: True if the uri is currently being resolved, otherwise False. """ + return uri in self.resolving_uri_set - @abstractmethod def start_resolving(self, uri: Uri) -> None: """Start resolving the given uri. @@ -34,8 +62,9 @@ def start_resolving(self, uri: Uri) -> None: Returns: None """ + self.resolving_uri_set.add(uri) + self.resolution_path.append(uri) - @abstractmethod def stop_resolving(self, uri: Uri) -> None: """Stop resolving the given uri. @@ -44,45 +73,54 @@ def stop_resolving(self, uri: Uri) -> None: Returns: None """ + self.resolving_uri_set.remove(uri) - @abstractmethod - def track_step(self, step: IUriResolutionStep[TUriLike]) -> None: + def track_step(self, step: UriResolutionStep) -> None: """Track the given step in the resolution history. Args: - step (IUriResolutionStep): The step to track. + step (UriResolutionStep): The step to track. Returns: None """ + self.history.append(step) - @abstractmethod - def get_history(self) -> List[IUriResolutionStep[TUriLike]]: + def get_history(self) -> List[UriResolutionStep]: """Get the resolution history. Returns: - List[IUriResolutionStep]: The resolution history. + List[UriResolutionStep]: The resolution history. """ + return self.history - @abstractmethod def get_resolution_path(self) -> List[Uri]: """Get the resolution path. Returns: List[Uri]: The ordered list of URI resolution path. """ + return self.resolution_path - @abstractmethod - def create_sub_history_context(self) -> "IUriResolutionContext[TUriLike]": + def create_sub_history_context(self) -> "UriResolutionContext": """Create a new sub context that shares the same resolution path. Returns: - IUriResolutionContext: The new context. + UriResolutionContext: The new context. """ + return UriResolutionContext( + resolving_uri_set=self.resolving_uri_set, + resolution_path=self.resolution_path, + ) - @abstractmethod - def create_sub_context(self) -> "IUriResolutionContext[TUriLike]": + def create_sub_context(self) -> "UriResolutionContext": """Create a new sub context that shares the same resolution history. Returns: - IUriResolutionContext: The new context. + UriResolutionContext: The new context. """ + return UriResolutionContext( + resolving_uri_set=self.resolving_uri_set, history=self.history + ) + + +__all__ = ["UriResolutionContext"] diff --git a/packages/polywrap-core/polywrap_core/types/uri_resolution_step.py b/packages/polywrap-core/polywrap_core/types/uri_resolution_step.py index ed75a331..4ababc33 100644 --- a/packages/polywrap-core/polywrap_core/types/uri_resolution_step.py +++ b/packages/polywrap-core/polywrap_core/types/uri_resolution_step.py @@ -1,27 +1,28 @@ -"""This module contains the uri resolution step interface.""" +"""This module contains implementation of IUriResolutionStep interface.""" from __future__ import annotations from dataclasses import dataclass -from typing import Generic, List, Optional, TypeVar +from typing import Any, List, Optional from .uri import Uri -from .uri_like import UriLike - -TUriLike = TypeVar("TUriLike", bound=UriLike) @dataclass(slots=True, kw_only=True) -class IUriResolutionStep(Generic[TUriLike]): +class UriResolutionStep: """Represents a single step in the resolution of a uri. Attributes: source_uri (Uri): The uri that was resolved. - result (T): The result of the resolution. must be a UriLike. - description: A description of the resolution step. - sub_history: A list of sub steps that were taken to resolve the uri. + result (Any): The result of the resolution. + description (Optional[str]): A description of the resolution step. + sub_history (Optional[List[UriResolutionStep]]): A list of sub steps\ + that were taken to resolve the uri. """ source_uri: Uri - result: TUriLike + result: Any description: Optional[str] = None - sub_history: Optional[List["IUriResolutionStep[TUriLike]"]] = None + sub_history: Optional[List[UriResolutionStep]] = None + + +__all__ = ["UriResolutionStep"] diff --git a/packages/polywrap-core/polywrap_core/types/uri_resolver.py b/packages/polywrap-core/polywrap_core/types/uri_resolver.py index 66463d1c..0de1f60a 100644 --- a/packages/polywrap-core/polywrap_core/types/uri_resolver.py +++ b/packages/polywrap-core/polywrap_core/types/uri_resolver.py @@ -1,31 +1,36 @@ """This module contains the uri resolver interface.""" from __future__ import annotations -from abc import ABC, abstractmethod +from typing import Protocol from .invoker_client import InvokerClient from .uri import Uri from .uri_package_wrapper import UriPackageOrWrapper -from .uri_resolution_context import IUriResolutionContext +from .uri_resolution_context import UriResolutionContext -class UriResolver(ABC): +class UriResolver(Protocol): """Defines interface for wrapper uri resolver.""" - @abstractmethod - async def try_resolve_uri( + def try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> UriPackageOrWrapper: """Try to resolve a uri. Args: - uri: The uri to resolve. - client: The minimal invoker client to use for resolving the uri. - resolution_context: The context for resolving the uri. + uri (Uri): The uri to resolve. + client (InvokerClient): The minimal invoker client \ + to use for resolving the uri. + resolution_context (UriResolutionContext): The context \ + for resolving the uri. Returns: UriPackageOrWrapper: result of the URI resolution. """ + ... + + +__all__ = ["UriResolver"] diff --git a/packages/polywrap-core/polywrap_core/types/uri_resolver_handler.py b/packages/polywrap-core/polywrap_core/types/uri_resolver_handler.py index 3c56687a..ca1140b5 100644 --- a/packages/polywrap-core/polywrap_core/types/uri_resolver_handler.py +++ b/packages/polywrap-core/polywrap_core/types/uri_resolver_handler.py @@ -1,27 +1,29 @@ """This module contains uri resolver handler interface.""" from __future__ import annotations -from abc import ABC, abstractmethod -from typing import Generic, TypeVar +from typing import Any, Optional, Protocol -from .options.uri_resolver_options import TryResolveUriOptions -from .uri_like import UriLike +from .uri import Uri +from .uri_resolution_context import UriResolutionContext -TUriLike = TypeVar("TUriLike", bound=UriLike) - -class UriResolverHandler(ABC, Generic[TUriLike]): +class UriResolverHandler(Protocol): """Uri resolver handler interface.""" - @abstractmethod - async def try_resolve_uri( - self, options: TryResolveUriOptions[TUriLike] - ) -> TUriLike: + def try_resolve_uri( + self, uri: Uri, resolution_context: Optional[UriResolutionContext] = None + ) -> Any: """Try to resolve a uri. Args: - options: The options for resolving the uri. + uri (Uri): Uri of the wrapper to resolve. + resolution_context (Optional[IUriResolutionContext]):\ + A URI resolution context Returns: - T: result of the URI resolution. Must be a UriLike. + Any: result of the URI resolution. """ + ... + + +__all__ = ["UriResolverHandler"] diff --git a/packages/polywrap-core/polywrap_core/types/uri_wrapper.py b/packages/polywrap-core/polywrap_core/types/uri_wrapper.py index 56749816..8930220e 100644 --- a/packages/polywrap-core/polywrap_core/types/uri_wrapper.py +++ b/packages/polywrap-core/polywrap_core/types/uri_wrapper.py @@ -1,35 +1,23 @@ """This module contains the UriWrapper type.""" from __future__ import annotations -from typing import Generic, TypeVar +from dataclasses import dataclass from .uri import Uri -from .uri_like import UriLike from .wrapper import Wrapper -TUriLike = TypeVar("TUriLike", bound=UriLike) - -class UriWrapper(Generic[TUriLike], Uri): +@dataclass(slots=True, kw_only=True) +class UriWrapper: """UriWrapper is a dataclass that contains a URI and a wrapper. Attributes: - wrapper: The wrapper. + uri (Uri): The URI. + wrapper (Wrapper): The wrapper. """ - _wrapper: Wrapper[TUriLike] - - def __init__(self, uri: Uri, wrapper: Wrapper[TUriLike]) -> None: - """Initialize a new instance of UriWrapper. + uri: Uri + wrapper: Wrapper - Args: - uri: The URI. - wrapper: The wrapper. - """ - super().__init__(uri.authority, uri.path) - self._wrapper = wrapper - @property - def wrapper(self) -> Wrapper[TUriLike]: - """Return the wrapper.""" - return self._wrapper +__all__ = ["UriWrapper"] diff --git a/packages/polywrap-core/polywrap_core/types/wrap_package.py b/packages/polywrap-core/polywrap_core/types/wrap_package.py index 4ce160d1..e9f4b30e 100644 --- a/packages/polywrap-core/polywrap_core/types/wrap_package.py +++ b/packages/polywrap-core/polywrap_core/types/wrap_package.py @@ -1,36 +1,36 @@ """This module contains the IWrapPackage interface.""" -from abc import ABC, abstractmethod -from typing import Generic, Optional, TypeVar +from __future__ import annotations -from polywrap_manifest import AnyWrapManifest +from typing import Optional, Protocol -from .options import GetManifestOptions -from .uri_like import UriLike -from .wrapper import Wrapper +from polywrap_manifest import AnyWrapManifest, DeserializeManifestOptions -TUriLike = TypeVar("TUriLike", bound=UriLike) +from .wrapper import Wrapper -class WrapPackage(ABC, Generic[TUriLike]): +class WrapPackage(Protocol): """Wrapper package interface.""" - @abstractmethod - async def create_wrapper(self) -> Wrapper[TUriLike]: + def create_wrapper(self) -> Wrapper: """Create a new wrapper instance from the wrapper package. Returns: Wrapper: The newly created wrapper instance. """ + ... - @abstractmethod - async def get_manifest( - self, options: Optional[GetManifestOptions] = None + def get_manifest( + self, options: Optional[DeserializeManifestOptions] = None ) -> AnyWrapManifest: """Get the manifest from the wrapper package. Args: - options: The options for getting the manifest. + options (DeserializeManifestOptions): The options for getting the manifest. Returns: AnyWrapManifest: The manifest of the wrapper. """ + ... + + +__all__ = ["WrapPackage"] diff --git a/packages/polywrap-core/polywrap_core/types/wrapper.py b/packages/polywrap-core/polywrap_core/types/wrapper.py index d92fe87c..303893e6 100644 --- a/packages/polywrap-core/polywrap_core/types/wrapper.py +++ b/packages/polywrap-core/polywrap_core/types/wrapper.py @@ -1,52 +1,37 @@ """This module contains the Wrapper interface.""" -from abc import abstractmethod -from typing import Any, Dict, Generic, TypeVar, Union +from __future__ import annotations + +from typing import Optional, Protocol, Union from polywrap_manifest import AnyWrapManifest from .invocable import Invocable -from .invoker import InvokeOptions, Invoker -from .options import GetFileOptions -from .uri_like import UriLike - -TUriLike = TypeVar("TUriLike", bound=UriLike) -class Wrapper(Generic[TUriLike], Invocable[TUriLike]): +class Wrapper(Invocable, Protocol): """Defines the interface for a wrapper.""" - @abstractmethod - async def invoke( - self, options: InvokeOptions[TUriLike], invoker: Invoker[TUriLike] - ) -> Any: - """Invoke the wrapper. - - Args: - options: The options for invoking the wrapper. - invoker: The invoker to use for invoking the wrapper. - - Returns: - Any: The result of the wrapper invocation. - """ - - @abstractmethod - async def get_file(self, options: GetFileOptions) -> Union[str, bytes]: + def get_file( + self, path: str, encoding: Optional[str] = "utf-8" + ) -> Union[str, bytes]: """Get a file from the wrapper. Args: - options: The options for getting the file. + path (str): Path to the file. + encoding (Optional[str]): Encoding of the file. Returns: Union[str, bytes]: The file contents """ + ... - @abstractmethod def get_manifest(self) -> AnyWrapManifest: """Get the manifest of the wrapper. Returns: AnyWrapManifest: The manifest of the wrapper. """ + ... -WrapperCache = Dict[str, Wrapper[TUriLike]] +__all__ = ["Wrapper"] diff --git a/packages/polywrap-core/polywrap_core/utils/__init__.py b/packages/polywrap-core/polywrap_core/utils/__init__.py index 0d6a3b67..abd549d8 100644 --- a/packages/polywrap-core/polywrap_core/utils/__init__.py +++ b/packages/polywrap-core/polywrap_core/utils/__init__.py @@ -1,3 +1,4 @@ -"""This module contains the core utility functions.""" -from .instance_of import * -from .maybe_async import * +"""This package contains the utilities used by the polywrap-uri-resolvers package.""" +from .build_clean_uri_history import * +from .get_env_from_resolution_path import * +from .get_implementations import * diff --git a/packages/polywrap-core/polywrap_core/utils/build_clean_uri_history.py b/packages/polywrap-core/polywrap_core/utils/build_clean_uri_history.py new file mode 100644 index 00000000..a22dd0f1 --- /dev/null +++ b/packages/polywrap-core/polywrap_core/utils/build_clean_uri_history.py @@ -0,0 +1,73 @@ +"""This module contains an utility function for building a clean history of URI resolution steps.""" +from typing import List, Optional, Union + +from ..types import UriPackage, UriResolutionStep, UriWrapper + +CleanResolutionStep = List[Union[str, "CleanResolutionStep"]] + + +def build_clean_uri_history( + history: List[UriResolutionStep], depth: Optional[int] = None +) -> CleanResolutionStep: + """Build a clean history of the URI resolution steps. + + Args: + history: A list of URI resolution steps. + depth: The depth of the history to build. + + Returns: + CleanResolutionStep: A clean history of the URI resolution steps. + """ + clean_history: CleanResolutionStep = [] + + if depth is not None: + depth -= 1 + + if not history: + return clean_history + + for step in history: + clean_history.append(_build_clean_history_step(step)) + + if ( + not step.sub_history + or len(step.sub_history) == 0 + or (depth is not None and depth < 0) + ): + continue + + sub_history = build_clean_uri_history(step.sub_history, depth) + if len(sub_history) > 0: + clean_history.append(sub_history) + + return clean_history + + +def _build_clean_history_step(step: UriResolutionStep) -> str: + uri_package_or_wrapper = step.result + + match uri_package_or_wrapper: + case UriPackage(uri=uri): + return ( + f"{step.source_uri} => {step.description} => package ({uri})" + if step.description + else f"{step.source_uri} => package ({uri})" + ) + case UriWrapper(uri=uri): + return ( + f"{step.source_uri} => {step.description} => wrapper ({uri})" + if step.description + else f"{step.source_uri} => wrapper ({uri})" + ) + case uri: + if step.source_uri == uri: + return ( + f"{step.source_uri} => {step.description}" + if step.description + else f"{step.source_uri}" + ) + return ( + f"{step.source_uri} => {step.description} => uri ({uri})" + if step.description + else f"{step.source_uri} => uri ({uri})" + ) diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/utils/get_env_from_uri_history.py b/packages/polywrap-core/polywrap_core/utils/get_env_from_resolution_path.py similarity index 78% rename from packages/polywrap-uri-resolvers/polywrap_uri_resolvers/utils/get_env_from_uri_history.py rename to packages/polywrap-core/polywrap_core/utils/get_env_from_resolution_path.py index 1e5b3d6b..33bc4ac2 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/utils/get_env_from_uri_history.py +++ b/packages/polywrap-core/polywrap_core/utils/get_env_from_resolution_path.py @@ -1,12 +1,12 @@ """This module contains the utility function for getting the env from the URI history.""" -from typing import Any, Dict, List, Union +from typing import Any, List, Union -from polywrap_core import Client, Uri +from ..types import Client, Uri -def get_env_from_uri_history( +def get_env_from_resolution_path( uri_history: List[Uri], client: Client -) -> Union[Dict[str, Any], None]: +) -> Union[Any, None]: """Get environment variable from URI resolution history. Args: diff --git a/packages/polywrap-core/polywrap_core/utils/get_implementations.py b/packages/polywrap-core/polywrap_core/utils/get_implementations.py new file mode 100644 index 00000000..e8657129 --- /dev/null +++ b/packages/polywrap-core/polywrap_core/utils/get_implementations.py @@ -0,0 +1,49 @@ +"""This module contains the get_implementations utility.""" +from typing import Dict, List, Optional, Set + +from ..types import InvokerClient, Uri, UriResolutionContext +from ..types.errors import WrapGetImplementationsError + + +def _get_final_uri( + uri: Uri, + client: Optional[InvokerClient] = None, + resolution_context: Optional[UriResolutionContext] = None, +) -> Uri: + if client: + try: + return client.try_resolve_uri(uri, resolution_context) + except Exception as e: + raise WrapGetImplementationsError(uri, "Failed to resolve redirects") from e + return uri + + +def get_implementations( + interface_uri: Uri, + interfaces: Dict[Uri, List[Uri]], + client: Optional[InvokerClient] = None, + resolution_context: Optional[UriResolutionContext] = None, +) -> Optional[List[Uri]]: + """Get implementations of an interface with its URI. + + Args: + interface_uri (Uri): URI of the interface. + interfaces (Dict[Uri, List[Uri]]): Dictionary of interfaces and their implementations. + client (Optional[InvokerClient]): The client to use for resolving the URI. + resolution_context (Optional[UriResolutionContext]): The resolution context to use. + + Returns: + Optional[List[Uri]]: List of implementations or None if not found. + """ + final_interface_uri = _get_final_uri(interface_uri, client, resolution_context) + final_implementations: Set[Uri] = set() + + for interface in interfaces: + final_current_interface_uri = _get_final_uri( + interface, client, resolution_context + ) + if final_current_interface_uri == final_interface_uri: + impls = set(interfaces.get(interface, [])) + final_implementations = final_implementations.union(impls) + + return list(final_implementations) if final_implementations else None diff --git a/packages/polywrap-core/polywrap_core/utils/instance_of.py b/packages/polywrap-core/polywrap_core/utils/instance_of.py deleted file mode 100644 index 3772179d..00000000 --- a/packages/polywrap-core/polywrap_core/utils/instance_of.py +++ /dev/null @@ -1,16 +0,0 @@ -"""This module contains the instance_of utility function.""" -import inspect -from typing import Any - - -def instance_of(obj: Any, cls: Any): - """Check if an object is an instance of a class or any of its parent classes. - - Args: - obj (Any): any object instance - cls (Any): class to check against - - Returns: - bool: True if obj is an instance of cls or any of its parent classes, False otherwise - """ - return cls in inspect.getmro(obj.__class__) diff --git a/packages/polywrap-core/polywrap_core/utils/maybe_async.py b/packages/polywrap-core/polywrap_core/utils/maybe_async.py deleted file mode 100644 index 913182f2..00000000 --- a/packages/polywrap-core/polywrap_core/utils/maybe_async.py +++ /dev/null @@ -1,18 +0,0 @@ -"""This module contains the utility function for executing a function that may be async.""" -from __future__ import annotations - -import inspect -from typing import Any, Awaitable, Callable, Optional, Union - - -def is_coroutine(test: Optional[Union[Awaitable[Any], Any]] = None) -> bool: - """Check if the given object is a coroutine.""" - return test is not None and inspect.iscoroutine(test) - - -async def execute_maybe_async_function(func: Callable[..., Any], *args: Any) -> Any: - """Execute a function that may be async.""" - result = func(*args) - if is_coroutine(result): - result = await result - return result diff --git a/packages/polywrap-core/pyproject.toml b/packages/polywrap-core/pyproject.toml index dc73c351..5097c49e 100644 --- a/packages/polywrap-core/pyproject.toml +++ b/packages/polywrap-core/pyproject.toml @@ -12,9 +12,10 @@ authors = ["Cesar ", "Niraj "] python = "^3.10" polywrap-msgpack = {path = "../polywrap-msgpack", develop = true} polywrap-manifest = {path = "../polywrap-manifest", develop = true} -[tool.poetry.dev-dependencies] + +[tool.poetry.group.dev.dependencies] +pycln = "^2.1.3" pytest = "^7.1.2" -pytest-asyncio = "^0.19.0" pylint = "^2.15.4" black = "^22.10.0" bandit = { version = "^1.7.4", extras = ["toml"]} @@ -24,13 +25,6 @@ isort = "^5.10.1" pyright = "^1.1.275" pydocstyle = "^6.1.1" -[tool.poetry.group.temp.dependencies] -pydeps = "^1.11.1" - - -[tool.poetry.group.dev.dependencies] -pycln = "^2.1.3" - [tool.bandit] exclude_dirs = ["tests"] @@ -42,7 +36,6 @@ typeCheckingMode = "strict" reportShadowedImports = false [tool.pytest.ini_options] -asyncio_mode = "auto" testpaths = [ "tests" ] @@ -52,6 +45,7 @@ disable = [ "invalid-name", "too-many-return-statements", "too-few-public-methods", + "unnecessary-ellipsis" ] ignore = [ "tests/" diff --git a/packages/polywrap-core/tests/test_build_clean_uri_history.py b/packages/polywrap-core/tests/test_build_clean_uri_history.py new file mode 100644 index 00000000..e5da523d --- /dev/null +++ b/packages/polywrap-core/tests/test_build_clean_uri_history.py @@ -0,0 +1,46 @@ +from polywrap_core import ( + CleanResolutionStep, + Uri, + build_clean_uri_history, + UriResolutionStep, +) +import pytest + + +@pytest.fixture +def history() -> list[UriResolutionStep]: + return [ + UriResolutionStep( + source_uri=Uri.from_str("test/1"), + result=Uri.from_str("test/2"), + description="AggreagatorResolver", + sub_history=[ + UriResolutionStep( + source_uri=Uri.from_str("test/1"), + result=Uri.from_str("test/2"), + description="ExtensionRedirectResolver", + ), + ], + ), + UriResolutionStep( + source_uri=Uri.from_str("test/2"), + result=Uri.from_str("test/3"), + description="SimpleRedirectResolver", + ), + ] + + +@pytest.fixture +def expected() -> CleanResolutionStep: + return [ + "wrap://test/1 => AggreagatorResolver => uri (wrap://test/2)", + ["wrap://test/1 => ExtensionRedirectResolver => uri (wrap://test/2)"], + "wrap://test/2 => SimpleRedirectResolver => uri (wrap://test/3)", + ] + + +def test_build_clean_uri_history( + history: list[UriResolutionStep], expected: CleanResolutionStep +): + print(build_clean_uri_history(history)) + assert build_clean_uri_history(history) == expected diff --git a/packages/polywrap-core/tests/test_env_from_resolution_path.py b/packages/polywrap-core/tests/test_env_from_resolution_path.py new file mode 100644 index 00000000..5c832372 --- /dev/null +++ b/packages/polywrap-core/tests/test_env_from_resolution_path.py @@ -0,0 +1,40 @@ +from typing import Any +from polywrap_core import ( + Client, + Uri, + get_env_from_resolution_path, +) +import pytest + + +@pytest.fixture +def resolution_path() -> list[Any]: + return [ + Uri.from_str("test/1"), + Uri.from_str("test/2"), + Uri.from_str("test/3"), + ] + + +@pytest.fixture +def client() -> Any: + class MockClient: + def get_env_by_uri(self, uri: Uri) -> Any: + if uri.uri == "wrap://test/3": + return { + "arg1": "arg1", + "arg2": "arg2", + } + + return MockClient() + + +def test_get_env_from_resolution_path(resolution_path: list[Any], client: Client): + assert get_env_from_resolution_path(resolution_path, client) == { + "arg1": "arg1", + "arg2": "arg2", + } + + +def test_get_env_from_resolution_path_empty(client: Client): + assert get_env_from_resolution_path([], client) is None diff --git a/packages/polywrap-core/tests/test_get_implementations.py b/packages/polywrap-core/tests/test_get_implementations.py new file mode 100644 index 00000000..b8e3cd84 --- /dev/null +++ b/packages/polywrap-core/tests/test_get_implementations.py @@ -0,0 +1,79 @@ +from polywrap_core import ( + Any, + Client, + Uri, + get_implementations, +) +import pytest + +interface_1 = Uri.from_str("wrap://ens/interface-1.eth") +interface_2 = Uri.from_str("wrap://ens/interface-2.eth") +interface_3 = Uri.from_str("wrap://ens/interface-3.eth") + +implementation_1 = Uri.from_str("wrap://ens/implementation-1.eth") +implementation_2 = Uri.from_str("wrap://ens/implementation-2.eth") +implementation_3 = Uri.from_str("wrap://ens/implementation-3.eth") + + +redirects = { + interface_1: interface_2, + implementation_1: implementation_2, + implementation_2: implementation_3, +} + +interfaces = { + interface_1: [implementation_1, implementation_2], + interface_2: [implementation_3], + interface_3: [implementation_3], +} + + +@pytest.fixture +def client() -> Any: + class MockClient: + def try_resolve_uri(self, uri: Uri, *args: Any) -> Uri: + return redirects.get(uri, uri) + + return MockClient() + + +def test_get_implementations_1(client: Client): + result = get_implementations(interface_1, interfaces, client) + + assert result + assert set(result) == { + implementation_1, + implementation_2, + implementation_3, + } + + +def test_get_implementations_2(client: Client): + result = get_implementations(interface_2, interfaces, client) + + assert result + assert set(result) == { + implementation_1, + implementation_2, + implementation_3, + } + + +def test_get_implementations_3(client: Client): + result = get_implementations(interface_3, interfaces, client) + + assert result + assert set(result) == { + implementation_3, + } + + +def test_implementations_not_redirected(client: Client): + result = get_implementations(interface_1, { + interface_1: [implementation_1], + }, client) + + assert result + assert set(result) == { + implementation_1, + } \ No newline at end of file diff --git a/packages/polywrap-core/tests/test_maybe_async.py b/packages/polywrap-core/tests/test_maybe_async.py deleted file mode 100644 index 6e3323f9..00000000 --- a/packages/polywrap-core/tests/test_maybe_async.py +++ /dev/null @@ -1,27 +0,0 @@ -import inspect - -import pytest - -from polywrap_core import execute_maybe_async_function, is_coroutine - - -@pytest.mark.asyncio -async def test_sanity(): - async def coroutine(): - pass - - def test_function(): - pass - - async def test_function_return_promise(): - pass - - test_coroutine_resp = coroutine() - test_function_resp = execute_maybe_async_function(test_function) - test_function_return_promise_resp = execute_maybe_async_function(test_function_return_promise) - assert is_coroutine(test_coroutine_resp) - assert inspect.iscoroutine(test_function_resp) - assert inspect.iscoroutine(test_function_return_promise_resp) - await test_coroutine_resp - await test_function_resp - await test_function_return_promise_resp diff --git a/packages/polywrap-manifest/polywrap_manifest/deserialize.py b/packages/polywrap-manifest/polywrap_manifest/deserialize.py index 1f2f169e..d8996505 100644 --- a/packages/polywrap-manifest/polywrap_manifest/deserialize.py +++ b/packages/polywrap-manifest/polywrap_manifest/deserialize.py @@ -53,3 +53,6 @@ def deserialize_wrap_manifest( raise NotImplementedError( f"Version {manifest_version.value} is not implemented" ) + + +__all__ = ["deserialize_wrap_manifest"] diff --git a/packages/polywrap-manifest/polywrap_manifest/errors.py b/packages/polywrap-manifest/polywrap_manifest/errors.py index 0bdbff49..19015dde 100644 --- a/packages/polywrap-manifest/polywrap_manifest/errors.py +++ b/packages/polywrap-manifest/polywrap_manifest/errors.py @@ -7,3 +7,6 @@ class ManifestError(Exception): class DeserializeManifestError(ManifestError): """Raised when a manifest cannot be deserialized.""" + + +__all__ = ["ManifestError", "DeserializeManifestError"] diff --git a/packages/polywrap-manifest/polywrap_manifest/manifest.py b/packages/polywrap-manifest/polywrap_manifest/manifest.py index 29268c31..d0be947c 100644 --- a/packages/polywrap-manifest/polywrap_manifest/manifest.py +++ b/packages/polywrap-manifest/polywrap_manifest/manifest.py @@ -22,17 +22,6 @@ class DeserializeManifestOptions: no_validate: Optional[bool] = None -@dataclass(slots=True, kw_only=True) -class SerializeManifestOptions: - """Options for serializing a manifest to msgpack encoded bytes. - - Attributes: - no_validate: If true, do not validate the manifest. - """ - - no_validate: Optional[bool] = None - - class WrapManifestVersions(Enum): """The versions of the Wrap manifest.""" @@ -68,3 +57,24 @@ class WrapAbiVersions(Enum): LATEST_WRAP_MANIFEST_VERSION = "0.1" LATEST_WRAP_ABI_VERSION = "0.1" + +__all__ = [ + # Options + "DeserializeManifestOptions", + # Enums + "WrapManifestVersions", + "WrapManifestAbiVersions", + "WrapAbiVersions", + # Concrete Versions + "WrapManifest_0_1", + "WrapAbi_0_1_0_1", + # Any Versions + "AnyWrapManifest", + "AnyWrapAbi", + # Latest Versions + "WrapManifest", + "WrapAbi", + # Latest Version constants + "LATEST_WRAP_MANIFEST_VERSION", + "LATEST_WRAP_ABI_VERSION", +] diff --git a/packages/polywrap-msgpack/polywrap_msgpack/__init__.py b/packages/polywrap-msgpack/polywrap_msgpack/__init__.py index fbf10d10..096032d9 100644 --- a/packages/polywrap-msgpack/polywrap_msgpack/__init__.py +++ b/packages/polywrap-msgpack/polywrap_msgpack/__init__.py @@ -14,13 +14,18 @@ from .sanitize import * __all__ = [ + # Serializer "msgpack_decode", "msgpack_encode", + # Extensions "decode_ext_hook", "encode_ext_hook", - "sanitize", "ExtensionTypes", + # Sanitizers + "sanitize", + # Extention types "GenericMap", + # Errors "MsgpackError", "MsgpackDecodeError", "MsgpackEncodeError", diff --git a/packages/polywrap-msgpack/polywrap_msgpack/decoder.py b/packages/polywrap-msgpack/polywrap_msgpack/decoder.py index 9d78a9d7..a768be9b 100644 --- a/packages/polywrap-msgpack/polywrap_msgpack/decoder.py +++ b/packages/polywrap-msgpack/polywrap_msgpack/decoder.py @@ -43,8 +43,8 @@ def msgpack_decode(val: bytes) -> Any: Any: any python object """ try: - return msgpack.unpackb( + return msgpack.unpackb( # pyright: ignore[reportUnknownMemberType] val, ext_hook=decode_ext_hook - ) # pyright: reportUnknownMemberType=false + ) except Exception as e: raise MsgpackDecodeError("Failed to decode msgpack data") from e diff --git a/packages/polywrap-msgpack/polywrap_msgpack/encoder.py b/packages/polywrap-msgpack/polywrap_msgpack/encoder.py index a74642b1..71ea9c16 100644 --- a/packages/polywrap-msgpack/polywrap_msgpack/encoder.py +++ b/packages/polywrap-msgpack/polywrap_msgpack/encoder.py @@ -28,8 +28,12 @@ def encode_ext_hook(obj: Any) -> ExtType: return ExtType( ExtensionTypes.GENERIC_MAP.value, # pylint: disable=protected-access - msgpack_encode(cast(GenericMap[Any, Any], obj)._map), - ) # pyright: reportPrivateUsage=false + msgpack_encode( + cast( + GenericMap[Any, Any], obj + )._map # pyright: ignore[reportPrivateUsage] + ), + ) raise MsgpackExtError(f"Object of type {type(obj)} is not supported") diff --git a/packages/polywrap-msgpack/polywrap_msgpack/sanitize.py b/packages/polywrap-msgpack/polywrap_msgpack/sanitize.py index e2982e36..93d8ba1b 100644 --- a/packages/polywrap-msgpack/polywrap_msgpack/sanitize.py +++ b/packages/polywrap-msgpack/polywrap_msgpack/sanitize.py @@ -22,7 +22,7 @@ def sanitize(value: Any) -> Any: if isinstance(value, GenericMap): dictionary: Dict[Any, Any] = cast( GenericMap[Any, Any], value - )._map # pyright: reportPrivateUsage=false + )._map # pyright: ignore[reportPrivateUsage] new_map: GenericMap[str, Any] = GenericMap({}) for key, val in dictionary.items(): if not isinstance(key, str): diff --git a/packages/polywrap-plugin/node_modules/.yarn-integrity b/packages/polywrap-plugin/node_modules/.yarn-integrity deleted file mode 100644 index 103d87c5..00000000 --- a/packages/polywrap-plugin/node_modules/.yarn-integrity +++ /dev/null @@ -1,30 +0,0 @@ -{ - "systemParams": "darwin-arm64-93", - "modulesFolders": [], - "flags": [], - "linkedModules": [ - "@coordinape/hardhat", - "@polywrap/client-js", - "@polywrap/core-js", - "@polywrap/msgpack-js", - "@polywrap/polywrap-manifest-types-js", - "@polywrap/schema-bind", - "@polywrap/schema-compose", - "@polywrap/schema-parse", - "@polywrap/wrap-manifest-types-js", - "@web3api/cli", - "@web3api/client-js", - "@web3api/core-js", - "@web3api/ethereum-plugin-js", - "@web3api/ipfs-plugin-js", - "@web3api/schema-bind", - "@web3api/schema-compose", - "@web3api/test-env-js", - "@web3api/wasm-as", - "polywrap" - ], - "topLevelPatterns": [], - "lockfileEntries": {}, - "files": [], - "artifacts": {} -} \ No newline at end of file diff --git a/packages/polywrap-plugin/poetry.lock b/packages/polywrap-plugin/poetry.lock index 8a7257a8..97b7dda8 100644 --- a/packages/polywrap-plugin/poetry.lock +++ b/packages/polywrap-plugin/poetry.lock @@ -1,15 +1,15 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry and should not be changed by hand. [[package]] name = "astroid" -version = "2.15.4" +version = "2.15.5" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false python-versions = ">=3.7.2" files = [ - {file = "astroid-2.15.4-py3-none-any.whl", hash = "sha256:a1b8543ef9d36ea777194bc9b17f5f8678d2c56ee6a45b2c2f17eec96f242347"}, - {file = "astroid-2.15.4.tar.gz", hash = "sha256:c81e1c7fbac615037744d067a9bb5f9aeb655edf59b63ee8b59585475d6f80d8"}, + {file = "astroid-2.15.5-py3-none-any.whl", hash = "sha256:078e5212f9885fa85fbb0cf0101978a336190aadea6e13305409d099f71b2324"}, + {file = "astroid-2.15.5.tar.gz", hash = "sha256:1039262575027b441137ab4a62a793a9b43defb42c32d5670f38686207cd780f"}, ] [package.dependencies] @@ -273,42 +273,41 @@ files = [ [[package]] name = "libcst" -version = "0.4.9" +version = "0.4.10" description = "A concrete syntax tree with AST-like properties for Python 3.5, 3.6, 3.7, 3.8, 3.9, and 3.10 programs." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "libcst-0.4.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4f9e42085c403e22201e5c41e707ef73e4ea910ad9fc67983ceee2368097f54e"}, - {file = "libcst-0.4.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1266530bf840cc40633a04feb578bb4cac1aa3aea058cc3729e24eab09a8e996"}, - {file = "libcst-0.4.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9679177391ccb9b0cdde3185c22bf366cb672457c4b7f4031fcb3b5e739fbd6"}, - {file = "libcst-0.4.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d67bc87e0d8db9434f2ea063734938a320f541f4c6da1074001e372f840f385d"}, - {file = "libcst-0.4.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e316da5a126f2a9e1d7680f95f907b575f082a35e2f8bd5620c59b2aaaebfe0a"}, - {file = "libcst-0.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:7415569ab998a85b0fc9af3a204611ea7fadb2d719a12532c448f8fc98f5aca4"}, - {file = "libcst-0.4.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:15ded11ff7f4572f91635e02b519ae959f782689fdb4445bbebb7a3cc5c71d75"}, - {file = "libcst-0.4.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b266867b712a120fad93983de432ddb2ccb062eb5fd2bea748c9a94cb200c36"}, - {file = "libcst-0.4.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:045b3b0b06413cdae6e9751b5f417f789ffa410f2cb2815e3e0e0ea6bef10ec0"}, - {file = "libcst-0.4.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e799add8fba4976628b9c1a6768d73178bf898f0ed1bd1322930c2d3db9063ba"}, - {file = "libcst-0.4.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10479371d04ee8dc978c889c1774bbf6a83df88fa055fcb0159a606f6679c565"}, - {file = "libcst-0.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:7a98286cbbfa90a42d376900c875161ad02a5a2a6b7c94c0f7afd9075e329ce4"}, - {file = "libcst-0.4.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:400166fc4efb9aa06ce44498d443aa78519082695b1894202dd73cd507d2d712"}, - {file = "libcst-0.4.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46123863fba35cc84f7b54dd68826419cabfd9504d8a101c7fe3313ea03776f9"}, - {file = "libcst-0.4.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27be8db54c0e5fe440021a771a38b81a7dbc23cd630eb8b0e9828b7717f9b702"}, - {file = "libcst-0.4.9-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:132bec627b064bd567e7e4cd6c89524d02842151eb0d8f5f3f7ffd2579ec1b09"}, - {file = "libcst-0.4.9-cp37-cp37m-win_amd64.whl", hash = "sha256:596860090aeed3ee6ad1e59c35c6c4110a57e4e896abf51b91cae003ec720a11"}, - {file = "libcst-0.4.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f4487608258109f774300466d4ca97353df29ae6ac23d1502e13e5509423c9d5"}, - {file = "libcst-0.4.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aa53993e9a2853efb3ed3605da39f2e7125df6430f613eb67ef886c1ce4f94b5"}, - {file = "libcst-0.4.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6ce794483d4c605ef0f5b199a49fb6996f9586ca938b7bfef213bd13858d7ab"}, - {file = "libcst-0.4.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:786e562b54bbcd17a060d1244deeef466b7ee07fe544074c252c4a169e38f1ee"}, - {file = "libcst-0.4.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:794250d2359edd518fb698e5d21c38a5bdfc5e4a75d0407b4c19818271ce6742"}, - {file = "libcst-0.4.9-cp38-cp38-win_amd64.whl", hash = "sha256:76491f67431318c3145442e97dddcead7075b074c59eac51be7cc9e3fffec6ee"}, - {file = "libcst-0.4.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3cf48d7aec6dc54b02aec0b1bb413c5bb3b02d852fd6facf1f05c7213e61a176"}, - {file = "libcst-0.4.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b3348c6b7711a5235b133bd8e11d22e903c388db42485b8ceb5f2aa0fae9b9f"}, - {file = "libcst-0.4.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e33b66762efaa014c38819efae5d8f726dd823e32d5d691035484411d2a2a69"}, - {file = "libcst-0.4.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1350d375d3fb9b20a6cf10c09b2964baca9be753a033dde7c1aced49d8e58387"}, - {file = "libcst-0.4.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3822056dc13326082362db35b3f649e0f4a97e36ddb4e487441da8e0fb9db7b3"}, - {file = "libcst-0.4.9-cp39-cp39-win_amd64.whl", hash = "sha256:183636141b839aa35b639e100883813744523bc7c12528906621121731b28443"}, - {file = "libcst-0.4.9.tar.gz", hash = "sha256:01786c403348f76f274dbaf3888ae237ffb73e6ed6973e65eba5c1fc389861dd"}, + {file = "libcst-0.4.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8fa0ec646ed7bce984d0ee9dbf514af278050bdb16a4fb986e916ace534eebc6"}, + {file = "libcst-0.4.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3cb3b7821eac00713844cda079583230c546a589b22ed5f03f2ddc4f985c384b"}, + {file = "libcst-0.4.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7acfa747112ae40b032739661abd7c81aff37191294f7c2dab8bbd72372e78f"}, + {file = "libcst-0.4.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1312e293b864ef3cb4b09534ed5f104c2dc45b680233c68bf76237295041c781"}, + {file = "libcst-0.4.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76884b1afe475e8e68e704bf26eb9f9a2867029643e58f2f26a0286e3b6e998e"}, + {file = "libcst-0.4.10-cp310-cp310-win_amd64.whl", hash = "sha256:1069b808a711db5cd47538f27eb2c73206317aa0d8b5a3500b23aab24f86eb2e"}, + {file = "libcst-0.4.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:50be085346a35812535c7f876319689e15a7bfd1bd8efae8fd70589281d944b6"}, + {file = "libcst-0.4.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bb9f10e5763e361e8bd8ff765fc0f1bcf744f242ff8b6d3e50ffec4dda3972ac"}, + {file = "libcst-0.4.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfeeabb528b5df7b4be1817b584ce79e9a1a66687bd72f6de9c22272462812f1"}, + {file = "libcst-0.4.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5648aeae8c90a2abab1f7b1bf205769a0179ed2cfe1ea7f681f6885e87b8b193"}, + {file = "libcst-0.4.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a144f20aff4643b00374facf8409d30c7935db8176e5b2a07e1fd44004db2c1f"}, + {file = "libcst-0.4.10-cp311-cp311-win_amd64.whl", hash = "sha256:a10adc2e8ea2dda2b70eabec631ead2fc4a7a7ab633d6c2b690823c698b8431a"}, + {file = "libcst-0.4.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58fe90458a26a55358207f74abf8a05dff51d662069f070b4bd308a000a80c09"}, + {file = "libcst-0.4.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:999fbbe467f61cbce9e6e054f86cd1c5ffa3740fd3dc8ebdd600db379f699256"}, + {file = "libcst-0.4.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83ee7e7be4efac4c140a97d772e1f6b3553f98fa5f46ad78df5dfe51e5a4aa4d"}, + {file = "libcst-0.4.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:158478e8f45578fb26621b3dc0fe275f9e004297e9afdcf08936ecda05681174"}, + {file = "libcst-0.4.10-cp37-cp37m-win_amd64.whl", hash = "sha256:5ed101fee1af7abea3684fcff7fab5b170ceea4040756f54c15c870539daec66"}, + {file = "libcst-0.4.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:349f2b4ee4b982fe254c65c78d941fc96299f3c422b79f95ef8c7bba2b7f0f90"}, + {file = "libcst-0.4.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7cfa4d4beb84d0d63247aca27f1a15c63984512274c5b23040f8b4ba511036d7"}, + {file = "libcst-0.4.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24582506da24e31f2644f862f11413a6b80fbad68d15194bfcc3f7dfebf2ec5e"}, + {file = "libcst-0.4.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cdf2d0157438d3d52d310b0b6be31ff99bed19de489b2ebd3e2a4cd9946da45"}, + {file = "libcst-0.4.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a677103d2f1ab0e50bc3a7cc6c96c7d64bcbac826d785e4cbf5ee9aaa9fcfa25"}, + {file = "libcst-0.4.10-cp38-cp38-win_amd64.whl", hash = "sha256:a8fdfd4a7d301adb785aa4b98e4a7cca45c5ff8cfb460b485d081efcfaaeeab7"}, + {file = "libcst-0.4.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b1569d87536bed4e9c11dd5c94a137dc0bce2a2b05961489c6016bf4521bb7cf"}, + {file = "libcst-0.4.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:72dff8783ac79cd10f2bd2fde0b28f262e9a22718ae26990948ba6131b85ca8b"}, + {file = "libcst-0.4.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76adc53660ef094ff83f77a2550a7e00d1cab8e5e63336e071c17c09b5a89fe2"}, + {file = "libcst-0.4.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3e9d9fdd9a9b9b8991936ff1c07527ce7ef396c8233280ba9a7137e72c2e48e"}, + {file = "libcst-0.4.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e1b4cbaf7b1cdad5fa3eababe42d5b46c0d52afe13c5ba4eac2495fc57630ea"}, + {file = "libcst-0.4.10-cp39-cp39-win_amd64.whl", hash = "sha256:bcbd07cec3d7a7be6f0299b0c246e085e3d6cc8af367e2c96059183b97c2e2fe"}, ] [package.dependencies] @@ -317,7 +316,7 @@ typing-extensions = ">=3.7.4.2" typing-inspect = ">=0.4.0" [package.extras] -dev = ["Sphinx (>=5.1.1)", "black (==22.10.0)", "coverage (>=4.5.4)", "fixit (==0.1.1)", "flake8 (>=3.7.8,<5)", "hypothesis (>=4.36.0)", "hypothesmith (>=0.0.4)", "jinja2 (==3.1.2)", "jupyter (>=1.0.0)", "maturin (>=0.8.3,<0.14)", "nbsphinx (>=0.4.2)", "prompt-toolkit (>=2.0.9)", "pyre-check (==0.9.9)", "setuptools-rust (>=1.5.2)", "setuptools-scm (>=6.0.1)", "slotscheck (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "ufmt (==2.0.1)", "usort (==1.0.5)"] +dev = ["Sphinx (>=5.1.1)", "black (==23.1.0)", "build (>=0.10.0)", "coverage (>=4.5.4)", "fixit (==0.1.1)", "flake8 (>=3.7.8,<5)", "hypothesis (>=4.36.0)", "hypothesmith (>=0.0.4)", "jinja2 (==3.1.2)", "jupyter (>=1.0.0)", "maturin (>=0.8.3,<0.14)", "nbsphinx (>=0.4.2)", "prompt-toolkit (>=2.0.9)", "pyre-check (==0.9.10)", "setuptools-rust (>=1.5.2)", "setuptools-scm (>=6.0.1)", "slotscheck (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "ufmt (==2.1.0)", "usort (==1.0.6)"] [[package]] name = "markdown-it-py" @@ -455,14 +454,14 @@ files = [ [[package]] name = "nodeenv" -version = "1.7.0" +version = "1.8.0" description = "Node.js virtual environment builder" category = "dev" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" files = [ - {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, - {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, ] [package.dependencies] @@ -506,18 +505,18 @@ files = [ [[package]] name = "platformdirs" -version = "3.5.0" +version = "3.5.1" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.5.0-py3-none-any.whl", hash = "sha256:47692bc24c1958e8b0f13dd727307cff1db103fca36399f457da8e05f222fdc4"}, - {file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"}, + {file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"}, + {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"}, ] [package.extras] -docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] @@ -737,14 +736,14 @@ testutils = ["gitpython (>3)"] [[package]] name = "pyright" -version = "1.1.306" +version = "1.1.309" description = "Command line wrapper for pyright" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pyright-1.1.306-py3-none-any.whl", hash = "sha256:008eb2a29584ae274a154d749cf81476a3073fb562a462eac8d43a753378b9db"}, - {file = "pyright-1.1.306.tar.gz", hash = "sha256:16d5d198be64de497d5f9002000a271176c381e21b977ca5566cf779b643c9ed"}, + {file = "pyright-1.1.309-py3-none-any.whl", hash = "sha256:a8b052c1997f7334e80074998ea0f93bd149550e8cf27ccb5481d3b2e1aad161"}, + {file = "pyright-1.1.309.tar.gz", hash = "sha256:1abcfa83814d792a5d70b38621cc6489acfade94ebb2279e55ba1f394d54296c"}, ] [package.dependencies] @@ -866,19 +865,19 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "setuptools" -version = "67.7.2" +version = "67.8.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "setuptools-67.7.2-py3-none-any.whl", hash = "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b"}, - {file = "setuptools-67.7.2.tar.gz", hash = "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"}, + {file = "setuptools-67.8.0-py3-none-any.whl", hash = "sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f"}, + {file = "setuptools-67.8.0.tar.gz", hash = "sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] @@ -919,14 +918,14 @@ files = [ [[package]] name = "stevedore" -version = "5.0.0" +version = "5.1.0" description = "Manage dynamic plugins for Python applications" category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "stevedore-5.0.0-py3-none-any.whl", hash = "sha256:bd5a71ff5e5e5f5ea983880e4a1dd1bb47f8feebbb3d95b592398e2f02194771"}, - {file = "stevedore-5.0.0.tar.gz", hash = "sha256:2c428d2338976279e8eb2196f7a94910960d9f7ba2f41f3988511e95ca447021"}, + {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"}, + {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"}, ] [package.dependencies] @@ -1037,14 +1036,14 @@ test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6. [[package]] name = "typing-extensions" -version = "4.5.0" +version = "4.6.0" description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, - {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, + {file = "typing_extensions-4.6.0-py3-none-any.whl", hash = "sha256:6ad00b63f849b7dcc313b70b6b304ed67b2b2963b3098a33efe18056b1a9a223"}, + {file = "typing_extensions-4.6.0.tar.gz", hash = "sha256:ff6b238610c747e44c268aa4bb23c8c735d665a63726df3f9431ce707f2aa768"}, ] [[package]] diff --git a/packages/polywrap-plugin/polywrap_plugin/module.py b/packages/polywrap-plugin/polywrap_plugin/module.py index 8fe6ec06..fea82e2e 100644 --- a/packages/polywrap-plugin/polywrap_plugin/module.py +++ b/packages/polywrap-plugin/polywrap_plugin/module.py @@ -1,21 +1,42 @@ """This module contains the PluginModule class.""" # pylint: disable=invalid-name from abc import ABC -from typing import Any, Generic, TypeVar +from dataclasses import dataclass +from typing import Any, Generic, Optional, TypeVar from polywrap_core import ( - InvokeOptions, - Invoker, - UriPackageOrWrapper, + InvokerClient, + Uri, + UriResolutionContext, WrapAbortError, WrapInvocationError, - execute_maybe_async_function, ) from polywrap_msgpack import msgpack_decode TConfig = TypeVar("TConfig") +@dataclass(kw_only=True, slots=True) +class InvokeOptions: + """InvokeOptions is a dataclass that holds the options for an invocation. + + Attributes: + uri: The URI of the wrapper. + method: The method to invoke. + args: The arguments to pass to the method. + env: The environment variables to set for the invocation. + resolution_context: A URI resolution context. + client: The client to use for subinvocations. + """ + + uri: Uri + method: str + args: Optional[Any] = None + env: Optional[Any] = None + resolution_context: Optional[UriResolutionContext] = None + client: Optional[InvokerClient] = None + + class PluginModule(Generic[TConfig], ABC): """PluginModule is the base class for all plugin modules. @@ -33,20 +54,17 @@ def __init__(self, config: TConfig): """ self.config = config - async def __wrap_invoke__( + def __wrap_invoke__( self, - options: InvokeOptions[UriPackageOrWrapper], - invoker: Invoker[UriPackageOrWrapper], + options: InvokeOptions, ) -> Any: """Invoke a method on the plugin. Args: - method: The name of the method to invoke. - args: The arguments to pass to the method. - invoker: The invoker to use for subinvocations. + options: The options to use when invoking the plugin. Returns: - The result of the plugin method invocation or an error. + The result of the plugin method invocation. """ if not hasattr(self, options.method): raise WrapInvocationError( @@ -61,11 +79,12 @@ async def __wrap_invoke__( if isinstance(options.args, bytes) else options.args ) - return await execute_maybe_async_function( - callable_method, decoded_args, invoker, options.env - ) + return callable_method(decoded_args, options.client, options.env) except Exception as err: raise WrapAbortError(options, repr(err)) from err raise WrapInvocationError( options, f"{options.method} is not a callable method in plugin module" ) + + +__all__ = ["PluginModule"] diff --git a/packages/polywrap-plugin/polywrap_plugin/package.py b/packages/polywrap-plugin/polywrap_plugin/package.py index 609da1ad..4592a348 100644 --- a/packages/polywrap-plugin/polywrap_plugin/package.py +++ b/packages/polywrap-plugin/polywrap_plugin/package.py @@ -2,8 +2,8 @@ # pylint: disable=invalid-name from typing import Generic, Optional, TypeVar -from polywrap_core import GetManifestOptions, UriPackageOrWrapper, WrapPackage, Wrapper -from polywrap_manifest import AnyWrapManifest +from polywrap_core import WrapPackage, Wrapper +from polywrap_manifest import AnyWrapManifest, DeserializeManifestOptions from .module import PluginModule from .wrapper import PluginWrapper @@ -11,7 +11,7 @@ TConfig = TypeVar("TConfig") -class PluginPackage(Generic[TConfig], WrapPackage[UriPackageOrWrapper]): +class PluginPackage(WrapPackage, Generic[TConfig]): """PluginPackage implements IWrapPackage interface for the plugin. Attributes: @@ -32,12 +32,12 @@ def __init__(self, module: PluginModule[TConfig], manifest: AnyWrapManifest): self.module = module self.manifest = manifest - async def create_wrapper(self) -> Wrapper[UriPackageOrWrapper]: + def create_wrapper(self) -> Wrapper: """Create a new plugin wrapper instance.""" return PluginWrapper(module=self.module, manifest=self.manifest) - async def get_manifest( - self, options: Optional[GetManifestOptions] = None + def get_manifest( + self, options: Optional[DeserializeManifestOptions] = None ) -> AnyWrapManifest: """Get the manifest of the plugin. @@ -48,3 +48,6 @@ async def get_manifest( The manifest of the plugin. """ return self.manifest + + +__all__ = ["PluginPackage"] diff --git a/packages/polywrap-plugin/polywrap_plugin/resolution_context_override_client.py b/packages/polywrap-plugin/polywrap_plugin/resolution_context_override_client.py new file mode 100644 index 00000000..3700f72f --- /dev/null +++ b/packages/polywrap-plugin/polywrap_plugin/resolution_context_override_client.py @@ -0,0 +1,84 @@ +"""This module defines the ResolutionContextOverrideClient class.""" +from typing import Any, List, Optional + +from polywrap_core import InvokerClient, Uri, UriResolutionContext + + +class ResolutionContextOverrideClient(InvokerClient): + """A client that overrides the resolution context of the wrapped client. + + Args: + client (InvokerClient): The wrapped client. + resolution_context (Optional[UriResolutionContext]): The resolution context to use. + """ + + client: InvokerClient + resolution_context: Optional[UriResolutionContext] + + __slots__ = ("client", "resolution_context") + + def __init__( + self, client: InvokerClient, resolution_context: Optional[UriResolutionContext] + ): + """Initialize a new ResolutionContextOverrideClient instance.""" + self.client = client + self.resolution_context = resolution_context + + def invoke( + self, + uri: Uri, + method: str, + args: Optional[Any] = None, + env: Optional[Any] = None, + resolution_context: Optional[UriResolutionContext] = None, + encode_result: Optional[bool] = False, + ) -> Any: + """Invoke the Wrapper based on the provided InvokerOptions. + + Args: + uri (Uri): Uri of the wrapper + method (str): Method to be executed + args (Optional[Any]) : Arguments for the method, structured as a dictionary + env (Optional[Any]): Override the client's config for all invokes within this invoke. + resolution_context (Optional[UriResolutionContext]): A URI resolution context + encode_result (Optional[bool]): If True, the result will be encoded + + Returns: + Any: invocation result. + """ + return self.client.invoke( + uri, + method, + args, + env, + self.resolution_context, + encode_result, + ) + + def get_implementations( + self, uri: Uri, apply_resolution: bool = True + ) -> Optional[List[Uri]]: + """Get implementations of an interface with its URI. + + Args: + uri (Uri): URI of the interface. + apply_resolution (bool): If True, apply resolution to the URI and interfaces. + + Returns: + Optional[List[Uri]]: List of implementations or None if not found. + """ + return self.client.get_implementations(uri, apply_resolution) + + def try_resolve_uri( + self, uri: Uri, resolution_context: UriResolutionContext | None = None + ) -> Any: + """Try to resolve a URI to a wrap package, a wrapper, or a URI. + + Args: + uri (Uri): The URI to resolve. + resolution_context (UriResolutionContext): The resolution context. + + Returns: + Any: URI Resolution Result. + """ + return self.client.try_resolve_uri(uri, self.resolution_context) diff --git a/packages/polywrap-plugin/polywrap_plugin/wrapper.py b/packages/polywrap-plugin/polywrap_plugin/wrapper.py index 49604e45..ac947758 100644 --- a/packages/polywrap-plugin/polywrap_plugin/wrapper.py +++ b/packages/polywrap-plugin/polywrap_plugin/wrapper.py @@ -1,24 +1,25 @@ """This module contains the PluginWrapper class.""" # pylint: disable=invalid-name -from typing import Generic, TypeVar, Union +# pylint: disable=too-many-arguments +from typing import Any, Generic, Optional, TypeVar, Union from polywrap_core import ( - GetFileOptions, InvocableResult, - InvokeOptions, - Invoker, - UriPackageOrWrapper, + InvokerClient, + Uri, + UriResolutionContext, Wrapper, ) from polywrap_manifest import AnyWrapManifest -from .module import PluginModule +from .module import InvokeOptions, PluginModule +from .resolution_context_override_client import ResolutionContextOverrideClient TConfig = TypeVar("TConfig") TResult = TypeVar("TResult") -class PluginWrapper(Generic[TConfig], Wrapper[UriPackageOrWrapper]): +class PluginWrapper(Wrapper, Generic[TConfig]): """PluginWrapper implements the Wrapper interface for plugin wrappers. Attributes: @@ -41,31 +42,53 @@ def __init__( self.module = module self.manifest = manifest - async def invoke( + def invoke( self, - options: InvokeOptions[UriPackageOrWrapper], - invoker: Invoker[UriPackageOrWrapper], + uri: Uri, + method: str, + args: Optional[Any] = None, + env: Optional[Any] = None, + resolution_context: Optional[UriResolutionContext] = None, + client: Optional[InvokerClient] = None, ) -> InvocableResult: - """Invoke a method on the plugin. + """Invoke the Wrapper based on the provided InvokeOptions. Args: - options (InvokeOptions): options to use when invoking the plugin. - invoker (Invoker): the invoker to use when invoking the plugin. + uri (Uri): Uri of the wrapper + method (str): Method to be executed + args (Optional[Any]) : Arguments for the method, structured as a dictionary + env (Optional[Any]): Override the client's config for all invokes within this invoke. + resolution_context (Optional[UriResolutionContext]): A URI resolution context + client (Optional[Invoker]): The invoker instance requesting this invocation.\ + This invoker will be used for any subinvocation that may occur. Returns: - Result[InvocableResult]: the result of the invocation. + InvocableResult: Result of the invocation. """ - result = await self.module.__wrap_invoke__(options, invoker) + options = InvokeOptions( + uri=uri, + method=method, + args=args, + env=env, + resolution_context=resolution_context, + client=ResolutionContextOverrideClient(client, resolution_context) + if client + else None, + ) + result = self.module.__wrap_invoke__(options) return InvocableResult(result=result, encoded=False) - async def get_file(self, options: GetFileOptions) -> Union[str, bytes]: - """Get a file from the plugin. + def get_file( + self, path: str, encoding: Optional[str] = "utf-8" + ) -> Union[str, bytes]: + """Get a file from the wrapper. Args: - options (GetFileOptions): options to use when getting the file. + path (str): Path to the file. + encoding (Optional[str]): Encoding of the file. Returns: - Result[Union[str, bytes]]: the file contents or an error. + Union[str, bytes]: The file contents """ raise NotImplementedError("client.get_file(..) is not implemented for plugins") @@ -76,3 +99,6 @@ def get_manifest(self) -> AnyWrapManifest: Result[AnyWrapManifest]: the manifest of the plugin. """ return self.manifest + + +__all__ = ["PluginWrapper"] diff --git a/packages/polywrap-plugin/pyproject.toml b/packages/polywrap-plugin/pyproject.toml index fa462b30..2f579e76 100644 --- a/packages/polywrap-plugin/pyproject.toml +++ b/packages/polywrap-plugin/pyproject.toml @@ -50,6 +50,7 @@ disable = [ "too-many-return-statements", "broad-exception-caught", "too-few-public-methods", + "too-many-arguments", ] ignore = [ "tests/" diff --git a/packages/polywrap-plugin/tests/conftest.py b/packages/polywrap-plugin/tests/conftest.py index 6fc7aa3b..d15900c0 100644 --- a/packages/polywrap-plugin/tests/conftest.py +++ b/packages/polywrap-plugin/tests/conftest.py @@ -2,15 +2,15 @@ from typing import Any, Dict, List, Union, Optional from polywrap_plugin import PluginModule -from polywrap_core import Invoker, Uri, InvokerOptions, UriPackageOrWrapper, Env +from polywrap_core import InvokerClient, Uri @fixture -def invoker() -> Invoker[UriPackageOrWrapper]: - class MockInvoker(Invoker[UriPackageOrWrapper]): - async def invoke(self, options: InvokerOptions[UriPackageOrWrapper]) -> Any: +def client() -> InvokerClient: + class MockInvoker(InvokerClient): + async def invoke(self, *args: Any) -> Any: raise NotImplementedError() - def get_implementations(self, uri: Uri) -> Union[List[Uri], None]: + def get_implementations(self, *args: Any) -> Union[List[Uri], None]: raise NotImplementedError() return MockInvoker() @@ -22,7 +22,7 @@ class GreetingModule(PluginModule[None]): def __init__(self, config: None): super().__init__(config) - def greeting(self, args: Dict[str, Any], client: Invoker[UriPackageOrWrapper], env: Optional[Env] = None): + def greeting(self, args: Dict[str, Any], client: InvokerClient, env: Optional[Any] = None): return f"Greetings from: {args['name']}" return GreetingModule(None) \ No newline at end of file diff --git a/packages/polywrap-plugin/tests/test_plugin_module.py b/packages/polywrap-plugin/tests/test_plugin_module.py index ef18454b..a308a276 100644 --- a/packages/polywrap-plugin/tests/test_plugin_module.py +++ b/packages/polywrap-plugin/tests/test_plugin_module.py @@ -1,16 +1,14 @@ -import pytest -from polywrap_core import Invoker, Uri, UriPackageOrWrapper, InvokeOptions +from polywrap_core import InvokerClient, Uri from polywrap_plugin import PluginModule +from polywrap_plugin.module import InvokeOptions -@pytest.mark.asyncio -async def test_plugin_module( - greeting_module: PluginModule[None], invoker: Invoker[UriPackageOrWrapper] +def test_plugin_module( + greeting_module: PluginModule[None], client: InvokerClient ): - result = await greeting_module.__wrap_invoke__( + result = greeting_module.__wrap_invoke__( InvokeOptions( - uri=Uri.from_str("plugin/greeting"), method="greeting", args={"name": "Joe"} + uri=Uri.from_str("plugin/greeting"), method="greeting", args={"name": "Joe"}, client=client ), - invoker, ) assert result, "Greetings from: Joe" diff --git a/packages/polywrap-plugin/tests/test_plugin_package.py b/packages/polywrap-plugin/tests/test_plugin_package.py index aa4dc9f4..5af64b23 100644 --- a/packages/polywrap-plugin/tests/test_plugin_package.py +++ b/packages/polywrap-plugin/tests/test_plugin_package.py @@ -1,24 +1,31 @@ from typing import cast -import pytest -from polywrap_core import InvokeOptions, Uri, Invoker, UriPackageOrWrapper +from polywrap_core import Uri, InvokerClient from polywrap_manifest import AnyWrapManifest from polywrap_plugin import PluginPackage, PluginModule -@pytest.mark.asyncio -async def test_plugin_package_invoke(greeting_module: PluginModule[None], invoker: Invoker[UriPackageOrWrapper]): +def test_plugin_package_invoke( + greeting_module: PluginModule[None], client: InvokerClient +): manifest = cast(AnyWrapManifest, {}) plugin_package = PluginPackage(greeting_module, manifest) - wrapper = await plugin_package.create_wrapper() - args = { - "name": "Joe" - } - options: InvokeOptions[UriPackageOrWrapper] = InvokeOptions( + wrapper = plugin_package.create_wrapper() + args = {"name": "Joe"} + + result = wrapper.invoke( uri=Uri.from_str("ens/greeting.eth"), method="greeting", - args=args + args=args, + client=client, ) + assert result, "Greetings from: Joe" + - result = await wrapper.invoke(options, invoker) - assert result, "Greetings from: Joe" \ No newline at end of file +def test_plugin_package_get_manifest( + greeting_module: PluginModule[None], client: InvokerClient +): + manifest = cast(AnyWrapManifest, {}) + plugin_package = PluginPackage(greeting_module, manifest) + + assert plugin_package.get_manifest() is manifest diff --git a/packages/polywrap-plugin/tests/test_plugin_wrapper.py b/packages/polywrap-plugin/tests/test_plugin_wrapper.py index 779b7328..25dcd8cf 100644 --- a/packages/polywrap-plugin/tests/test_plugin_wrapper.py +++ b/packages/polywrap-plugin/tests/test_plugin_wrapper.py @@ -1,24 +1,48 @@ from typing import cast -import pytest -from polywrap_core import InvokeOptions, Uri, Invoker, UriPackageOrWrapper +from polywrap_core import Uri, InvokerClient from polywrap_manifest import AnyWrapManifest from polywrap_plugin import PluginWrapper, PluginModule +import pytest -@pytest.mark.asyncio -async def test_plugin_wrapper_invoke(greeting_module: PluginModule[None], invoker: Invoker[UriPackageOrWrapper]): + +def test_plugin_wrapper_invoke( + greeting_module: PluginModule[None], client: InvokerClient +): manifest = cast(AnyWrapManifest, {}) wrapper = PluginWrapper(greeting_module, manifest) - args = { - "name": "Joe" - } - options: InvokeOptions[UriPackageOrWrapper] = InvokeOptions( + args = {"name": "Joe"} + + result = wrapper.invoke( uri=Uri.from_str("ens/greeting.eth"), method="greeting", - args=args + args=args, + client=client, ) + assert result, "Greetings from: Joe" + + +def test_plugin_wrapper_get_file( + greeting_module: PluginModule[None], client: InvokerClient +): + manifest = cast(AnyWrapManifest, {}) + + wrapper = PluginWrapper(greeting_module, manifest) + + with pytest.raises(NotImplementedError): + wrapper.get_file( + path="greeting.txt", + encoding="utf-8", + ) + + +def test_plugin_wrapper_manifest( + greeting_module: PluginModule[None], client: InvokerClient +): + manifest = cast(AnyWrapManifest, {}) + + wrapper = PluginWrapper(greeting_module, manifest) - result = await wrapper.invoke(options, invoker) - assert result, "Greetings from: Joe" \ No newline at end of file + assert wrapper.manifest is manifest diff --git a/packages/polywrap-test-cases/.gitignore b/packages/polywrap-test-cases/.gitignore new file mode 100644 index 00000000..4faabeff --- /dev/null +++ b/packages/polywrap-test-cases/.gitignore @@ -0,0 +1 @@ +wrappers/ \ No newline at end of file diff --git a/packages/polywrap-test-cases/README.md b/packages/polywrap-test-cases/README.md new file mode 100644 index 00000000..00bdf773 --- /dev/null +++ b/packages/polywrap-test-cases/README.md @@ -0,0 +1,36 @@ +# polywrap-wasm + +Python implementation of the plugin wrapper runtime. + +## Usage + +### Invoke Plugin Wrapper + +```python +from typing import Any, Dict, List, Union, Optional +from polywrap_manifest import AnyWrapManifest +from polywrap_plugin import PluginModule +from polywrap_core import Invoker, Uri, InvokerOptions, UriPackageOrWrapper, Env + +class GreetingModule(PluginModule[None]): + def __init__(self, config: None): + super().__init__(config) + + def greeting(self, args: Dict[str, Any], client: Invoker[UriPackageOrWrapper], env: Optional[Env] = None): + return f"Greetings from: {args['name']}" + +manifest = cast(AnyWrapManifest, {}) +wrapper = PluginWrapper(greeting_module, manifest) +args = { + "name": "Joe" +} +options: InvokeOptions[UriPackageOrWrapper] = InvokeOptions( + uri=Uri.from_str("ens/greeting.eth"), + method="greeting", + args=args +) +invoker: Invoker = ... + +result = await wrapper.invoke(options, invoker) +assert result, "Greetings from: Joe" +``` diff --git a/packages/polywrap-test-cases/poetry.lock b/packages/polywrap-test-cases/poetry.lock new file mode 100644 index 00000000..204c9efd --- /dev/null +++ b/packages/polywrap-test-cases/poetry.lock @@ -0,0 +1,996 @@ +# This file is automatically @generated by Poetry and should not be changed by hand. + +[[package]] +name = "astroid" +version = "2.15.4" +description = "An abstract syntax tree for Python with inference support." +category = "dev" +optional = false +python-versions = ">=3.7.2" +files = [ + {file = "astroid-2.15.4-py3-none-any.whl", hash = "sha256:a1b8543ef9d36ea777194bc9b17f5f8678d2c56ee6a45b2c2f17eec96f242347"}, + {file = "astroid-2.15.4.tar.gz", hash = "sha256:c81e1c7fbac615037744d067a9bb5f9aeb655edf59b63ee8b59585475d6f80d8"}, +] + +[package.dependencies] +lazy-object-proxy = ">=1.4.0" +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} +wrapt = [ + {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, + {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, +] + +[[package]] +name = "bandit" +version = "1.7.5" +description = "Security oriented static analyser for python code." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "bandit-1.7.5-py3-none-any.whl", hash = "sha256:75665181dc1e0096369112541a056c59d1c5f66f9bb74a8d686c3c362b83f549"}, + {file = "bandit-1.7.5.tar.gz", hash = "sha256:bdfc739baa03b880c2d15d0431b31c658ffc348e907fe197e54e0389dd59e11e"}, +] + +[package.dependencies] +colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} +GitPython = ">=1.0.1" +PyYAML = ">=5.3.1" +rich = "*" +stevedore = ">=1.20.0" +tomli = {version = ">=1.1.0", optional = true, markers = "python_version < \"3.11\" and extra == \"toml\""} + +[package.extras] +test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "tomli (>=1.1.0)"] +toml = ["tomli (>=1.1.0)"] +yaml = ["PyYAML"] + +[[package]] +name = "black" +version = "22.12.0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, + {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, + {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, + {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, + {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, + {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, + {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, + {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, + {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, + {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, + {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, + {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "dill" +version = "0.3.6" +description = "serialize all of python" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, + {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] + +[[package]] +name = "distlib" +version = "0.3.6" +description = "Distribution utilities" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"}, + {file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.1.1" +description = "Backport of PEP 654 (exception groups)" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, + {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "filelock" +version = "3.12.0" +description = "A platform independent file lock." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "filelock-3.12.0-py3-none-any.whl", hash = "sha256:ad98852315c2ab702aeb628412cbf7e95b7ce8c3bf9565670b4eaecf1db370a9"}, + {file = "filelock-3.12.0.tar.gz", hash = "sha256:fc03ae43288c013d2ea83c8597001b1129db351aad9c57fe2409327916b8e718"}, +] + +[package.extras] +docs = ["furo (>=2023.3.27)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] + +[[package]] +name = "gitdb" +version = "4.0.10" +description = "Git Object Database" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "gitdb-4.0.10-py3-none-any.whl", hash = "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7"}, + {file = "gitdb-4.0.10.tar.gz", hash = "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a"}, +] + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.31" +description = "GitPython is a Python library used to interact with Git repositories" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "GitPython-3.1.31-py3-none-any.whl", hash = "sha256:f04893614f6aa713a60cbbe1e6a97403ef633103cdd0ef5eb6efe0deb98dbe8d"}, + {file = "GitPython-3.1.31.tar.gz", hash = "sha256:8ce3bcf69adfdf7c7d503e78fd3b1c492af782d58893b650adb2ac8912ddd573"}, +] + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "isort" +version = "5.12.0" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, +] + +[package.extras] +colors = ["colorama (>=0.4.3)"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] +plugins = ["setuptools"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] + +[[package]] +name = "lazy-object-proxy" +version = "1.9.0" +description = "A fast and thorough lazy object proxy." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, +] + +[[package]] +name = "libcst" +version = "0.4.9" +description = "A concrete syntax tree with AST-like properties for Python 3.5, 3.6, 3.7, 3.8, 3.9, and 3.10 programs." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "libcst-0.4.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4f9e42085c403e22201e5c41e707ef73e4ea910ad9fc67983ceee2368097f54e"}, + {file = "libcst-0.4.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1266530bf840cc40633a04feb578bb4cac1aa3aea058cc3729e24eab09a8e996"}, + {file = "libcst-0.4.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9679177391ccb9b0cdde3185c22bf366cb672457c4b7f4031fcb3b5e739fbd6"}, + {file = "libcst-0.4.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d67bc87e0d8db9434f2ea063734938a320f541f4c6da1074001e372f840f385d"}, + {file = "libcst-0.4.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e316da5a126f2a9e1d7680f95f907b575f082a35e2f8bd5620c59b2aaaebfe0a"}, + {file = "libcst-0.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:7415569ab998a85b0fc9af3a204611ea7fadb2d719a12532c448f8fc98f5aca4"}, + {file = "libcst-0.4.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:15ded11ff7f4572f91635e02b519ae959f782689fdb4445bbebb7a3cc5c71d75"}, + {file = "libcst-0.4.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b266867b712a120fad93983de432ddb2ccb062eb5fd2bea748c9a94cb200c36"}, + {file = "libcst-0.4.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:045b3b0b06413cdae6e9751b5f417f789ffa410f2cb2815e3e0e0ea6bef10ec0"}, + {file = "libcst-0.4.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e799add8fba4976628b9c1a6768d73178bf898f0ed1bd1322930c2d3db9063ba"}, + {file = "libcst-0.4.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10479371d04ee8dc978c889c1774bbf6a83df88fa055fcb0159a606f6679c565"}, + {file = "libcst-0.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:7a98286cbbfa90a42d376900c875161ad02a5a2a6b7c94c0f7afd9075e329ce4"}, + {file = "libcst-0.4.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:400166fc4efb9aa06ce44498d443aa78519082695b1894202dd73cd507d2d712"}, + {file = "libcst-0.4.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46123863fba35cc84f7b54dd68826419cabfd9504d8a101c7fe3313ea03776f9"}, + {file = "libcst-0.4.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27be8db54c0e5fe440021a771a38b81a7dbc23cd630eb8b0e9828b7717f9b702"}, + {file = "libcst-0.4.9-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:132bec627b064bd567e7e4cd6c89524d02842151eb0d8f5f3f7ffd2579ec1b09"}, + {file = "libcst-0.4.9-cp37-cp37m-win_amd64.whl", hash = "sha256:596860090aeed3ee6ad1e59c35c6c4110a57e4e896abf51b91cae003ec720a11"}, + {file = "libcst-0.4.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f4487608258109f774300466d4ca97353df29ae6ac23d1502e13e5509423c9d5"}, + {file = "libcst-0.4.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aa53993e9a2853efb3ed3605da39f2e7125df6430f613eb67ef886c1ce4f94b5"}, + {file = "libcst-0.4.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6ce794483d4c605ef0f5b199a49fb6996f9586ca938b7bfef213bd13858d7ab"}, + {file = "libcst-0.4.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:786e562b54bbcd17a060d1244deeef466b7ee07fe544074c252c4a169e38f1ee"}, + {file = "libcst-0.4.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:794250d2359edd518fb698e5d21c38a5bdfc5e4a75d0407b4c19818271ce6742"}, + {file = "libcst-0.4.9-cp38-cp38-win_amd64.whl", hash = "sha256:76491f67431318c3145442e97dddcead7075b074c59eac51be7cc9e3fffec6ee"}, + {file = "libcst-0.4.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3cf48d7aec6dc54b02aec0b1bb413c5bb3b02d852fd6facf1f05c7213e61a176"}, + {file = "libcst-0.4.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b3348c6b7711a5235b133bd8e11d22e903c388db42485b8ceb5f2aa0fae9b9f"}, + {file = "libcst-0.4.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e33b66762efaa014c38819efae5d8f726dd823e32d5d691035484411d2a2a69"}, + {file = "libcst-0.4.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1350d375d3fb9b20a6cf10c09b2964baca9be753a033dde7c1aced49d8e58387"}, + {file = "libcst-0.4.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3822056dc13326082362db35b3f649e0f4a97e36ddb4e487441da8e0fb9db7b3"}, + {file = "libcst-0.4.9-cp39-cp39-win_amd64.whl", hash = "sha256:183636141b839aa35b639e100883813744523bc7c12528906621121731b28443"}, + {file = "libcst-0.4.9.tar.gz", hash = "sha256:01786c403348f76f274dbaf3888ae237ffb73e6ed6973e65eba5c1fc389861dd"}, +] + +[package.dependencies] +pyyaml = ">=5.2" +typing-extensions = ">=3.7.4.2" +typing-inspect = ">=0.4.0" + +[package.extras] +dev = ["Sphinx (>=5.1.1)", "black (==22.10.0)", "coverage (>=4.5.4)", "fixit (==0.1.1)", "flake8 (>=3.7.8,<5)", "hypothesis (>=4.36.0)", "hypothesmith (>=0.0.4)", "jinja2 (==3.1.2)", "jupyter (>=1.0.0)", "maturin (>=0.8.3,<0.14)", "nbsphinx (>=0.4.2)", "prompt-toolkit (>=2.0.9)", "pyre-check (==0.9.9)", "setuptools-rust (>=1.5.2)", "setuptools-scm (>=6.0.1)", "slotscheck (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "ufmt (==2.0.1)", "usort (==1.0.5)"] + +[[package]] +name = "markdown-it-py" +version = "2.2.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"}, + {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "nodeenv" +version = "1.7.0" +description = "Node.js virtual environment builder" +category = "dev" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +files = [ + {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, + {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, +] + +[package.dependencies] +setuptools = "*" + +[[package]] +name = "packaging" +version = "23.1" +description = "Core utilities for Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, +] + +[[package]] +name = "pathspec" +version = "0.10.3" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.10.3-py3-none-any.whl", hash = "sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6"}, + {file = "pathspec-0.10.3.tar.gz", hash = "sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6"}, +] + +[[package]] +name = "pbr" +version = "5.11.1" +description = "Python Build Reasonableness" +category = "dev" +optional = false +python-versions = ">=2.6" +files = [ + {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"}, + {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"}, +] + +[[package]] +name = "platformdirs" +version = "3.5.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.5.0-py3-none-any.whl", hash = "sha256:47692bc24c1958e8b0f13dd727307cff1db103fca36399f457da8e05f222fdc4"}, + {file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"}, +] + +[package.extras] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] + +[[package]] +name = "pluggy" +version = "1.0.0" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] + +[[package]] +name = "pycln" +version = "2.1.3" +description = "A formatter for finding and removing unused import statements." +category = "dev" +optional = false +python-versions = ">=3.6.2,<4" +files = [ + {file = "pycln-2.1.3-py3-none-any.whl", hash = "sha256:161142502e4ff9853cd462a38401e29eb56235919856df2cb7fa4c84e463717f"}, + {file = "pycln-2.1.3.tar.gz", hash = "sha256:a33bfc64ded74a623b7cf49eca38b58db4348facc60c35af26d45de149b256f5"}, +] + +[package.dependencies] +libcst = {version = ">=0.3.10,<0.5.0", markers = "python_version >= \"3.7\""} +pathspec = ">=0.9.0,<0.11.0" +pyyaml = ">=5.3.1,<7.0.0" +tomlkit = ">=0.11.1,<0.12.0" +typer = ">=0.4.1,<0.8.0" + +[[package]] +name = "pydocstyle" +version = "6.3.0" +description = "Python docstring style checker" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, + {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, +] + +[package.dependencies] +snowballstemmer = ">=2.2.0" + +[package.extras] +toml = ["tomli (>=1.2.3)"] + +[[package]] +name = "pygments" +version = "2.15.1" +description = "Pygments is a syntax highlighting package written in Python." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"}, + {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"}, +] + +[package.extras] +plugins = ["importlib-metadata"] + +[[package]] +name = "pylint" +version = "2.17.3" +description = "python code static checker" +category = "dev" +optional = false +python-versions = ">=3.7.2" +files = [ + {file = "pylint-2.17.3-py3-none-any.whl", hash = "sha256:a6cbb4c6e96eab4a3c7de7c6383c512478f58f88d95764507d84c899d656a89a"}, + {file = "pylint-2.17.3.tar.gz", hash = "sha256:761907349e699f8afdcd56c4fe02f3021ab5b3a0fc26d19a9bfdc66c7d0d5cd5"}, +] + +[package.dependencies] +astroid = ">=2.15.4,<=2.17.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = [ + {version = ">=0.2", markers = "python_version < \"3.11\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, +] +isort = ">=4.2.5,<6" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + +[[package]] +name = "pyright" +version = "1.1.305" +description = "Command line wrapper for pyright" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyright-1.1.305-py3-none-any.whl", hash = "sha256:147da3aac44ba0516423613cad5fbb7a0abba6b71c53718a1e151f456d4ab12e"}, + {file = "pyright-1.1.305.tar.gz", hash = "sha256:924d554253ecc4fafdfbfa76989d173cc15d426aa808630c0dd669fdc3227ef7"}, +] + +[package.dependencies] +nodeenv = ">=1.6.0" + +[package.extras] +all = ["twine (>=3.4.1)"] +dev = ["twine (>=3.4.1)"] + +[[package]] +name = "pytest" +version = "7.3.1" +description = "pytest: simple powerful testing with Python" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"}, + {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] + +[[package]] +name = "pytest-asyncio" +version = "0.19.0" +description = "Pytest support for asyncio" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-asyncio-0.19.0.tar.gz", hash = "sha256:ac4ebf3b6207259750bc32f4c1d8fcd7e79739edbc67ad0c58dd150b1d072fed"}, + {file = "pytest_asyncio-0.19.0-py3-none-any.whl", hash = "sha256:7a97e37cfe1ed296e2e84941384bdd37c376453912d397ed39293e0916f521fa"}, +] + +[package.dependencies] +pytest = ">=6.1.0" + +[package.extras] +testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] + +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, + {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, + {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] + +[[package]] +name = "rich" +version = "13.3.5" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "dev" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "rich-13.3.5-py3-none-any.whl", hash = "sha256:69cdf53799e63f38b95b9bf9c875f8c90e78dd62b2f00c13a911c7a3b9fa4704"}, + {file = "rich-13.3.5.tar.gz", hash = "sha256:2d11b9b8dd03868f09b4fffadc84a6a8cda574e40dc90821bd845720ebb8e89c"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0,<3.0.0" +pygments = ">=2.13.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "setuptools" +version = "67.7.2" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "setuptools-67.7.2-py3-none-any.whl", hash = "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b"}, + {file = "setuptools-67.7.2.tar.gz", hash = "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "smmap" +version = "5.0.0" +description = "A pure Python implementation of a sliding window memory map manager" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, + {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, +] + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] + +[[package]] +name = "stevedore" +version = "5.0.0" +description = "Manage dynamic plugins for Python applications" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "stevedore-5.0.0-py3-none-any.whl", hash = "sha256:bd5a71ff5e5e5f5ea983880e4a1dd1bb47f8feebbb3d95b592398e2f02194771"}, + {file = "stevedore-5.0.0.tar.gz", hash = "sha256:2c428d2338976279e8eb2196f7a94910960d9f7ba2f41f3988511e95ca447021"}, +] + +[package.dependencies] +pbr = ">=2.0.0,<2.1.0 || >2.1.0" + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "dev" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "tomlkit" +version = "0.11.8" +description = "Style preserving TOML library" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, + {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, +] + +[[package]] +name = "tox" +version = "3.28.0" +description = "tox is a generic virtualenv management and test command line tool" +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +files = [ + {file = "tox-3.28.0-py2.py3-none-any.whl", hash = "sha256:57b5ab7e8bb3074edc3c0c0b4b192a4f3799d3723b2c5b76f1fa9f2d40316eea"}, + {file = "tox-3.28.0.tar.gz", hash = "sha256:d0d28f3fe6d6d7195c27f8b054c3e99d5451952b54abdae673b71609a581f640"}, +] + +[package.dependencies] +colorama = {version = ">=0.4.1", markers = "platform_system == \"Windows\""} +filelock = ">=3.0.0" +packaging = ">=14" +pluggy = ">=0.12.0" +py = ">=1.4.17" +six = ">=1.14.0" +tomli = {version = ">=2.0.1", markers = "python_version >= \"3.7\" and python_version < \"3.11\""} +virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2,<20.0.3 || >20.0.3,<20.0.4 || >20.0.4,<20.0.5 || >20.0.5,<20.0.6 || >20.0.6,<20.0.7 || >20.0.7" + +[package.extras] +docs = ["pygments-github-lexers (>=0.0.5)", "sphinx (>=2.0.0)", "sphinxcontrib-autoprogram (>=0.1.5)", "towncrier (>=18.5.0)"] +testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pathlib2 (>=2.3.3)", "psutil (>=5.6.1)", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)"] + +[[package]] +name = "tox-poetry" +version = "0.4.1" +description = "Tox poetry plugin" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "tox-poetry-0.4.1.tar.gz", hash = "sha256:2395808e1ce487b5894c10f2202e14702bfa6d6909c0d1e525170d14809ac7ef"}, + {file = "tox_poetry-0.4.1-py2.py3-none-any.whl", hash = "sha256:11d9cd4e51d4cd9484b3ba63f2650ab4cfb4096e5f0682ecf561ddfc3c8e8c92"}, +] + +[package.dependencies] +pluggy = "*" +toml = "*" +tox = {version = ">=3.7.0", markers = "python_version >= \"3\""} + +[package.extras] +test = ["coverage", "pycodestyle", "pylint", "pytest"] + +[[package]] +name = "typer" +version = "0.7.0" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "typer-0.7.0-py3-none-any.whl", hash = "sha256:b5e704f4e48ec263de1c0b3a2387cd405a13767d2f907f44c1a08cbad96f606d"}, + {file = "typer-0.7.0.tar.gz", hash = "sha256:ff797846578a9f2a201b53442aedeb543319466870fbe1c701eab66dd7681165"}, +] + +[package.dependencies] +click = ">=7.1.1,<9.0.0" + +[package.extras] +all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<13.0.0)", "shellingham (>=1.3.0,<2.0.0)"] +dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"] +doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"] +test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<13.0.0)", "shellingham (>=1.3.0,<2.0.0)"] + +[[package]] +name = "typing-extensions" +version = "4.5.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, + {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, +] + +[[package]] +name = "typing-inspect" +version = "0.8.0" +description = "Runtime inspection utilities for typing module." +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "typing_inspect-0.8.0-py3-none-any.whl", hash = "sha256:5fbf9c1e65d4fa01e701fe12a5bca6c6e08a4ffd5bc60bfac028253a447c5188"}, + {file = "typing_inspect-0.8.0.tar.gz", hash = "sha256:8b1ff0c400943b6145df8119c41c244ca8207f1f10c9c057aeed1560e4806e3d"}, +] + +[package.dependencies] +mypy-extensions = ">=0.3.0" +typing-extensions = ">=3.7.4" + +[[package]] +name = "virtualenv" +version = "20.23.0" +description = "Virtual Python Environment builder" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.23.0-py3-none-any.whl", hash = "sha256:6abec7670e5802a528357fdc75b26b9f57d5d92f29c5462ba0fbe45feacc685e"}, + {file = "virtualenv-20.23.0.tar.gz", hash = "sha256:a85caa554ced0c0afbd0d638e7e2d7b5f92d23478d05d17a76daeac8f279f924"}, +] + +[package.dependencies] +distlib = ">=0.3.6,<1" +filelock = ">=3.11,<4" +platformdirs = ">=3.2,<4" + +[package.extras] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.7.1)", "time-machine (>=2.9)"] + +[[package]] +name = "wrapt" +version = "1.15.0" +description = "Module for decorators, wrappers and monkey patching." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +files = [ + {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, + {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, + {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, + {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, + {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, + {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, + {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, + {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, + {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, + {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, + {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, + {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, + {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, + {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, + {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, + {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, + {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, + {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, + {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.10" +content-hash = "da96c8da6df9a1e93509950d064ca803bad959afa8b85410e059156293a30447" diff --git a/packages/polywrap-test-cases/polywrap_test_cases/__init__.py b/packages/polywrap-test-cases/polywrap_test_cases/__init__.py new file mode 100644 index 00000000..b74016f8 --- /dev/null +++ b/packages/polywrap-test-cases/polywrap_test_cases/__init__.py @@ -0,0 +1,39 @@ +"""This package contains the utility functions to fetch the wrappers\ + from the wasm-test-harness repo.""" +import io +import os +import zipfile +from urllib.error import HTTPError +from urllib.request import urlopen + + +def get_path_to_test_wrappers() -> str: + """Get the path to the test wrappers.""" + return os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "wrappers")) + + +def fetch_file(url: str) -> bytes: + """Fetch a file using HTTP.""" + with urlopen(url) as response: + if response.status != 200: + raise HTTPError( + url, response.status, "Failed to fetch file", response.headers, None + ) + return response.read() + + +def unzip_file(file_buffer: bytes, destination: str) -> None: + """Unzip a file to a destination.""" + with zipfile.ZipFile(io.BytesIO(file_buffer), "r") as zip_ref: + zip_ref.extractall(destination) + + +def fetch_wrappers() -> None: + """Fetch the wrappers from the wasm-test-harness repo.""" + tag = "0.1.0" + repo_name = "wasm-test-harness" + url = f"https://github.com/polywrap/{repo_name}/releases/download/{tag}/wrappers" + + buffer = fetch_file(url) + zip_built_folder = get_path_to_test_wrappers() + unzip_file(buffer, zip_built_folder) diff --git a/packages/polywrap-test-cases/polywrap_test_cases/__main__.py b/packages/polywrap-test-cases/polywrap_test_cases/__main__.py new file mode 100644 index 00000000..3df55d7f --- /dev/null +++ b/packages/polywrap-test-cases/polywrap_test_cases/__main__.py @@ -0,0 +1,5 @@ +"""This module contains the main entry point of the package.""" +from . import fetch_wrappers + +if __name__ == "__main__": + fetch_wrappers() diff --git a/packages/polywrap-test-cases/polywrap_test_cases/py.typed b/packages/polywrap-test-cases/polywrap_test_cases/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-test-cases/pyproject.toml b/packages/polywrap-test-cases/pyproject.toml new file mode 100644 index 00000000..73aad8e5 --- /dev/null +++ b/packages/polywrap-test-cases/pyproject.toml @@ -0,0 +1,59 @@ +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +name = "polywrap-test-cases" +version = "0.1.0a29" +description = "Plugin package" +authors = ["Cesar "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.10" + +[tool.poetry.dev-dependencies] +pytest = "^7.1.2" +pytest-asyncio = "^0.19.0" +pylint = "^2.15.4" +black = "^22.10.0" +bandit = { version = "^1.7.4", extras = ["toml"]} +tox = "^3.26.0" +tox-poetry = "^0.4.1" +isort = "^5.10.1" +pyright = "^1.1.275" +pydocstyle = "^6.1.1" + +[tool.poetry.group.dev.dependencies] +pycln = "^2.1.3" + +[tool.bandit] +exclude_dirs = ["tests"] +skips = ["B310"] + +[tool.black] +target-version = ["py310"] + +[tool.pyright] +typeCheckingMode = "strict" +reportShadowedImports = false + +[tool.pytest.ini_options] +asyncio_mode = "auto" +testpaths = [ + "tests" +] + +[tool.pylint] +disable = [ +] +ignore = [ + "tests/" +] + +[tool.isort] +profile = "black" +multi_line_output = 3 + +[tool.pydocstyle] +# default \ No newline at end of file diff --git a/packages/polywrap-test-cases/tests/test_sanity.py b/packages/polywrap-test-cases/tests/test_sanity.py new file mode 100644 index 00000000..176c6edf --- /dev/null +++ b/packages/polywrap-test-cases/tests/test_sanity.py @@ -0,0 +1,16 @@ +import os +from polywrap_test_cases import get_path_to_test_wrappers +import pytest + + +@pytest.mark.parametrize( + "wrapper", ["asyncify", "bigint-type", "enum-type", "map-type"] +) +@pytest.mark.parametrize("language", ["as", "rs"]) +def test_wrappers_exist(wrapper: str, language: str): + assert os.path.exists(get_path_to_test_wrappers()) + wrapper_path = os.path.join(get_path_to_test_wrappers(), wrapper, "implementations", language) + assert os.path.exists(wrapper_path) + assert os.path.isdir(wrapper_path) + assert os.path.exists(os.path.join(wrapper_path, "wrap.info")) + assert os.path.exists(os.path.join(wrapper_path, "wrap.wasm")) diff --git a/packages/polywrap-test-cases/tox.ini b/packages/polywrap-test-cases/tox.ini new file mode 100644 index 00000000..bc546a3c --- /dev/null +++ b/packages/polywrap-test-cases/tox.ini @@ -0,0 +1,34 @@ +[tox] +isolated_build = True +envlist = py310 + +[testenv] +commands = + python -m polywrap_test_cases + pytest tests/ + +[testenv:getwraps] +commands = + python -m polywrap_test_cases + +[testenv:lint] +commands = + isort --check-only polywrap_test_cases + black --check polywrap_test_cases + pycln --check polywrap_test_cases --disable-all-dunder-policy + pylint polywrap_test_cases + pydocstyle polywrap_test_cases + +[testenv:typecheck] +commands = + pyright polywrap_test_cases + +[testenv:secure] +commands = + bandit -r polywrap_test_cases -c pyproject.toml + +[testenv:dev] +commands = + isort polywrap_test_cases + black polywrap_test_cases + pycln polywrap_test_cases --disable-all-dunder-policy diff --git a/packages/polywrap-uri-resolvers/assets/style.css b/packages/polywrap-uri-resolvers/assets/style.css new file mode 100644 index 00000000..3edac88e --- /dev/null +++ b/packages/polywrap-uri-resolvers/assets/style.css @@ -0,0 +1,186 @@ +body { + font-family: Helvetica, Arial, sans-serif; + font-size: 12px; + /* do not increase min-width as some may use split screens */ + min-width: 800px; + color: #999; +} + +h1 { + font-size: 24px; + color: black; +} + +h2 { + font-size: 16px; + color: black; +} + +p { + color: black; +} + +a { + color: #999; +} + +table { + border-collapse: collapse; +} + +/****************************** + * SUMMARY INFORMATION + ******************************/ +#environment td { + padding: 5px; + border: 1px solid #E6E6E6; +} +#environment tr:nth-child(odd) { + background-color: #f6f6f6; +} + +/****************************** + * TEST RESULT COLORS + ******************************/ +span.passed, +.passed .col-result { + color: green; +} + +span.skipped, +span.xfailed, +span.rerun, +.skipped .col-result, +.xfailed .col-result, +.rerun .col-result { + color: orange; +} + +span.error, +span.failed, +span.xpassed, +.error .col-result, +.failed .col-result, +.xpassed .col-result { + color: red; +} + +/****************************** + * RESULTS TABLE + * + * 1. Table Layout + * 2. Extra + * 3. Sorting items + * + ******************************/ +/*------------------ + * 1. Table Layout + *------------------*/ +#results-table { + border: 1px solid #e6e6e6; + color: #999; + font-size: 12px; + width: 100%; +} +#results-table th, +#results-table td { + padding: 5px; + border: 1px solid #E6E6E6; + text-align: left; +} +#results-table th { + font-weight: bold; +} + +/*------------------ + * 2. Extra + *------------------*/ +.log { + background-color: #e6e6e6; + border: 1px solid #e6e6e6; + color: black; + display: block; + font-family: "Courier New", Courier, monospace; + height: 230px; + overflow-y: scroll; + padding: 5px; + white-space: pre-wrap; +} +.log:only-child { + height: inherit; +} + +div.image { + border: 1px solid #e6e6e6; + float: right; + height: 240px; + margin-left: 5px; + overflow: hidden; + width: 320px; +} +div.image img { + width: 320px; +} + +div.video { + border: 1px solid #e6e6e6; + float: right; + height: 240px; + margin-left: 5px; + overflow: hidden; + width: 320px; +} +div.video video { + overflow: hidden; + width: 320px; + height: 240px; +} + +.collapsed { + display: none; +} + +.expander::after { + content: " (show details)"; + color: #BBB; + font-style: italic; + cursor: pointer; +} + +.collapser::after { + content: " (hide details)"; + color: #BBB; + font-style: italic; + cursor: pointer; +} + +/*------------------ + * 3. Sorting items + *------------------*/ +.sortable { + cursor: pointer; +} + +.sort-icon { + font-size: 0px; + float: left; + margin-right: 5px; + margin-top: 5px; + /*triangle*/ + width: 0; + height: 0; + border-left: 8px solid transparent; + border-right: 8px solid transparent; +} +.inactive .sort-icon { + /*finish triangle*/ + border-top: 8px solid #E6E6E6; +} +.asc.active .sort-icon { + /*finish triangle*/ + border-bottom: 8px solid #999; +} +.desc.active .sort-icon { + /*finish triangle*/ + border-top: 8px solid #999; +} diff --git a/packages/polywrap-uri-resolvers/poetry.lock b/packages/polywrap-uri-resolvers/poetry.lock index 1d490585..9b354d05 100644 --- a/packages/polywrap-uri-resolvers/poetry.lock +++ b/packages/polywrap-uri-resolvers/poetry.lock @@ -1,15 +1,15 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry and should not be changed by hand. [[package]] name = "astroid" -version = "2.15.4" +version = "2.15.5" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false python-versions = ">=3.7.2" files = [ - {file = "astroid-2.15.4-py3-none-any.whl", hash = "sha256:a1b8543ef9d36ea777194bc9b17f5f8678d2c56ee6a45b2c2f17eec96f242347"}, - {file = "astroid-2.15.4.tar.gz", hash = "sha256:c81e1c7fbac615037744d067a9bb5f9aeb655edf59b63ee8b59585475d6f80d8"}, + {file = "astroid-2.15.5-py3-none-any.whl", hash = "sha256:078e5212f9885fa85fbb0cf0101978a336190aadea6e13305409d099f71b2324"}, + {file = "astroid-2.15.5.tar.gz", hash = "sha256:1039262575027b441137ab4a62a793a9b43defb42c32d5670f38686207cd780f"}, ] [package.dependencies] @@ -273,42 +273,41 @@ files = [ [[package]] name = "libcst" -version = "0.4.9" +version = "0.4.10" description = "A concrete syntax tree with AST-like properties for Python 3.5, 3.6, 3.7, 3.8, 3.9, and 3.10 programs." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "libcst-0.4.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4f9e42085c403e22201e5c41e707ef73e4ea910ad9fc67983ceee2368097f54e"}, - {file = "libcst-0.4.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1266530bf840cc40633a04feb578bb4cac1aa3aea058cc3729e24eab09a8e996"}, - {file = "libcst-0.4.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9679177391ccb9b0cdde3185c22bf366cb672457c4b7f4031fcb3b5e739fbd6"}, - {file = "libcst-0.4.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d67bc87e0d8db9434f2ea063734938a320f541f4c6da1074001e372f840f385d"}, - {file = "libcst-0.4.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e316da5a126f2a9e1d7680f95f907b575f082a35e2f8bd5620c59b2aaaebfe0a"}, - {file = "libcst-0.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:7415569ab998a85b0fc9af3a204611ea7fadb2d719a12532c448f8fc98f5aca4"}, - {file = "libcst-0.4.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:15ded11ff7f4572f91635e02b519ae959f782689fdb4445bbebb7a3cc5c71d75"}, - {file = "libcst-0.4.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b266867b712a120fad93983de432ddb2ccb062eb5fd2bea748c9a94cb200c36"}, - {file = "libcst-0.4.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:045b3b0b06413cdae6e9751b5f417f789ffa410f2cb2815e3e0e0ea6bef10ec0"}, - {file = "libcst-0.4.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e799add8fba4976628b9c1a6768d73178bf898f0ed1bd1322930c2d3db9063ba"}, - {file = "libcst-0.4.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10479371d04ee8dc978c889c1774bbf6a83df88fa055fcb0159a606f6679c565"}, - {file = "libcst-0.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:7a98286cbbfa90a42d376900c875161ad02a5a2a6b7c94c0f7afd9075e329ce4"}, - {file = "libcst-0.4.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:400166fc4efb9aa06ce44498d443aa78519082695b1894202dd73cd507d2d712"}, - {file = "libcst-0.4.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46123863fba35cc84f7b54dd68826419cabfd9504d8a101c7fe3313ea03776f9"}, - {file = "libcst-0.4.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27be8db54c0e5fe440021a771a38b81a7dbc23cd630eb8b0e9828b7717f9b702"}, - {file = "libcst-0.4.9-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:132bec627b064bd567e7e4cd6c89524d02842151eb0d8f5f3f7ffd2579ec1b09"}, - {file = "libcst-0.4.9-cp37-cp37m-win_amd64.whl", hash = "sha256:596860090aeed3ee6ad1e59c35c6c4110a57e4e896abf51b91cae003ec720a11"}, - {file = "libcst-0.4.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f4487608258109f774300466d4ca97353df29ae6ac23d1502e13e5509423c9d5"}, - {file = "libcst-0.4.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aa53993e9a2853efb3ed3605da39f2e7125df6430f613eb67ef886c1ce4f94b5"}, - {file = "libcst-0.4.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6ce794483d4c605ef0f5b199a49fb6996f9586ca938b7bfef213bd13858d7ab"}, - {file = "libcst-0.4.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:786e562b54bbcd17a060d1244deeef466b7ee07fe544074c252c4a169e38f1ee"}, - {file = "libcst-0.4.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:794250d2359edd518fb698e5d21c38a5bdfc5e4a75d0407b4c19818271ce6742"}, - {file = "libcst-0.4.9-cp38-cp38-win_amd64.whl", hash = "sha256:76491f67431318c3145442e97dddcead7075b074c59eac51be7cc9e3fffec6ee"}, - {file = "libcst-0.4.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3cf48d7aec6dc54b02aec0b1bb413c5bb3b02d852fd6facf1f05c7213e61a176"}, - {file = "libcst-0.4.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b3348c6b7711a5235b133bd8e11d22e903c388db42485b8ceb5f2aa0fae9b9f"}, - {file = "libcst-0.4.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e33b66762efaa014c38819efae5d8f726dd823e32d5d691035484411d2a2a69"}, - {file = "libcst-0.4.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1350d375d3fb9b20a6cf10c09b2964baca9be753a033dde7c1aced49d8e58387"}, - {file = "libcst-0.4.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3822056dc13326082362db35b3f649e0f4a97e36ddb4e487441da8e0fb9db7b3"}, - {file = "libcst-0.4.9-cp39-cp39-win_amd64.whl", hash = "sha256:183636141b839aa35b639e100883813744523bc7c12528906621121731b28443"}, - {file = "libcst-0.4.9.tar.gz", hash = "sha256:01786c403348f76f274dbaf3888ae237ffb73e6ed6973e65eba5c1fc389861dd"}, + {file = "libcst-0.4.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8fa0ec646ed7bce984d0ee9dbf514af278050bdb16a4fb986e916ace534eebc6"}, + {file = "libcst-0.4.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3cb3b7821eac00713844cda079583230c546a589b22ed5f03f2ddc4f985c384b"}, + {file = "libcst-0.4.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7acfa747112ae40b032739661abd7c81aff37191294f7c2dab8bbd72372e78f"}, + {file = "libcst-0.4.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1312e293b864ef3cb4b09534ed5f104c2dc45b680233c68bf76237295041c781"}, + {file = "libcst-0.4.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76884b1afe475e8e68e704bf26eb9f9a2867029643e58f2f26a0286e3b6e998e"}, + {file = "libcst-0.4.10-cp310-cp310-win_amd64.whl", hash = "sha256:1069b808a711db5cd47538f27eb2c73206317aa0d8b5a3500b23aab24f86eb2e"}, + {file = "libcst-0.4.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:50be085346a35812535c7f876319689e15a7bfd1bd8efae8fd70589281d944b6"}, + {file = "libcst-0.4.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bb9f10e5763e361e8bd8ff765fc0f1bcf744f242ff8b6d3e50ffec4dda3972ac"}, + {file = "libcst-0.4.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfeeabb528b5df7b4be1817b584ce79e9a1a66687bd72f6de9c22272462812f1"}, + {file = "libcst-0.4.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5648aeae8c90a2abab1f7b1bf205769a0179ed2cfe1ea7f681f6885e87b8b193"}, + {file = "libcst-0.4.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a144f20aff4643b00374facf8409d30c7935db8176e5b2a07e1fd44004db2c1f"}, + {file = "libcst-0.4.10-cp311-cp311-win_amd64.whl", hash = "sha256:a10adc2e8ea2dda2b70eabec631ead2fc4a7a7ab633d6c2b690823c698b8431a"}, + {file = "libcst-0.4.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58fe90458a26a55358207f74abf8a05dff51d662069f070b4bd308a000a80c09"}, + {file = "libcst-0.4.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:999fbbe467f61cbce9e6e054f86cd1c5ffa3740fd3dc8ebdd600db379f699256"}, + {file = "libcst-0.4.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83ee7e7be4efac4c140a97d772e1f6b3553f98fa5f46ad78df5dfe51e5a4aa4d"}, + {file = "libcst-0.4.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:158478e8f45578fb26621b3dc0fe275f9e004297e9afdcf08936ecda05681174"}, + {file = "libcst-0.4.10-cp37-cp37m-win_amd64.whl", hash = "sha256:5ed101fee1af7abea3684fcff7fab5b170ceea4040756f54c15c870539daec66"}, + {file = "libcst-0.4.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:349f2b4ee4b982fe254c65c78d941fc96299f3c422b79f95ef8c7bba2b7f0f90"}, + {file = "libcst-0.4.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7cfa4d4beb84d0d63247aca27f1a15c63984512274c5b23040f8b4ba511036d7"}, + {file = "libcst-0.4.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24582506da24e31f2644f862f11413a6b80fbad68d15194bfcc3f7dfebf2ec5e"}, + {file = "libcst-0.4.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cdf2d0157438d3d52d310b0b6be31ff99bed19de489b2ebd3e2a4cd9946da45"}, + {file = "libcst-0.4.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a677103d2f1ab0e50bc3a7cc6c96c7d64bcbac826d785e4cbf5ee9aaa9fcfa25"}, + {file = "libcst-0.4.10-cp38-cp38-win_amd64.whl", hash = "sha256:a8fdfd4a7d301adb785aa4b98e4a7cca45c5ff8cfb460b485d081efcfaaeeab7"}, + {file = "libcst-0.4.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b1569d87536bed4e9c11dd5c94a137dc0bce2a2b05961489c6016bf4521bb7cf"}, + {file = "libcst-0.4.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:72dff8783ac79cd10f2bd2fde0b28f262e9a22718ae26990948ba6131b85ca8b"}, + {file = "libcst-0.4.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76adc53660ef094ff83f77a2550a7e00d1cab8e5e63336e071c17c09b5a89fe2"}, + {file = "libcst-0.4.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3e9d9fdd9a9b9b8991936ff1c07527ce7ef396c8233280ba9a7137e72c2e48e"}, + {file = "libcst-0.4.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e1b4cbaf7b1cdad5fa3eababe42d5b46c0d52afe13c5ba4eac2495fc57630ea"}, + {file = "libcst-0.4.10-cp39-cp39-win_amd64.whl", hash = "sha256:bcbd07cec3d7a7be6f0299b0c246e085e3d6cc8af367e2c96059183b97c2e2fe"}, ] [package.dependencies] @@ -317,7 +316,7 @@ typing-extensions = ">=3.7.4.2" typing-inspect = ">=0.4.0" [package.extras] -dev = ["Sphinx (>=5.1.1)", "black (==22.10.0)", "coverage (>=4.5.4)", "fixit (==0.1.1)", "flake8 (>=3.7.8,<5)", "hypothesis (>=4.36.0)", "hypothesmith (>=0.0.4)", "jinja2 (==3.1.2)", "jupyter (>=1.0.0)", "maturin (>=0.8.3,<0.14)", "nbsphinx (>=0.4.2)", "prompt-toolkit (>=2.0.9)", "pyre-check (==0.9.9)", "setuptools-rust (>=1.5.2)", "setuptools-scm (>=6.0.1)", "slotscheck (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "ufmt (==2.0.1)", "usort (==1.0.5)"] +dev = ["Sphinx (>=5.1.1)", "black (==23.1.0)", "build (>=0.10.0)", "coverage (>=4.5.4)", "fixit (==0.1.1)", "flake8 (>=3.7.8,<5)", "hypothesis (>=4.36.0)", "hypothesmith (>=0.0.4)", "jinja2 (==3.1.2)", "jupyter (>=1.0.0)", "maturin (>=0.8.3,<0.14)", "nbsphinx (>=0.4.2)", "prompt-toolkit (>=2.0.9)", "pyre-check (==0.9.10)", "setuptools-rust (>=1.5.2)", "setuptools-scm (>=6.0.1)", "slotscheck (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "ufmt (==2.1.0)", "usort (==1.0.6)"] [[package]] name = "markdown-it-py" @@ -455,14 +454,14 @@ files = [ [[package]] name = "nodeenv" -version = "1.7.0" +version = "1.8.0" description = "Node.js virtual environment builder" category = "dev" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" files = [ - {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, - {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, ] [package.dependencies] @@ -506,18 +505,18 @@ files = [ [[package]] name = "platformdirs" -version = "3.5.0" +version = "3.5.1" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.5.0-py3-none-any.whl", hash = "sha256:47692bc24c1958e8b0f13dd727307cff1db103fca36399f457da8e05f222fdc4"}, - {file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"}, + {file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"}, + {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"}, ] [package.extras] -docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] @@ -536,6 +535,25 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "polywrap-client" +version = "0.1.0a29" +description = "" +category = "dev" +optional = false +python-versions = "^3.10" +files = [] +develop = true + +[package.dependencies] +polywrap-core = {path = "../polywrap-core", develop = true} +polywrap-manifest = {path = "../polywrap-manifest", develop = true} +polywrap-msgpack = {path = "../polywrap-msgpack", develop = true} + +[package.source] +type = "directory" +url = "../polywrap-client" + [[package]] name = "polywrap-core" version = "0.1.0a29" @@ -589,6 +607,39 @@ msgpack = "^1.0.4" type = "directory" url = "../polywrap-msgpack" +[[package]] +name = "polywrap-plugin" +version = "0.1.0a29" +description = "Plugin package" +category = "dev" +optional = false +python-versions = "^3.10" +files = [] +develop = true + +[package.dependencies] +polywrap-core = {path = "../polywrap-core", develop = true} +polywrap-manifest = {path = "../polywrap-manifest", develop = true} +polywrap-msgpack = {path = "../polywrap-msgpack", develop = true} + +[package.source] +type = "directory" +url = "../polywrap-plugin" + +[[package]] +name = "polywrap-test-cases" +version = "0.1.0a29" +description = "Plugin package" +category = "dev" +optional = false +python-versions = "^3.10" +files = [] +develop = true + +[package.source] +type = "directory" +url = "../polywrap-test-cases" + [[package]] name = "polywrap-wasm" version = "0.1.0a29" @@ -644,48 +695,48 @@ typer = ">=0.4.1,<0.8.0" [[package]] name = "pydantic" -version = "1.10.7" +version = "1.10.8" description = "Data validation and settings management using python type hints" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e79e999e539872e903767c417c897e729e015872040e56b96e67968c3b918b2d"}, - {file = "pydantic-1.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:01aea3a42c13f2602b7ecbbea484a98169fb568ebd9e247593ea05f01b884b2e"}, - {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:516f1ed9bc2406a0467dd777afc636c7091d71f214d5e413d64fef45174cfc7a"}, - {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae150a63564929c675d7f2303008d88426a0add46efd76c3fc797cd71cb1b46f"}, - {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ecbbc51391248116c0a055899e6c3e7ffbb11fb5e2a4cd6f2d0b93272118a209"}, - {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f4a2b50e2b03d5776e7f21af73e2070e1b5c0d0df255a827e7c632962f8315af"}, - {file = "pydantic-1.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:a7cd2251439988b413cb0a985c4ed82b6c6aac382dbaff53ae03c4b23a70e80a"}, - {file = "pydantic-1.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:68792151e174a4aa9e9fc1b4e653e65a354a2fa0fed169f7b3d09902ad2cb6f1"}, - {file = "pydantic-1.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe2507b8ef209da71b6fb5f4e597b50c5a34b78d7e857c4f8f3115effaef5fe"}, - {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10a86d8c8db68086f1e30a530f7d5f83eb0685e632e411dbbcf2d5c0150e8dcd"}, - {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75ae19d2a3dbb146b6f324031c24f8a3f52ff5d6a9f22f0683694b3afcb16fb"}, - {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:464855a7ff7f2cc2cf537ecc421291b9132aa9c79aef44e917ad711b4a93163b"}, - {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:193924c563fae6ddcb71d3f06fa153866423ac1b793a47936656e806b64e24ca"}, - {file = "pydantic-1.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:b4a849d10f211389502059c33332e91327bc154acc1845f375a99eca3afa802d"}, - {file = "pydantic-1.10.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cc1dde4e50a5fc1336ee0581c1612215bc64ed6d28d2c7c6f25d2fe3e7c3e918"}, - {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0cfe895a504c060e5d36b287ee696e2fdad02d89e0d895f83037245218a87fe"}, - {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:670bb4683ad1e48b0ecb06f0cfe2178dcf74ff27921cdf1606e527d2617a81ee"}, - {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:950ce33857841f9a337ce07ddf46bc84e1c4946d2a3bba18f8280297157a3fd1"}, - {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c15582f9055fbc1bfe50266a19771bbbef33dd28c45e78afbe1996fd70966c2a"}, - {file = "pydantic-1.10.7-cp37-cp37m-win_amd64.whl", hash = "sha256:82dffb306dd20bd5268fd6379bc4bfe75242a9c2b79fec58e1041fbbdb1f7914"}, - {file = "pydantic-1.10.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c7f51861d73e8b9ddcb9916ae7ac39fb52761d9ea0df41128e81e2ba42886cd"}, - {file = "pydantic-1.10.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6434b49c0b03a51021ade5c4daa7d70c98f7a79e95b551201fff682fc1661245"}, - {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d34ab766fa056df49013bb6e79921a0265204c071984e75a09cbceacbbdd5d"}, - {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:701daea9ffe9d26f97b52f1d157e0d4121644f0fcf80b443248434958fd03dc3"}, - {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf135c46099ff3f919d2150a948ce94b9ce545598ef2c6c7bf55dca98a304b52"}, - {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0f85904f73161817b80781cc150f8b906d521fa11e3cdabae19a581c3606209"}, - {file = "pydantic-1.10.7-cp38-cp38-win_amd64.whl", hash = "sha256:9f6f0fd68d73257ad6685419478c5aece46432f4bdd8d32c7345f1986496171e"}, - {file = "pydantic-1.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c230c0d8a322276d6e7b88c3f7ce885f9ed16e0910354510e0bae84d54991143"}, - {file = "pydantic-1.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:976cae77ba6a49d80f461fd8bba183ff7ba79f44aa5cfa82f1346b5626542f8e"}, - {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d45fc99d64af9aaf7e308054a0067fdcd87ffe974f2442312372dfa66e1001d"}, - {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2a5ebb48958754d386195fe9e9c5106f11275867051bf017a8059410e9abf1f"}, - {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:abfb7d4a7cd5cc4e1d1887c43503a7c5dd608eadf8bc615413fc498d3e4645cd"}, - {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80b1fab4deb08a8292d15e43a6edccdffa5377a36a4597bb545b93e79c5ff0a5"}, - {file = "pydantic-1.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:d71e69699498b020ea198468e2480a2f1e7433e32a3a99760058c6520e2bea7e"}, - {file = "pydantic-1.10.7-py3-none-any.whl", hash = "sha256:0cd181f1d0b1d00e2b705f1bf1ac7799a2d938cce3376b8007df62b29be3c2c6"}, - {file = "pydantic-1.10.7.tar.gz", hash = "sha256:cfc83c0678b6ba51b0532bea66860617c4cd4251ecf76e9846fa5a9f3454e97e"}, + {file = "pydantic-1.10.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1243d28e9b05003a89d72e7915fdb26ffd1d39bdd39b00b7dbe4afae4b557f9d"}, + {file = "pydantic-1.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0ab53b609c11dfc0c060d94335993cc2b95b2150e25583bec37a49b2d6c6c3f"}, + {file = "pydantic-1.10.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9613fadad06b4f3bc5db2653ce2f22e0de84a7c6c293909b48f6ed37b83c61f"}, + {file = "pydantic-1.10.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df7800cb1984d8f6e249351139667a8c50a379009271ee6236138a22a0c0f319"}, + {file = "pydantic-1.10.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0c6fafa0965b539d7aab0a673a046466d23b86e4b0e8019d25fd53f4df62c277"}, + {file = "pydantic-1.10.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e82d4566fcd527eae8b244fa952d99f2ca3172b7e97add0b43e2d97ee77f81ab"}, + {file = "pydantic-1.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:ab523c31e22943713d80d8d342d23b6f6ac4b792a1e54064a8d0cf78fd64e800"}, + {file = "pydantic-1.10.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:666bdf6066bf6dbc107b30d034615d2627e2121506c555f73f90b54a463d1f33"}, + {file = "pydantic-1.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:35db5301b82e8661fa9c505c800d0990bc14e9f36f98932bb1d248c0ac5cada5"}, + {file = "pydantic-1.10.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90c1e29f447557e9e26afb1c4dbf8768a10cc676e3781b6a577841ade126b85"}, + {file = "pydantic-1.10.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93e766b4a8226e0708ef243e843105bf124e21331694367f95f4e3b4a92bbb3f"}, + {file = "pydantic-1.10.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:88f195f582851e8db960b4a94c3e3ad25692c1c1539e2552f3df7a9e972ef60e"}, + {file = "pydantic-1.10.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:34d327c81e68a1ecb52fe9c8d50c8a9b3e90d3c8ad991bfc8f953fb477d42fb4"}, + {file = "pydantic-1.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:d532bf00f381bd6bc62cabc7d1372096b75a33bc197a312b03f5838b4fb84edd"}, + {file = "pydantic-1.10.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7d5b8641c24886d764a74ec541d2fc2c7fb19f6da2a4001e6d580ba4a38f7878"}, + {file = "pydantic-1.10.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b1f6cb446470b7ddf86c2e57cd119a24959af2b01e552f60705910663af09a4"}, + {file = "pydantic-1.10.8-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c33b60054b2136aef8cf190cd4c52a3daa20b2263917c49adad20eaf381e823b"}, + {file = "pydantic-1.10.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1952526ba40b220b912cdc43c1c32bcf4a58e3f192fa313ee665916b26befb68"}, + {file = "pydantic-1.10.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bb14388ec45a7a0dc429e87def6396f9e73c8c77818c927b6a60706603d5f2ea"}, + {file = "pydantic-1.10.8-cp37-cp37m-win_amd64.whl", hash = "sha256:16f8c3e33af1e9bb16c7a91fc7d5fa9fe27298e9f299cff6cb744d89d573d62c"}, + {file = "pydantic-1.10.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ced8375969673929809d7f36ad322934c35de4af3b5e5b09ec967c21f9f7887"}, + {file = "pydantic-1.10.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:93e6bcfccbd831894a6a434b0aeb1947f9e70b7468f274154d03d71fabb1d7c6"}, + {file = "pydantic-1.10.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:191ba419b605f897ede9892f6c56fb182f40a15d309ef0142212200a10af4c18"}, + {file = "pydantic-1.10.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:052d8654cb65174d6f9490cc9b9a200083a82cf5c3c5d3985db765757eb3b375"}, + {file = "pydantic-1.10.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ceb6a23bf1ba4b837d0cfe378329ad3f351b5897c8d4914ce95b85fba96da5a1"}, + {file = "pydantic-1.10.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f2e754d5566f050954727c77f094e01793bcb5725b663bf628fa6743a5a9108"}, + {file = "pydantic-1.10.8-cp38-cp38-win_amd64.whl", hash = "sha256:6a82d6cda82258efca32b40040228ecf43a548671cb174a1e81477195ed3ed56"}, + {file = "pydantic-1.10.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e59417ba8a17265e632af99cc5f35ec309de5980c440c255ab1ca3ae96a3e0e"}, + {file = "pydantic-1.10.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:84d80219c3f8d4cad44575e18404099c76851bc924ce5ab1c4c8bb5e2a2227d0"}, + {file = "pydantic-1.10.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e4148e635994d57d834be1182a44bdb07dd867fa3c2d1b37002000646cc5459"}, + {file = "pydantic-1.10.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12f7b0bf8553e310e530e9f3a2f5734c68699f42218bf3568ef49cd9b0e44df4"}, + {file = "pydantic-1.10.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42aa0c4b5c3025483240a25b09f3c09a189481ddda2ea3a831a9d25f444e03c1"}, + {file = "pydantic-1.10.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17aef11cc1b997f9d574b91909fed40761e13fac438d72b81f902226a69dac01"}, + {file = "pydantic-1.10.8-cp39-cp39-win_amd64.whl", hash = "sha256:66a703d1983c675a6e0fed8953b0971c44dba48a929a2000a493c3772eb61a5a"}, + {file = "pydantic-1.10.8-py3-none-any.whl", hash = "sha256:7456eb22ed9aaa24ff3e7b4757da20d9e5ce2a81018c1b3ebd81a0b88a18f3b2"}, + {file = "pydantic-1.10.8.tar.gz", hash = "sha256:1410275520dfa70effadf4c21811d755e7ef9bb1f1d077a21958153a92c8d9ca"}, ] [package.dependencies] @@ -759,14 +810,14 @@ testutils = ["gitpython (>3)"] [[package]] name = "pyright" -version = "1.1.306" +version = "1.1.311" description = "Command line wrapper for pyright" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pyright-1.1.306-py3-none-any.whl", hash = "sha256:008eb2a29584ae274a154d749cf81476a3073fb562a462eac8d43a753378b9db"}, - {file = "pyright-1.1.306.tar.gz", hash = "sha256:16d5d198be64de497d5f9002000a271176c381e21b977ca5566cf779b643c9ed"}, + {file = "pyright-1.1.311-py3-none-any.whl", hash = "sha256:04df30c6b31d05068effe5563411291c876f5e4221d0af225a267b61dce1ca85"}, + {file = "pyright-1.1.311.tar.gz", hash = "sha256:554b555d3f770e8da2e76d6bb94e2ac63b3edc7dcd5fb8de202f9dd53e36689a"}, ] [package.dependencies] @@ -817,6 +868,41 @@ pytest = ">=6.1.0" [package.extras] testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] +[[package]] +name = "pytest-html" +version = "3.2.0" +description = "pytest plugin for generating HTML reports" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pytest-html-3.2.0.tar.gz", hash = "sha256:c4e2f4bb0bffc437f51ad2174a8a3e71df81bbc2f6894604e604af18fbe687c3"}, + {file = "pytest_html-3.2.0-py3-none-any.whl", hash = "sha256:868c08564a68d8b2c26866f1e33178419bb35b1e127c33784a28622eb827f3f3"}, +] + +[package.dependencies] +py = ">=1.8.2" +pytest = ">=5.0,<6.0.0 || >6.0.0" +pytest-metadata = "*" + +[[package]] +name = "pytest-metadata" +version = "3.0.0" +description = "pytest plugin for test session metadata" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest_metadata-3.0.0-py3-none-any.whl", hash = "sha256:a17b1e40080401dc23177599208c52228df463db191c1a573ccdffacd885e190"}, + {file = "pytest_metadata-3.0.0.tar.gz", hash = "sha256:769a9c65d2884bd583bc626b0ace77ad15dbe02dd91a9106d47fd46d9c2569ca"}, +] + +[package.dependencies] +pytest = ">=7.0.0" + +[package.extras] +test = ["black (>=22.1.0)", "flake8 (>=4.0.1)", "pre-commit (>=2.17.0)", "tox (>=3.24.5)"] + [[package]] name = "pyyaml" version = "6.0" @@ -888,19 +974,19 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "setuptools" -version = "67.7.2" +version = "67.8.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "setuptools-67.7.2-py3-none-any.whl", hash = "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b"}, - {file = "setuptools-67.7.2.tar.gz", hash = "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"}, + {file = "setuptools-67.8.0-py3-none-any.whl", hash = "sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f"}, + {file = "setuptools-67.8.0.tar.gz", hash = "sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] @@ -941,14 +1027,14 @@ files = [ [[package]] name = "stevedore" -version = "5.0.0" +version = "5.1.0" description = "Manage dynamic plugins for Python applications" category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "stevedore-5.0.0-py3-none-any.whl", hash = "sha256:bd5a71ff5e5e5f5ea983880e4a1dd1bb47f8feebbb3d95b592398e2f02194771"}, - {file = "stevedore-5.0.0.tar.gz", hash = "sha256:2c428d2338976279e8eb2196f7a94910960d9f7ba2f41f3988511e95ca447021"}, + {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"}, + {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"}, ] [package.dependencies] @@ -1059,26 +1145,26 @@ test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6. [[package]] name = "typing-extensions" -version = "4.5.0" +version = "4.6.2" description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, - {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, + {file = "typing_extensions-4.6.2-py3-none-any.whl", hash = "sha256:3a8b36f13dd5fdc5d1b16fe317f5668545de77fa0b8e02006381fd49d731ab98"}, + {file = "typing_extensions-4.6.2.tar.gz", hash = "sha256:06006244c70ac8ee83fa8282cb188f697b8db25bc8b4df07be1873c43897060c"}, ] [[package]] name = "typing-inspect" -version = "0.8.0" +version = "0.9.0" description = "Runtime inspection utilities for typing module." category = "dev" optional = false python-versions = "*" files = [ - {file = "typing_inspect-0.8.0-py3-none-any.whl", hash = "sha256:5fbf9c1e65d4fa01e701fe12a5bca6c6e08a4ffd5bc60bfac028253a447c5188"}, - {file = "typing_inspect-0.8.0.tar.gz", hash = "sha256:8b1ff0c400943b6145df8119c41c244ca8207f1f10c9c057aeed1560e4806e3d"}, + {file = "typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f"}, + {file = "typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78"}, ] [package.dependencies] @@ -1236,4 +1322,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "94ae3e22f4506227dc928324abc370121de92d93372dc588a0005fdaaeaf2dff" +content-hash = "79ae9ce53c2dd5d8fbaf60d88c5e2b7fe5f119f5ada10ff0ebd2515b76fe9d7c" diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/__init__.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/__init__.py index 0d1e90f6..79616fc5 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/__init__.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/__init__.py @@ -2,4 +2,3 @@ from .errors import * from .resolvers import * from .types import * -from .utils import * diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/errors.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/errors.py index b55063b7..ed4e1b0d 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/errors.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/errors.py @@ -1,13 +1,8 @@ """This module contains all the errors related to URI resolution.""" import json -from dataclasses import asdict -from typing import List, TypeVar +from typing import List -from polywrap_core import IUriResolutionStep, Uri, UriLike - -from .utils import get_uri_resolution_path - -TUriLike = TypeVar("TUriLike", bound=UriLike) +from polywrap_core import Uri, UriResolutionStep, build_clean_uri_history class UriResolutionError(Exception): @@ -17,17 +12,21 @@ class UriResolutionError(Exception): class InfiniteLoopError(UriResolutionError): """Raised when an infinite loop is detected while resolving a URI.""" - def __init__(self, uri: Uri, history: List[IUriResolutionStep[TUriLike]]): + uri: Uri + history: List[UriResolutionStep] + + def __init__(self, uri: Uri, history: List[UriResolutionStep]): """Initialize a new InfiniteLoopError instance. Args: uri (Uri): The URI that caused the infinite loop. - history (List[IUriResolutionStep[TUriLike]]): The resolution history. + history (List[UriResolutionStep]): The resolution history. """ - resolution_path = get_uri_resolution_path(history) + self.uri = uri + self.history = history super().__init__( f"An infinite loop was detected while resolving the URI: {uri.uri}\n" - f"History: {json.dumps([asdict(step) for step in resolution_path], indent=2)}" + f"History: {json.dumps(build_clean_uri_history(history), indent=2)}" ) @@ -38,14 +37,19 @@ class UriResolverExtensionError(UriResolutionError): class UriResolverExtensionNotFoundError(UriResolverExtensionError): """Raised when an extension resolver wrapper could not be found for a URI.""" - def __init__(self, uri: Uri, history: List[IUriResolutionStep[TUriLike]]): + uri: Uri + history: List[UriResolutionStep] + + def __init__(self, uri: Uri, history: List[UriResolutionStep]): """Initialize a new UriResolverExtensionNotFoundError instance. Args: uri (Uri): The URI that caused the error. - history (List[IUriResolutionStep[TUriLike]]): The resolution history. + history (List[UriResolutionStep]): The resolution history. """ + self.uri = uri + self.history = history super().__init__( f"Could not find an extension resolver wrapper for the URI: {uri.uri}\n" - f"History: {json.dumps([asdict(step) for step in history], indent=2)}" + f"History: {json.dumps(build_clean_uri_history(history), indent=2)}" ) diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/abc/resolver_with_history.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/abc/resolver_with_history.py index f88ddc86..5755cf50 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/abc/resolver_with_history.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/abc/resolver_with_history.py @@ -3,14 +3,13 @@ from polywrap_core import ( InvokerClient, - IUriResolutionContext, Uri, UriPackageOrWrapper, + UriResolutionContext, + UriResolutionStep, UriResolver, ) -from ...types import UriResolutionStep - class ResolverWithHistory(UriResolver): """Defines an abstract resolver that tracks its steps in\ @@ -20,11 +19,11 @@ class ResolverWithHistory(UriResolver): their steps in the resolution context. """ - async def try_resolve_uri( + def try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> UriPackageOrWrapper: """Try to resolve a URI to a wrap package, a wrapper, or a URI and \ update the resolution context with the result. @@ -35,15 +34,15 @@ async def try_resolve_uri( Args: uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use for\ + client (InvokerClient): The client to use for\ resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]):\ + resolution_context (IUriResolutionContext):\ The resolution context to update. Returns: UriPackageOrWrapper: The resolved URI package, wrapper, or URI. """ - result = await self._try_resolve_uri(uri, client, resolution_context) + result = self._try_resolve_uri(uri, client, resolution_context) step = UriResolutionStep( source_uri=uri, result=result, description=self.get_step_description() ) @@ -56,17 +55,17 @@ def get_step_description(self) -> str: """Get a description of the resolution step.""" @abstractmethod - async def _try_resolve_uri( + def _try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> UriPackageOrWrapper: """Resolve a URI to a wrap package, a wrapper, or a URI using an internal function. Args: uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use for\ + client (InvokerClient): The client to use for\ resolving the URI. resolution_context (IUriResolutionContext[UriPackageOrWrapper]):\ The resolution context to update. diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/aggregator/uri_resolver_aggregator.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/aggregator/uri_resolver_aggregator.py index a49e9c49..4d6ecc3b 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/aggregator/uri_resolver_aggregator.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/aggregator/uri_resolver_aggregator.py @@ -1,20 +1,12 @@ """This module contains the UriResolverAggregator Resolver.""" -from typing import List, Optional, cast +from typing import List, Optional -from polywrap_core import ( - InvokerClient, - IUriResolutionContext, - Uri, - UriPackage, - UriPackageOrWrapper, - UriResolver, - UriWrapper, -) +from polywrap_core import InvokerClient, UriResolutionContext, UriResolver -from ...types import UriResolutionStep +from .uri_resolver_aggregator_base import UriResolverAggregatorBase -class UriResolverAggregator(UriResolver): +class UriResolverAggregator(UriResolverAggregatorBase): """Defines a resolver that aggregates a list of resolvers. This resolver aggregates a list of resolvers and tries to resolve\ @@ -27,10 +19,10 @@ class UriResolverAggregator(UriResolver): step. Defaults to the class name. """ - __slots__ = ("resolvers", "step_description") + __slots__ = ("_resolvers", "_step_description") - resolvers: List[UriResolver] - step_description: Optional[str] + _resolvers: List[UriResolver] + _step_description: Optional[str] def __init__( self, resolvers: List[UriResolver], step_description: Optional[str] = None @@ -42,51 +34,16 @@ def __init__( step_description (Optional[str]): The description of the resolution\ step. Defaults to the class name. """ - self.step_description = step_description or self.__class__.__name__ - self.resolvers = resolvers - - async def try_resolve_uri( - self, - uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], - ) -> UriPackageOrWrapper: - """Try to resolve a URI to a wrap package, a wrapper, or a URI. - - This method tries to resolve the uri with each of the aggregated\ - resolvers. If a resolver returns a value other than the resolving\ - uri, the value is returned. - - Args: - uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use for\ - resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]):\ - The resolution context to update. - """ - sub_context = resolution_context.create_sub_history_context() - - for resolver in self.resolvers: - uri_package_or_wrapper = await resolver.try_resolve_uri( - uri, client, sub_context - ) - if uri_package_or_wrapper != uri or isinstance( - uri_package_or_wrapper, (UriPackage, UriWrapper) - ): - step = UriResolutionStep( - source_uri=uri, - result=cast(UriPackageOrWrapper, uri_package_or_wrapper), - sub_history=sub_context.get_history(), - description=self.step_description, - ) - resolution_context.track_step(step) - return cast(UriPackageOrWrapper, uri_package_or_wrapper) - - step = UriResolutionStep( - source_uri=uri, - result=uri, - sub_history=sub_context.get_history(), - description=self.step_description, - ) - resolution_context.track_step(step) - return uri + self._step_description = step_description or self.__class__.__name__ + self._resolvers = resolvers + super().__init__() + + def get_step_description(self) -> Optional[str]: + """Get the description of the resolution step.""" + return self._step_description + + def get_resolvers( + self, client: InvokerClient, resolution_context: UriResolutionContext + ) -> List[UriResolver]: + """Get the list of resolvers to aggregate.""" + return self._resolvers diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/aggregator/uri_resolver_aggregator_base.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/aggregator/uri_resolver_aggregator_base.py new file mode 100644 index 00000000..98d47488 --- /dev/null +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/aggregator/uri_resolver_aggregator_base.py @@ -0,0 +1,81 @@ +"""This module contains the UriResolverAggregator Resolver.""" +# pylint: disable=unnecessary-ellipsis +from abc import ABC, abstractmethod +from typing import List, Optional + +from polywrap_core import ( + InvokerClient, + Uri, + UriPackage, + UriPackageOrWrapper, + UriResolutionContext, + UriResolutionStep, + UriResolver, + UriWrapper, +) + + +class UriResolverAggregatorBase(UriResolver, ABC): + """Defines a base resolver that aggregates a list of resolvers. + + This resolver aggregates a list of resolvers and tries to resolve\ + the uri with each of them. If a resolver returns a value\ + other than the resolving uri, the value is returned. + """ + + @abstractmethod + def get_resolvers( + self, client: InvokerClient, resolution_context: UriResolutionContext + ) -> List[UriResolver]: + """Get the list of resolvers to aggregate.""" + ... + + @abstractmethod + def get_step_description(self) -> Optional[str]: + """Get the description of the resolution step. Defaults to the class name.""" + ... + + def try_resolve_uri( + self, + uri: Uri, + client: InvokerClient, + resolution_context: UriResolutionContext, + ) -> UriPackageOrWrapper: + """Try to resolve a URI to a wrap package, a wrapper, or a URI. + + This method tries to resolve the uri with each of the aggregated\ + resolvers. If a resolver returns a value other than the resolving\ + uri, the value is returned. + + Args: + uri (Uri): The URI to resolve. + client (InvokerClient): The client to use for\ + resolving the URI. + resolution_context (UriResolutionContext):\ + The resolution context to update. + """ + sub_context = resolution_context.create_sub_history_context() + + for resolver in self.get_resolvers(client, sub_context): + uri_package_or_wrapper = resolver.try_resolve_uri(uri, client, sub_context) + if ( + isinstance(uri_package_or_wrapper, (UriPackage, UriWrapper)) + or uri_package_or_wrapper != uri + ): + step = UriResolutionStep( + source_uri=uri, + result=uri_package_or_wrapper, + sub_history=sub_context.get_history(), + description=self.get_step_description(), + ) + resolution_context.track_step(step) + return uri_package_or_wrapper + + step = UriResolutionStep( + source_uri=uri, + result=uri, + sub_history=sub_context.get_history(), + description=self.get_step_description(), + ) + resolution_context.track_step(step) + return uri diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/cache/__init__.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/cache/__init__.py index a2b310c6..dc25fa1e 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/cache/__init__.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/cache/__init__.py @@ -1,3 +1,2 @@ """This package contains the resolvers for caching.""" -from .cache_resolver import * -from .request_synchronizer_resolver import * +from .resolution_result_cache_resolver import * diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/cache/request_synchronizer_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/cache/request_synchronizer_resolver.py deleted file mode 100644 index ebc3df99..00000000 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/cache/request_synchronizer_resolver.py +++ /dev/null @@ -1,132 +0,0 @@ -"""This module contains the RequestSynchronizerResolver.""" -from asyncio import Future, ensure_future -from dataclasses import dataclass -from typing import Optional, Union - -from polywrap_core import ( - Dict, - InvokerClient, - IUriResolutionContext, - Uri, - UriPackageOrWrapper, - UriResolver, -) - -from ...types import UriResolutionStep - - -@dataclass(kw_only=True, slots=True) -class RequestSynchronizerResolverOptions: - """Defines the options for the RequestSynchronizerResolver. - - Attributes: - should_ignore_cache (Optional[bool]): Whether to ignore the cache.\ - Defaults to False. - """ - - should_ignore_cache: Optional[bool] - - -class RequestSynchronizerResolver(UriResolver): - """Defines a resolver that synchronizes requests. - - This resolver synchronizes requests to the same uri.\ - If a request is already in progress, it returns the future\ - of the existing request.\ - If a request is not in progress, it creates a new request\ - and returns the future of the new request. - - Attributes: - existing_requests (Dict[Uri, Future[UriPackageOrWrapper]]):\ - The existing requests. - resolver_to_synchronize (UriResolver): The URI resolver \ - to synchronize. - options (Optional[RequestSynchronizerResolverOptions]):\ - The options to use. - """ - - __slots__ = ("resolver_to_synchronize", "options") - - existing_requests: Dict[Uri, Future[UriPackageOrWrapper]] - resolver_to_synchronize: UriResolver - options: Optional[RequestSynchronizerResolverOptions] - - def __init__( - self, - resolver_to_synchronize: UriResolver, - options: Optional[RequestSynchronizerResolverOptions] = None, - ): - """Initialize a new RequestSynchronizerResolver instance. - - Args: - resolver_to_synchronize (UriResolver): The URI resolver \ - to synchronize. - options (Optional[RequestSynchronizerResolverOptions]):\ - The options to use. - """ - self.existing_requests = {} - self.resolver_to_synchronize = resolver_to_synchronize - self.options = options - - def get_options(self) -> Union[RequestSynchronizerResolverOptions, None]: - """Get the options. - - Returns: - Union[RequestSynchronizerResolverOptions, None]:\ - The options or None. - """ - return self.options - - async def try_resolve_uri( - self, - uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], - ) -> UriPackageOrWrapper: - """Try to resolve the given uri to a wrap package, wrapper or uri. - - Synchronize requests to the same uri.\ - If a request is already in progress, it returns the future\ - of the existing request.\ - If a request is not in progress, it creates a new request\ - and returns the future of the new request. - - Args: - uri (Uri): The uri to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]):\ - The resolution context. - - Returns: - UriPackageOrWrapper: The resolved uri package, wrapper or uri. - """ - sub_context = resolution_context.create_sub_history_context() - - if existing_request := self.existing_requests.get(uri): - uri_package_or_wrapper = await existing_request - resolution_context.track_step( - UriResolutionStep( - source_uri=uri, - result=uri_package_or_wrapper, - description="RequestSynchronizerResolver (Cache)", - ) - ) - return uri_package_or_wrapper - - request_future = ensure_future( - self.resolver_to_synchronize.try_resolve_uri( - uri, - client, - sub_context, - ) - ) - self.existing_requests[uri] = request_future - uri_package_or_wrapper = await request_future - resolution_context.track_step( - UriResolutionStep( - source_uri=uri, - result=uri_package_or_wrapper, - description="RequestSynchronizerResolver (Cache)", - ) - ) - return uri_package_or_wrapper diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/cache/resolution_result_cache_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/cache/resolution_result_cache_resolver.py new file mode 100644 index 00000000..247ccde2 --- /dev/null +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/cache/resolution_result_cache_resolver.py @@ -0,0 +1,114 @@ +"""This module contains the ResolutionResultCacheResolver.""" + +from polywrap_core import ( + InvokerClient, + Uri, + UriPackageOrWrapper, + UriResolutionContext, + UriResolutionStep, + UriResolver, +) + +from ...errors import UriResolutionError +from ...types import ResolutionResultCache + + +class ResolutionResultCacheResolver(UriResolver): + """An implementation of IUriResolver that caches the URI resolution result. + + The URI resolution result can be a URI, IWrapPackage, Wrapper, or Error. + Errors are not cached by default and can be cached by setting the cache_errors option to True. + + Attributes: + resolver_to_cache (UriResolver): The URI resolver to cache. + cache (ResolutionResultCache): The resolution result cache. + options (ResolutionResultCacheResolverOptions): The options to use. + """ + + __slots__ = ("resolver_to_cache", "cache", "cache_errors") + + resolver_to_cache: UriResolver + cache: ResolutionResultCache + cache_errors: bool + + def __init__( + self, + resolver_to_cache: UriResolver, + cache: ResolutionResultCache, + cache_errors: bool = False, + ): + """Initialize a new ResolutionResultCacheResolver instance. + + Args: + resolver_to_cache (UriResolver): The URI resolver to cache. + cache (ResolutionResultCache): The resolution result cache. + options (ResolutionResultCacheResolverOptions): The options to use. + """ + self.resolver_to_cache = resolver_to_cache + self.cache = cache + self.cache_errors = cache_errors + + def try_resolve_uri( + self, + uri: Uri, + client: InvokerClient, + resolution_context: UriResolutionContext, + ) -> UriPackageOrWrapper: + """Try to resolve a URI to a wrap package, a wrapper, or a URI. + + This method tries to resolve the URI with the resolver to cache.\ + If the result is in the cache, it returns the cached result.\ + If the result is not in the cache, it resolves the URI using\ + the inner resolver and caches the result. + + Args: + uri (Uri): The URI to resolve. + client (InvokerClient): The client to use. + resolution_context (UriResolutionContext): The resolution context to use. + + Returns: + UriPackageOrWrapper: The result of the resolution. + """ + if cached_result := self.cache.get(uri): + if isinstance(cached_result, UriResolutionError): + raise cached_result + + resolution_context.track_step( + UriResolutionStep( + source_uri=uri, + result=cached_result, + description="ResolutionResultCacheResolver (Cache)", + ) + ) + return cached_result + + sub_context = resolution_context.create_sub_history_context() + result: UriPackageOrWrapper + + if self.cache_errors: + try: + result = self.resolver_to_cache.try_resolve_uri( + uri, + client, + sub_context, + ) + except UriResolutionError as error: + self.cache.set(uri, error) + raise error + else: + result = self.resolver_to_cache.try_resolve_uri( + uri, + client, + sub_context, + ) + self.cache.set(uri, result) + + resolution_context.track_step( + UriResolutionStep( + source_uri=uri, + result=result, + sub_history=sub_context.get_history(), + description="ResolutionResultCacheResolver", + ) + ) + return result diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/extensions/extendable_uri_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/extensions/extendable_uri_resolver.py index 29bff003..e2c27b9e 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/extensions/extendable_uri_resolver.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/extensions/extendable_uri_resolver.py @@ -1,19 +1,13 @@ """This module contains the ExtendableUriResolver class.""" -from typing import List, Optional, cast +from typing import List, Optional -from polywrap_core import ( - InvokerClient, - IUriResolutionContext, - Uri, - UriPackageOrWrapper, - UriResolver, -) +from polywrap_core import InvokerClient, Uri, UriResolutionContext, UriResolver -from ..aggregator import UriResolverAggregator +from ..aggregator import UriResolverAggregatorBase from .extension_wrapper_uri_resolver import ExtensionWrapperUriResolver -class ExtendableUriResolver(UriResolver): +class ExtendableUriResolver(UriResolverAggregatorBase): """Defines a resolver that resolves a uri to a wrapper by using extension wrappers. This resolver resolves a uri to a wrapper by using extension wrappers.\ @@ -52,35 +46,22 @@ def __init__( """ self.ext_interface_uris = ext_interface_uris or self.DEFAULT_EXT_INTERFACE_URIS self.resolver_name = resolver_name or self.__class__.__name__ + super().__init__() - async def try_resolve_uri( - self, - uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], - ) -> UriPackageOrWrapper: - """Try to resolve a URI to a wrap package, a wrapper, or a URI. + def get_step_description(self) -> Optional[str]: + """Get the description of the resolution step.""" + return self.resolver_name - Args: - uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use for\ - resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]): The\ - resolution context. - - Returns: - UriPackageOrWrapper: The resolved URI, wrap package, or wrapper. - """ + def get_resolvers( + self, client: InvokerClient, resolution_context: UriResolutionContext + ) -> List[UriResolver]: + """Get the list of resolvers to aggregate.""" uri_resolvers_uris: List[Uri] = [] for ext_interface_uri in self.ext_interface_uris: uri_resolvers_uris.extend( - client.get_implementations(ext_interface_uri) or [] + client.get_implementations(ext_interface_uri, apply_resolution=False) + or [] ) - resolvers = [ExtensionWrapperUriResolver(uri) for uri in uri_resolvers_uris] - aggregator = UriResolverAggregator( - cast(List[UriResolver], resolvers), self.resolver_name - ) - - return await aggregator.try_resolve_uri(uri, client, resolution_context) + return [ExtensionWrapperUriResolver(uri) for uri in uri_resolvers_uris] diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/extensions/extension_wrapper_uri_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/extensions/extension_wrapper_uri_resolver.py index 1692df02..5862b99a 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/extensions/extension_wrapper_uri_resolver.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/extensions/extension_wrapper_uri_resolver.py @@ -1,28 +1,29 @@ """This module contains the ExtensionWrapperUriResolver class.""" -from typing import Optional, TypedDict, cast +from __future__ import annotations + +from typing import Optional, TypedDict from polywrap_core import ( - Client, - InvokeOptions, InvokerClient, - IUriResolutionContext, - TryResolveUriOptions, Uri, UriPackage, UriPackageOrWrapper, - UriWrapper, - Wrapper, + UriResolutionContext, + UriResolutionStep, + UriResolver, + WrapError, ) -from polywrap_msgpack import msgpack_decode from polywrap_wasm import WasmPackage -from ...errors import UriResolverExtensionError, UriResolverExtensionNotFoundError -from ...utils import get_env_from_uri_history -from ..abc import ResolverWithHistory +from ...errors import ( + InfiniteLoopError, + UriResolverExtensionError, + UriResolverExtensionNotFoundError, +) from .uri_resolver_extension_file_reader import UriResolverExtensionFileReader -class MaybeUriOrManifest(TypedDict): +class MaybeUriOrManifest(TypedDict, total=False): """Defines a type for the return value of the extension wrapper's\ tryResolveUri function. @@ -34,7 +35,7 @@ class MaybeUriOrManifest(TypedDict): manifest: Optional[bytes] -class ExtensionWrapperUriResolver(ResolverWithHistory): +class ExtensionWrapperUriResolver(UriResolver): """Defines a resolver that resolves a uri to a wrapper by using an extension wrapper. This resolver resolves a uri to a wrapper by using an extension wrapper.\ @@ -65,11 +66,11 @@ def get_step_description(self) -> str: """ return f"ResolverExtension ({self.extension_wrapper_uri})" - async def _try_resolve_uri( + def try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> UriPackageOrWrapper: """Try to resolve a URI to a wrap package, a wrapper, or a URI. @@ -80,9 +81,9 @@ async def _try_resolve_uri( Args: uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use for\ + client (InvokerClient): The client to use for\ resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]): The\ + resolution_context (UriResolutionContext): The\ resolution context. Returns: @@ -91,103 +92,70 @@ async def _try_resolve_uri( sub_context = resolution_context.create_sub_context() try: - extension_wrapper = await self._load_resolver_extension(client, sub_context) - uri_or_manifest = await self._try_resolve_uri_with_extension( - uri, extension_wrapper, client, sub_context + uri_package_or_wrapper = self._try_resolve_uri_with_extension( + uri, client, sub_context ) - if uri_or_manifest.get("uri"): - return Uri.from_str(cast(str, uri_or_manifest["uri"])) - - if uri_or_manifest.get("manifest"): - package = WasmPackage( - UriResolverExtensionFileReader( - self.extension_wrapper_uri, uri, client - ), - uri_or_manifest["manifest"], + resolution_context.track_step( + UriResolutionStep( + source_uri=uri, + result=uri_package_or_wrapper, + description=self.get_step_description(), + sub_history=sub_context.get_history(), ) - return UriPackage(uri, package) - - return uri + ) - except Exception as err: + return uri_package_or_wrapper + except WrapError as err: raise UriResolverExtensionError( f"Failed to resolve uri: {uri}, using extension resolver: " f"({self.extension_wrapper_uri})" ) from err - - async def _load_resolver_extension( - self, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], - ) -> Wrapper[UriPackageOrWrapper]: - """Load the URI resolver extension wrapper. - - Args: - client (InvokerClient[UriPackageOrWrapper]): The client to use for\ - resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]): The\ - resolution context. - """ - result = await client.try_resolve_uri( - TryResolveUriOptions( - uri=self.extension_wrapper_uri, resolution_context=resolution_context - ) - ) - - extension_wrapper: Wrapper[UriPackageOrWrapper] - - if isinstance(result, UriPackage): - extension_wrapper = await cast( - UriPackage[UriPackageOrWrapper], result - ).package.create_wrapper() - elif isinstance(result, UriWrapper): - extension_wrapper = cast(UriWrapper[UriPackageOrWrapper], result).wrapper - else: - raise UriResolverExtensionNotFoundError( - self.extension_wrapper_uri, resolution_context.get_history() - ) - return extension_wrapper - - async def _try_resolve_uri_with_extension( + except InfiniteLoopError as err: + if err.uri == self.extension_wrapper_uri: + raise UriResolverExtensionNotFoundError( + self.extension_wrapper_uri, sub_context.get_history() + ) from err + raise err + + def _try_resolve_uri_with_extension( self, uri: Uri, - extension_wrapper: Wrapper[UriPackageOrWrapper], - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], - ) -> MaybeUriOrManifest: + client: InvokerClient, + resolution_context: UriResolutionContext, + ) -> UriPackageOrWrapper: """Try to resolve a URI to a uri or a manifest using the extension wrapper. Args: uri (Uri): The URI to resolve. - extension_wrapper (Wrapper[UriPackageOrWrapper]): The extension wrapper. - client (InvokerClient[UriPackageOrWrapper]): The client to use for\ - resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]): The\ - resolution context. + client (InvokerClient): The client to use for resolving the URI. + resolution_context (UriResolutionContext): The resolution context. Returns: MaybeUriOrManifest: The resolved URI or manifest. """ - env = ( - get_env_from_uri_history( - resolution_context.get_resolution_path(), cast(Client, client) - ) - if hasattr(client, "get_env_by_uri") - else None + uri_or_manifest: Optional[MaybeUriOrManifest] = client.invoke( + uri=self.extension_wrapper_uri, + method="tryResolveUri", + args={ + "authority": uri.authority, + "path": uri.path, + }, + encode_result=False, + resolution_context=resolution_context, ) - result = await extension_wrapper.invoke( - InvokeOptions( - uri=self.extension_wrapper_uri, - method="tryResolveUri", - args={ - "authority": uri.authority, - "path": uri.path, - }, - env=env, - ), - client, - ) + if uri_or_manifest is None: + return uri + + if result_uri := uri_or_manifest.get("uri"): + return Uri.from_str(result_uri) + + if result_manifest := uri_or_manifest.get("manifest"): + package = WasmPackage( + UriResolverExtensionFileReader(self.extension_wrapper_uri, uri, client), + result_manifest, + ) + return UriPackage(uri=uri, package=package) - return msgpack_decode(result) if isinstance(result, bytes) else result + return uri diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/extensions/uri_resolver_extension_file_reader.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/extensions/uri_resolver_extension_file_reader.py index 7bacf0eb..c5106917 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/extensions/uri_resolver_extension_file_reader.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/extensions/uri_resolver_extension_file_reader.py @@ -1,7 +1,7 @@ """This module contains the UriResolverExtensionFileReader class.""" from pathlib import Path -from polywrap_core import FileReader, Invoker, InvokerOptions, Uri, UriPackageOrWrapper +from polywrap_core import FileReader, Invoker, Uri class UriResolverExtensionFileReader(FileReader): @@ -14,31 +14,31 @@ class UriResolverExtensionFileReader(FileReader): Attributes: extension_uri (Uri): The uri of the extension wrapper. wrapper_uri (Uri): The uri of the wrapper that uses the extension wrapper. - invoker (Invoker[UriPackageOrWrapper]): The invoker used to invoke the getFile method. + invoker (Invoker): The invoker used to invoke the getFile method. """ extension_uri: Uri wrapper_uri: Uri - invoker: Invoker[UriPackageOrWrapper] + invoker: Invoker def __init__( self, extension_uri: Uri, wrapper_uri: Uri, - invoker: Invoker[UriPackageOrWrapper], + invoker: Invoker, ): """Initialize a new UriResolverExtensionFileReader instance. Args: extension_uri (Uri): The uri of the extension wrapper. wrapper_uri (Uri): The uri of the wrapper that uses the extension wrapper. - invoker (Invoker[UriPackageOrWrapper]): The invoker used to invoke the getFile method. + invoker (Invoker): The invoker used to invoke the getFile method. """ self.extension_uri = extension_uri self.wrapper_uri = wrapper_uri self.invoker = invoker - async def read_file(self, file_path: str) -> bytes: + def read_file(self, file_path: str) -> bytes: """Read a file using the extension wrapper. Args: @@ -48,10 +48,8 @@ async def read_file(self, file_path: str) -> bytes: bytes: The contents of the file. """ path = str(Path(self.wrapper_uri.path).joinpath(file_path)) - result = await self.invoker.invoke( - InvokerOptions( - uri=self.extension_uri, method="getFile", args={"path": path} - ) + result = self.invoker.invoke( + uri=self.extension_uri, method="getFile", args={"path": path} ) if not isinstance(result, bytes): diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/base_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/base_resolver.py index 6fd1bcc4..fd3c8582 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/base_resolver.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/base_resolver.py @@ -4,9 +4,9 @@ from polywrap_core import ( FileReader, InvokerClient, - IUriResolutionContext, Uri, UriPackageOrWrapper, + UriResolutionContext, UriResolver, ) @@ -30,26 +30,26 @@ def __init__(self, file_reader: FileReader, redirects: Dict[Uri, Uri]): self._fs_resolver = FsUriResolver(file_reader) self._redirect_resolver = RedirectUriResolver(redirects) - async def try_resolve_uri( + def try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> UriPackageOrWrapper: """Try to resolve a URI to a wrap package, a wrapper, or a URI. Args: uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use for resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]): The resolution context. + client (InvokerClient): The client to use for resolving the URI. + resolution_context (UriResolutionContext): The resolution context. Returns: UriPackageOrWrapper: The resolved URI. """ - redirected_uri = await self._redirect_resolver.try_resolve_uri( + redirected_uri = self._redirect_resolver.try_resolve_uri( uri, client, resolution_context ) - return await self._fs_resolver.try_resolve_uri( + return self._fs_resolver.try_resolve_uri( redirected_uri, client, resolution_context ) diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/fs_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/fs_resolver.py index b793702f..ade7ff60 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/fs_resolver.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/fs_resolver.py @@ -4,19 +4,20 @@ from polywrap_core import ( FileReader, InvokerClient, - IUriResolutionContext, Uri, UriPackage, UriPackageOrWrapper, + UriResolutionContext, UriResolver, ) -from polywrap_wasm import WRAP_MANIFEST_PATH, WRAP_MODULE_PATH, WasmPackage +from polywrap_wasm import WasmPackage +from polywrap_wasm.constants import WRAP_MANIFEST_PATH, WRAP_MODULE_PATH class SimpleFileReader(FileReader): """Defines a simple file reader.""" - async def read_file(self, file_path: str) -> bytes: + def read_file(self, file_path: str) -> bytes: """Read a file. Args: @@ -42,18 +43,18 @@ def __init__(self, file_reader: FileReader): """ self.file_reader = file_reader - async def try_resolve_uri( + def try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> UriPackageOrWrapper: """Try to resolve a URI. Args: uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use for resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]): The resolution context. + client (InvokerClient): The client to use for resolving the URI. + resolution_context (UriResolutionContext): The resolution context. Returns: UriPackageOrWrapper: The resolved URI. @@ -63,13 +64,9 @@ async def try_resolve_uri( wrapper_path = Path(uri.path) - wasm_module = await self.file_reader.read_file( - str(wrapper_path / WRAP_MODULE_PATH) - ) + wasm_module = self.file_reader.read_file(str(wrapper_path / WRAP_MODULE_PATH)) - manifest = await self.file_reader.read_file( - str(wrapper_path / WRAP_MANIFEST_PATH) - ) + manifest = self.file_reader.read_file(str(wrapper_path / WRAP_MANIFEST_PATH)) return UriPackage( uri=uri, diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/package/package_to_wrapper_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/package_to_wrapper_resolver.py similarity index 80% rename from packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/package/package_to_wrapper_resolver.py rename to packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/package_to_wrapper_resolver.py index 3dd2a472..7cc45eea 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/package/package_to_wrapper_resolver.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/package_to_wrapper_resolver.py @@ -1,19 +1,19 @@ """This module contains the PackageToWrapperResolver class.""" from dataclasses import dataclass -from typing import Optional, cast +from typing import Optional from polywrap_core import ( InvokerClient, - IUriResolutionContext, Uri, UriPackage, UriPackageOrWrapper, + UriResolutionContext, + UriResolutionStep, UriResolver, UriWrapper, ) from polywrap_manifest import DeserializeManifestOptions -from ...types import UriResolutionStep from ..abc import ResolverWithHistory @@ -58,31 +58,30 @@ def __init__( """ self.resolver = resolver self.options = options + super().__init__() - async def _try_resolve_uri( + def _try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> UriPackageOrWrapper: """Try to resolve the given URI to a wrapper or a redirected URI. Args: uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]):\ + client (InvokerClient): The client to use. + resolution_context (IUriResolutionContext):\ The resolution context to use. Returns: UriPackageOrWrapper: The resolved URI or wrapper. """ sub_context = resolution_context.create_sub_context() - result = await self.resolver.try_resolve_uri(uri, client, sub_context) + result = self.resolver.try_resolve_uri(uri, client, sub_context) if isinstance(result, UriPackage): - wrapper = await cast( - UriPackage[UriPackageOrWrapper], result - ).package.create_wrapper() - result = UriWrapper(uri, wrapper) + wrapper = result.package.create_wrapper() + result = UriWrapper(uri=uri, wrapper=wrapper) resolution_context.track_step( UriResolutionStep( diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/redirect_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/redirect_resolver.py index cdb9b652..3e34ab67 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/redirect_resolver.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/redirect_resolver.py @@ -1,13 +1,7 @@ """This module contains the RedirectUriResolver class.""" from typing import Dict -from polywrap_core import ( - InvokerClient, - IUriResolutionContext, - Uri, - UriPackageOrWrapper, - UriResolver, -) +from polywrap_core import InvokerClient, Uri, UriResolutionContext, UriResolver class RedirectUriResolver(UriResolver): @@ -23,18 +17,18 @@ def __init__(self, redirects: Dict[Uri, Uri]): """ self._redirects = redirects - async def try_resolve_uri( + def try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> Uri: """Try to resolve a URI to redirected URI. Args: uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use for resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]): The resolution context. + client (InvokerClient): The client to use for resolving the URI. + resolution_context (UriResolutionContext): The resolution context. Returns: Uri: The resolved URI. diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/wrapper_cache/__init__.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/wrapper_cache/__init__.py new file mode 100644 index 00000000..30b09078 --- /dev/null +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/wrapper_cache/__init__.py @@ -0,0 +1,3 @@ +"""This package contains interface and implementations for wrapper cache.""" +from .in_memory_wrapper_cache import * +from .wrapper_cache import * diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/in_memory_wrapper_cache.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/wrapper_cache/in_memory_wrapper_cache.py similarity index 64% rename from packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/in_memory_wrapper_cache.py rename to packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/wrapper_cache/in_memory_wrapper_cache.py index aca47d11..16975e64 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/in_memory_wrapper_cache.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/wrapper_cache/in_memory_wrapper_cache.py @@ -1,7 +1,7 @@ """This module contains the in-memory wrapper cache.""" from typing import Dict, Union -from polywrap_core import Uri, UriPackageOrWrapper, Wrapper +from polywrap_core import Uri, UriWrapper from .wrapper_cache import WrapperCache @@ -10,19 +10,19 @@ class InMemoryWrapperCache(WrapperCache): """InMemoryWrapperCache is an in-memory implementation of the wrapper cache interface. Attributes: - map (Dict[Uri, Wrapper]): The map of uris to wrappers. + map (Dict[Uri, UriWrapper]): The map of uris to wrappers. """ - map: Dict[Uri, Wrapper[UriPackageOrWrapper]] + map: Dict[Uri, UriWrapper] def __init__(self): """Initialize a new InMemoryWrapperCache instance.""" self.map = {} - def get(self, uri: Uri) -> Union[Wrapper[UriPackageOrWrapper], None]: + def get(self, uri: Uri) -> Union[UriWrapper, None]: """Get a wrapper from the cache by its uri.""" return self.map.get(uri) - def set(self, uri: Uri, wrapper: Wrapper[UriPackageOrWrapper]) -> None: + def set(self, uri: Uri, wrapper: UriWrapper) -> None: """Set a wrapper in the cache by its uri.""" self.map[uri] = wrapper diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/wrapper_cache.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/wrapper_cache/wrapper_cache.py similarity index 54% rename from packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/wrapper_cache.py rename to packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/wrapper_cache/wrapper_cache.py index 505eb6be..9825b59b 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/wrapper_cache.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/wrapper_cache/wrapper_cache.py @@ -1,20 +1,20 @@ """This module contains the wrapper cache interface.""" -from abc import ABC, abstractmethod -from typing import Union +from abc import abstractmethod +from typing import Protocol, Union -from polywrap_core import Uri, UriPackageOrWrapper, Wrapper +from polywrap_core import Uri, UriWrapper -class WrapperCache(ABC): +class WrapperCache(Protocol): """Defines a cache interface for caching wrappers by uri. This is used by the wrapper resolver to cache wrappers for a given uri. """ @abstractmethod - def get(self, uri: Uri) -> Union[Wrapper[UriPackageOrWrapper], None]: + def get(self, uri: Uri) -> Union[UriWrapper, None]: """Get a wrapper from the cache by its uri.""" @abstractmethod - def set(self, uri: Uri, wrapper: Wrapper[UriPackageOrWrapper]) -> None: + def set(self, uri: Uri, wrapper: UriWrapper) -> None: """Set a wrapper in the cache by its uri.""" diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/cache/cache_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/wrapper_cache_resolver.py similarity index 82% rename from packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/cache/cache_resolver.py rename to packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/wrapper_cache_resolver.py index 94e076ab..08ac0748 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/cache/cache_resolver.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/legacy/wrapper_cache_resolver.py @@ -1,19 +1,19 @@ """This module contains the WrapperCacheResolver.""" from dataclasses import dataclass -from typing import List, Optional, Union, cast +from typing import List, Optional, Union from polywrap_core import ( InvokerClient, - IUriResolutionContext, Uri, UriPackageOrWrapper, + UriResolutionContext, + UriResolutionStep, UriResolver, UriWrapper, - Wrapper, ) from polywrap_manifest import DeserializeManifestOptions -from ...types import UriResolutionStep, WrapperCache +from .wrapper_cache import WrapperCache @dataclass(kw_only=True, slots=True) @@ -75,11 +75,11 @@ def get_options(self) -> Union[WrapperCacheResolverOptions, None]: """ return self.options - async def try_resolve_uri( + def try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> UriPackageOrWrapper: """Try to resolve a URI to a wrapper, or a URI. @@ -90,37 +90,35 @@ async def try_resolve_uri( Args: uri (Uri): The URI to resolve. client (InvokerClient): The client to use. - resolution_context (IUriResolutionContext): The resolution\ + resolution_context (UriResolutionContext): The resolution\ context to use. Returns: UriPackageOrWrapper: The result of the resolution. """ - if wrapper := self.cache.get(uri): - result = UriWrapper(uri, wrapper) + if uri_wrapper := self.cache.get(uri): resolution_context.track_step( UriResolutionStep( source_uri=uri, - result=result, + result=uri_wrapper, description="WrapperCacheResolver (Cache Hit)", ) ) - return result + return uri_wrapper sub_context = resolution_context.create_sub_history_context() - result = await self.resolver_to_cache.try_resolve_uri( + result = self.resolver_to_cache.try_resolve_uri( uri, client, sub_context, ) - if isinstance(result, Wrapper): - uri_wrapper = cast(UriWrapper[UriPackageOrWrapper], result) + if isinstance(result, UriWrapper): resolution_path: List[Uri] = sub_context.get_resolution_path() for cache_uri in resolution_path: - self.cache.set(cache_uri, uri_wrapper.wrapper) + self.cache.set(cache_uri, result) resolution_context.track_step( UriResolutionStep( diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/package/__init__.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/package/__init__.py index d7c941e1..9538aca7 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/package/__init__.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/package/__init__.py @@ -1,3 +1,2 @@ """This package contains the resolvers for packages.""" from .package_resolver import * -from .package_to_wrapper_resolver import * diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/package/package_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/package/package_resolver.py index 2af39593..c25623c0 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/package/package_resolver.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/package/package_resolver.py @@ -1,10 +1,10 @@ """This module contains the PackageResolver class.""" from polywrap_core import ( InvokerClient, - IUriResolutionContext, Uri, UriPackage, UriPackageOrWrapper, + UriResolutionContext, WrapPackage, ) @@ -14,20 +14,21 @@ class PackageResolver(ResolverWithHistory): """Defines a resolver that resolves a uri to a package.""" - __slots__ = ("uri", "wrap_package") + __slots__ = ("uri", "package") uri: Uri - wrap_package: WrapPackage[UriPackageOrWrapper] + package: WrapPackage - def __init__(self, uri: Uri, wrap_package: WrapPackage[UriPackageOrWrapper]): + def __init__(self, uri: Uri, wrap_package: WrapPackage): """Initialize a new PackageResolver instance. Args: uri (Uri): The uri to resolve. - wrap_package (WrapPackage[UriPackageOrWrapper]): The wrap package to return. + wrap_package (WrapPackage): The wrap package to return. """ self.uri = uri - self.wrap_package = wrap_package + self.package = wrap_package + super().__init__() def get_step_description(self) -> str: """Get the description of the resolver step. @@ -37,11 +38,11 @@ def get_step_description(self) -> str: """ return f"Package ({self.uri.uri})" - async def _try_resolve_uri( + def _try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> UriPackageOrWrapper: """Try to resolve a URI to a wrap package, a wrapper, or a URI. @@ -51,12 +52,12 @@ async def _try_resolve_uri( Args: uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use for\ + client (InvokerClient): The client to use for\ resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]): The\ + resolution_context (UriResolutionContext): The\ resolution context. Returns: UriPackageOrWrapper: The resolved URI package, wrapper, or URI. """ - return uri if uri != self.uri else UriPackage(uri, self.wrap_package) + return uri if uri != self.uri else UriPackage(uri=uri, package=self.package) diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/recursive/recursive_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/recursive/recursive_resolver.py index e00fe37d..06a69e13 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/recursive/recursive_resolver.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/recursive/recursive_resolver.py @@ -1,9 +1,9 @@ """This module contains the recursive resolver.""" from polywrap_core import ( InvokerClient, - IUriResolutionContext, Uri, UriPackageOrWrapper, + UriResolutionContext, UriResolver, ) @@ -32,18 +32,18 @@ def __init__(self, resolver: UriResolver): """ self.resolver = resolver - async def try_resolve_uri( + def try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> UriPackageOrWrapper: """Try to resolve a URI to a wrap package, a wrapper, or a URI. Args: uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use for resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]): The resolution context. + client (InvokerClient): The client to use for resolving the URI. + resolution_context (UriResolutionContext): The resolution context. Returns: UriPackageOrWrapper: The resolved URI. @@ -53,13 +53,15 @@ async def try_resolve_uri( resolution_context.start_resolving(uri) - uri_package_or_wrapper = await self.resolver.try_resolve_uri( + uri_package_or_wrapper = self.resolver.try_resolve_uri( uri, client, resolution_context ) - if uri_package_or_wrapper != uri: - uri_package_or_wrapper = await self.try_resolve_uri( - uri_package_or_wrapper, client, resolution_context + if isinstance(uri_package_or_wrapper, Uri) and uri_package_or_wrapper != uri: + uri_package_or_wrapper = self.try_resolve_uri( + uri_package_or_wrapper, + client, + resolution_context, ) resolution_context.stop_resolving(uri) diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/redirect/redirect_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/redirect/redirect_resolver.py index 34f3b05b..837d53ed 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/redirect/redirect_resolver.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/redirect/redirect_resolver.py @@ -1,5 +1,5 @@ """This module contains the RedirectResolver class.""" -from polywrap_core import InvokerClient, IUriResolutionContext, Uri, UriPackageOrWrapper +from polywrap_core import InvokerClient, Uri, UriPackageOrWrapper, UriResolutionContext from ..abc import ResolverWithHistory @@ -30,6 +30,7 @@ def __init__(self, from_uri: Uri, to_uri: Uri) -> None: """ self.from_uri = from_uri self.to_uri = to_uri + super().__init__() def get_step_description(self) -> str: """Get the description of the resolver step. @@ -39,11 +40,11 @@ def get_step_description(self) -> str: """ return f"Redirect ({self.from_uri} - {self.to_uri})" - async def _try_resolve_uri( + def _try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> UriPackageOrWrapper: """Try to resolve a URI to a wrap package, a wrapper, or a URI. @@ -53,10 +54,8 @@ async def _try_resolve_uri( Args: uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use for\ - resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]): The\ - resolution context. + client (InvokerClient): The client to use for resolving the URI. + resolution_context (UriResolutionContext): The resolution context. Returns: UriPackageOrWrapper: The resolved URI package, wrapper, or URI. diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/static/static_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/static/static_resolver.py index 5a5757d4..cd1db81d 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/static/static_resolver.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/static/static_resolver.py @@ -1,15 +1,13 @@ """This module contains the StaticResolver class.""" from polywrap_core import ( InvokerClient, - IUriResolutionContext, - IUriResolutionStep, Uri, UriPackage, UriPackageOrWrapper, + UriResolutionContext, + UriResolutionStep, UriResolver, UriWrapper, - WrapPackage, - Wrapper, ) from ...types import StaticResolverLike @@ -34,38 +32,39 @@ def __init__(self, uri_map: StaticResolverLike): """ self.uri_map = uri_map - async def try_resolve_uri( + def try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> UriPackageOrWrapper: """Try to resolve a URI to a wrap package, a wrapper, or a URI. Args: uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use for resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]): The resolution context. + client (InvokerClient): The client to use for resolving the URI. + resolution_context (UriResolutionContext): The resolution context. Returns: UriPackageOrWrapper: The resolved URI. """ result = self.uri_map.get(uri) - uri_package_or_wrapper: UriPackageOrWrapper = uri - description: str = "StaticResolver - Miss" - if result: - if isinstance(result, WrapPackage): - description = f"Static - Package ({uri})" - uri_package_or_wrapper = UriPackage(uri, result) - elif isinstance(result, Wrapper): - description = f"Static - Wrapper ({uri})" - uri_package_or_wrapper = UriWrapper(uri, result) - else: - description = f"Static - Redirect ({uri}, {result})" + match result: + case None: + description: str = "Static - Miss" + uri_package_or_wrapper: UriPackageOrWrapper = uri + case UriPackage(): + description = "Static - Package" + uri_package_or_wrapper = result + case UriWrapper(): + description = "Static - Wrapper" + uri_package_or_wrapper = result + case _: + description = f"Static - Redirect ({uri} - {result})" uri_package_or_wrapper = result - step = IUriResolutionStep( + step = UriResolutionStep( source_uri=uri, result=uri_package_or_wrapper, description=description ) resolution_context.track_step(step) diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/wrapper/wrapper_resolver.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/wrapper/wrapper_resolver.py index c549d076..4d39d230 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/wrapper/wrapper_resolver.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/resolvers/wrapper/wrapper_resolver.py @@ -1,9 +1,9 @@ """This module contains the resolver for wrappers.""" from polywrap_core import ( InvokerClient, - IUriResolutionContext, Uri, UriPackageOrWrapper, + UriResolutionContext, UriWrapper, Wrapper, ) @@ -16,23 +16,24 @@ class WrapperResolver(ResolverWithHistory): Attributes: uri (Uri): The uri to resolve. - wrapper (Wrapper[UriPackageOrWrapper]): The wrapper to use. + wrapper (Wrapper): The wrapper to use. """ __slots__ = ("uri", "wrapper") uri: Uri - wrapper: Wrapper[UriPackageOrWrapper] + wrapper: Wrapper - def __init__(self, uri: Uri, wrapper: Wrapper[UriPackageOrWrapper]): + def __init__(self, uri: Uri, wrapper: Wrapper): """Initialize a new WrapperResolver instance. Args: uri (Uri): The uri to resolve. - wrapper (Wrapper[UriPackageOrWrapper]): The wrapper to use. + wrapper (Wrapper): The wrapper to use. """ self.uri = uri self.wrapper = wrapper + super().__init__() def get_step_description(self) -> str: """Get the description of the resolver step. @@ -42,20 +43,20 @@ def get_step_description(self) -> str: """ return f"Wrapper ({self.uri})" - async def _try_resolve_uri( + def _try_resolve_uri( self, uri: Uri, - client: InvokerClient[UriPackageOrWrapper], - resolution_context: IUriResolutionContext[UriPackageOrWrapper], + client: InvokerClient, + resolution_context: UriResolutionContext, ) -> UriPackageOrWrapper: """Try to resolve a URI to a wrap package, a wrapper, or a URI. Args: uri (Uri): The URI to resolve. - client (InvokerClient[UriPackageOrWrapper]): The client to use for resolving the URI. - resolution_context (IUriResolutionContext[UriPackageOrWrapper]): The resolution context. + client (InvokerClient): The client to use for resolving the URI. + resolution_context (UriResolutionContext): The resolution context. Returns: UriPackageOrWrapper: The resolved URI, wrap package, or wrapper. """ - return uri if uri != self.uri else UriWrapper(uri, self.wrapper) + return uri if uri != self.uri else UriWrapper(uri=uri, wrapper=self.wrapper) diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/__init__.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/__init__.py index abfded87..b5019260 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/__init__.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/__init__.py @@ -2,5 +2,4 @@ from .cache import * from .static_resolver_like import * from .uri_redirect import * -from .uri_resolution_context import * from .uri_resolver_like import * diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/__init__.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/__init__.py index 30b09078..3824e09e 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/__init__.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/__init__.py @@ -1,3 +1,2 @@ -"""This package contains interface and implementations for wrapper cache.""" -from .in_memory_wrapper_cache import * -from .wrapper_cache import * +"""This package contains implementations for the cache.""" +from .resolution_result_cache import * diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/resolution_result_cache/__init__.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/resolution_result_cache/__init__.py new file mode 100644 index 00000000..58b79226 --- /dev/null +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/resolution_result_cache/__init__.py @@ -0,0 +1,3 @@ +"""This package contains interface and implementations for wrapper cache.""" +from .in_memory_resolution_result_cache import * +from .resolution_result_cache import * diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/resolution_result_cache/in_memory_resolution_result_cache.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/resolution_result_cache/in_memory_resolution_result_cache.py new file mode 100644 index 00000000..035833e6 --- /dev/null +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/resolution_result_cache/in_memory_resolution_result_cache.py @@ -0,0 +1,37 @@ +"""This module contains the in-memory wrapper cache.""" +from typing import Dict, Union + +from polywrap_core import Uri, UriPackageOrWrapper + +from ....errors import UriResolutionError +from .resolution_result_cache import ResolutionResultCache + + +class InMemoryResolutionResultCache(ResolutionResultCache): + """InMemoryResolutionResultCache is an in-memory implementation \ + of the resolution result cache interface. + + Attributes: + map (Dict[Uri, Union[UriPackageOrWrapper, UriResolutionError]]):\ + The map of uris to resolution result. + """ + + map: Dict[Uri, Union[UriPackageOrWrapper, UriResolutionError]] + + def __init__(self): + """Initialize a new InMemoryResolutionResultCache instance.""" + self.map = {} + + def get(self, uri: Uri) -> Union[UriPackageOrWrapper, UriResolutionError, None]: + """Get the resolution result from the cache by its uri.""" + return self.map.get(uri) + + def set( + self, uri: Uri, result: Union[UriPackageOrWrapper, UriResolutionError] + ) -> None: + """Set the resolution result in the cache by its uri.""" + self.map[uri] = result + + def __str__(self) -> str: + """Display cache as a string.""" + return f"{self.map}" diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/resolution_result_cache/resolution_result_cache.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/resolution_result_cache/resolution_result_cache.py new file mode 100644 index 00000000..154eb71c --- /dev/null +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/cache/resolution_result_cache/resolution_result_cache.py @@ -0,0 +1,29 @@ +"""This module contains the wrapper cache interface.""" +# pylint: disable=unnecessary-ellipsis +from typing import Protocol, Union + +from polywrap_core import Uri, UriPackageOrWrapper + +from ....errors import UriResolutionError + + +class ResolutionResultCache(Protocol): + """Defines a cache interface for caching resolution results by uri. + + This is used by the resolution result resolver to cache resolution results\ + for a given uri. + """ + + def get(self, uri: Uri) -> Union[UriPackageOrWrapper, UriResolutionError, None]: + """Get the resolution result from the cache by its uri.""" + ... + + def set( + self, uri: Uri, result: Union[UriPackageOrWrapper, UriResolutionError] + ) -> None: + """Set the resolution result in the cache by its uri.""" + ... + + def __str__(self) -> str: + """Display cache as a string.""" + ... diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/static_resolver_like.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/static_resolver_like.py index 0bad456f..933b62ec 100644 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/static_resolver_like.py +++ b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/static_resolver_like.py @@ -2,19 +2,9 @@ StaticResolverLike is a type that represents a union of types\ that can be used as a StaticResolver. - ->>> StaticResolverLike = Union[ -... Dict[Uri, Uri], -... Dict[Uri, WrapPackage], -... Dict[Uri, Wrapper], -... ] """ -from typing import Dict, Union +from typing import Dict -from polywrap_core import Uri, UriPackageOrWrapper, WrapPackage, Wrapper +from polywrap_core import Uri, UriPackageOrWrapper -StaticResolverLike = Union[ - Dict[Uri, Uri], - Dict[Uri, WrapPackage[UriPackageOrWrapper]], - Dict[Uri, Wrapper[UriPackageOrWrapper]], -] +StaticResolverLike = Dict[Uri, UriPackageOrWrapper] diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/uri_resolution_context/__init__.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/uri_resolution_context/__init__.py deleted file mode 100644 index 5923e009..00000000 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/uri_resolution_context/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -"""This module contains the utility classes and functions for URI Resolution.""" -from .uri_resolution_context import * -from .uri_resolution_step import * diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/uri_resolution_context/uri_resolution_context.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/uri_resolution_context/uri_resolution_context.py deleted file mode 100644 index 700a9c1a..00000000 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/uri_resolution_context/uri_resolution_context.py +++ /dev/null @@ -1,121 +0,0 @@ -"""This module contains implementation of IUriResolutionContext interface.""" -from typing import List, Optional, Set - -from polywrap_core import ( - IUriResolutionContext, - IUriResolutionStep, - Uri, - UriPackageOrWrapper, -) - - -class UriResolutionContext(IUriResolutionContext[UriPackageOrWrapper]): - """Represents the context of a uri resolution. - - Attributes: - resolving_uri_set: A set of uris that are currently being resolved. - resolution_path: A list of uris in the order that they are being resolved. - history: A list of steps that have been taken to resolve the uri. - """ - - resolving_uri_set: Set[Uri] - resolution_path: List[Uri] - history: List[IUriResolutionStep[UriPackageOrWrapper]] - - __slots__ = ("resolving_uri_map", "resolution_path", "history") - - def __init__( - self, - resolving_uri_set: Optional[Set[Uri]] = None, - resolution_path: Optional[List[Uri]] = None, - history: Optional[List[IUriResolutionStep[UriPackageOrWrapper]]] = None, - ): - """Initialize a new instance of UriResolutionContext. - - Args: - resolving_uri_set: A set of uris that are currently being resolved. - resolution_path: A list of uris in the order that they are being resolved. - history: A list of steps that have been taken to resolve the uri. - """ - self.resolving_uri_set = resolving_uri_set or set() - self.resolution_path = resolution_path or [] - self.history = history or [] - - def is_resolving(self, uri: Uri) -> bool: - """Check if the given uri is currently being resolved. - - Args: - uri: The uri to check. - - Returns: - bool: True if the uri is currently being resolved, otherwise False. - """ - return uri in self.resolving_uri_set - - def start_resolving(self, uri: Uri) -> None: - """Start resolving the given uri. - - Args: - uri: The uri to start resolving. - - Returns: None - """ - self.resolving_uri_set.add(uri) - self.resolution_path.append(uri) - - def stop_resolving(self, uri: Uri) -> None: - """Stop resolving the given uri. - - Args: - uri: The uri to stop resolving. - - Returns: None - """ - self.resolving_uri_set.remove(uri) - - def track_step(self, step: IUriResolutionStep[UriPackageOrWrapper]) -> None: - """Track the given step in the resolution history. - - Args: - step: The step to track. - - Returns: None - """ - self.history.append(step) - - def get_history(self) -> List[IUriResolutionStep[UriPackageOrWrapper]]: - """Get the resolution history. - - Returns: - List[IUriResolutionStep]: The resolution history. - """ - return self.history - - def get_resolution_path(self) -> List[Uri]: - """Get the resolution path. - - Returns: - List[Uri]: The ordered list of URI resolution path. - """ - return self.resolution_path - - def create_sub_history_context(self) -> IUriResolutionContext[UriPackageOrWrapper]: - """Create a new sub context that shares the same resolution path. - - Returns: - IUriResolutionContext: The new context. - """ - return UriResolutionContext( - resolving_uri_set=self.resolving_uri_set, - resolution_path=self.resolution_path, - ) - - def create_sub_context(self) -> IUriResolutionContext[UriPackageOrWrapper]: - """Create a new sub context that shares the same resolution history. - - Returns: - IUriResolutionContext: The new context. - """ - return UriResolutionContext( - resolving_uri_set=self.resolving_uri_set, history=self.history - ) diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/uri_resolution_context/uri_resolution_step.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/uri_resolution_context/uri_resolution_step.py deleted file mode 100644 index effeec4a..00000000 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/types/uri_resolution_context/uri_resolution_step.py +++ /dev/null @@ -1,18 +0,0 @@ -"""This module contains implementation of IUriResolutionStep interface.""" -from __future__ import annotations - -from dataclasses import dataclass - -from polywrap_core import IUriResolutionStep, UriPackageOrWrapper - - -@dataclass(slots=True, kw_only=True) -class UriResolutionStep(IUriResolutionStep[UriPackageOrWrapper]): - """Represents a single step in the resolution of a uri. - - Attributes: - source_uri: The uri that was resolved. - result: The result of the resolution. - description: A description of the resolution step. - sub_history: A list of sub steps that were taken to resolve the uri. - """ diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/utils/__init__.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/utils/__init__.py deleted file mode 100644 index 6f71584a..00000000 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/utils/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""This package contains the utilities used by the polywrap-uri-resolvers package.""" -from .build_clean_uri_history import * -from .get_env_from_uri_history import * -from .get_uri_resolution_path import * diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/utils/build_clean_uri_history.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/utils/build_clean_uri_history.py deleted file mode 100644 index 9eddd139..00000000 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/utils/build_clean_uri_history.py +++ /dev/null @@ -1,73 +0,0 @@ -"""This module contains an utility function for building a clean history of URI resolution steps.""" -from typing import List, Optional, TypeVar, Union - -from polywrap_core import IUriResolutionStep, Uri, UriLike, UriPackage - -CleanResolutionStep = List[Union[str, "CleanResolutionStep"]] - -TUriLike = TypeVar("TUriLike", bound=UriLike) - - -def build_clean_uri_history( - history: List[IUriResolutionStep[TUriLike]], depth: Optional[int] = None -) -> CleanResolutionStep: - """Build a clean history of the URI resolution steps. - - Args: - history: A list of URI resolution steps. - depth: The depth of the history to build. - - Returns: - CleanResolutionStep: A clean history of the URI resolution steps. - """ - clean_history: CleanResolutionStep = [] - - if depth is not None: - depth -= 1 - - if not history: - return clean_history - - for step in history: - clean_history.append(_build_clean_history_step(step)) - - if ( - not step.sub_history - or len(step.sub_history) == 0 - or (depth is not None and depth < 0) - ): - continue - - sub_history = build_clean_uri_history(step.sub_history, depth) - if len(sub_history) > 0: - clean_history.append(sub_history) - - return clean_history - - -def _build_clean_history_step(step: IUriResolutionStep[TUriLike]) -> str: - uri_package_or_wrapper = step.result - - if isinstance(uri_package_or_wrapper, Uri): - if step.source_uri == uri_package_or_wrapper: - return ( - f"{step.source_uri} => {step.description}" - if step.description - else f"{step.source_uri}" - ) - return ( - f"{step.source_uri} => {step.description} => uri ({uri_package_or_wrapper.uri})" - if step.description - else f"{step.source_uri} => uri ({uri_package_or_wrapper})" - ) - if isinstance(uri_package_or_wrapper, UriPackage): - return ( - f"{step.source_uri} => {step.description} => package ({uri_package_or_wrapper})" - if step.description - else f"{step.source_uri} => package ({uri_package_or_wrapper})" - ) - return ( - f"{step.source_uri} => {step.description} => wrapper ({uri_package_or_wrapper})" - if step.description - else f"{step.source_uri} => wrapper ({uri_package_or_wrapper})" - ) diff --git a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/utils/get_uri_resolution_path.py b/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/utils/get_uri_resolution_path.py deleted file mode 100644 index 6e650e6a..00000000 --- a/packages/polywrap-uri-resolvers/polywrap_uri_resolvers/utils/get_uri_resolution_path.py +++ /dev/null @@ -1,35 +0,0 @@ -"""This module contains the get_uri_resolution_path function.""" -from typing import List, TypeVar - -from polywrap_core import IUriResolutionStep, UriLike - -TUriLike = TypeVar("TUriLike", bound=UriLike) - - -def get_uri_resolution_path( - history: List[IUriResolutionStep[TUriLike]], -) -> List[IUriResolutionStep[TUriLike]]: - """Get the URI resolution path from the URI resolution history. - - Args: - history (List[IUriResolutionStep[TUriLike]]): URI resolution history - - Returns: - List[IUriResolutionStep[TUriLike]]: URI resolution path - """ - # Get all non-empty items from the resolution history - - def add_uri_resolution_path_for_sub_history( - step: IUriResolutionStep[TUriLike], - ) -> IUriResolutionStep[TUriLike]: - if step.sub_history and len(step.sub_history): - step.sub_history = get_uri_resolution_path(step.sub_history) - return step - - return [ - add_uri_resolution_path_for_sub_history(step) - for step in filter( - lambda step: step.source_uri != step.result, - history, - ) - ] diff --git a/packages/polywrap-uri-resolvers/pyproject.toml b/packages/polywrap-uri-resolvers/pyproject.toml index 727c52cf..152a9232 100644 --- a/packages/polywrap-uri-resolvers/pyproject.toml +++ b/packages/polywrap-uri-resolvers/pyproject.toml @@ -13,7 +13,12 @@ readme = "README.md" python = "^3.10" polywrap-wasm = {path = "../polywrap-wasm", develop = true} polywrap-core = {path = "../polywrap-core", develop = true} -[tool.poetry.dev-dependencies] + +[tool.poetry.group.dev.dependencies] +pycln = "^2.1.3" +polywrap-client = {path = "../polywrap-client", develop = true} +polywrap-plugin = {path = "../polywrap-plugin", develop = true} +polywrap-test-cases = {path = "../polywrap-test-cases", develop = true} pytest = "^7.1.2" pytest-asyncio = "^0.19.0" pylint = "^2.15.4" @@ -24,9 +29,7 @@ tox-poetry = "^0.4.1" isort = "^5.10.1" pyright = "^1.1.275" pydocstyle = "^6.1.1" - -[tool.poetry.group.dev.dependencies] -pycln = "^2.1.3" +pytest-html = "^3.2.0" [tool.bandit] exclude_dirs = ["tests"] diff --git a/packages/polywrap-uri-resolvers/tests/__init__.py b/packages/polywrap-uri-resolvers/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/conftest.py b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/conftest.py new file mode 100644 index 00000000..37f75ff8 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/conftest.py @@ -0,0 +1,18 @@ +import pytest +from polywrap_core import Uri, UriResolutionContext, ClientConfig +from polywrap_client import PolywrapClient +from polywrap_uri_resolvers import UriResolverAggregator, RedirectResolver + +@pytest.fixture +def client() -> PolywrapClient: + resolver = UriResolverAggregator([ + RedirectResolver(Uri.from_str("test/1"), Uri.from_str("test/2")), + RedirectResolver(Uri.from_str("test/2"), Uri.from_str("test/3")), + RedirectResolver(Uri.from_str("test/3"), Uri.from_str("test/4")), + ], "TestAggregator") + return PolywrapClient(ClientConfig(resolver=resolver)) + +@pytest.fixture +def resolution_context() -> UriResolutionContext: + return UriResolutionContext() + diff --git a/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/histories/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/histories/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/histories/can_resolve_first.py b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/histories/can_resolve_first.py new file mode 100644 index 00000000..71edc200 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/histories/can_resolve_first.py @@ -0,0 +1,6 @@ +EXPECTED = [ + "wrap://test/1 => TestAggregator => uri (wrap://test/2)", + [ + "wrap://test/1 => Redirect (wrap://test/1 - wrap://test/2) => uri (wrap://test/2)", + ] +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/histories/can_resolve_last.py b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/histories/can_resolve_last.py new file mode 100644 index 00000000..0ecc3af6 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/histories/can_resolve_last.py @@ -0,0 +1,8 @@ +EXPECTED = [ + "wrap://test/3 => TestAggregator => uri (wrap://test/4)", + [ + "wrap://test/3 => Redirect (wrap://test/1 - wrap://test/2)", + "wrap://test/3 => Redirect (wrap://test/2 - wrap://test/3)", + "wrap://test/3 => Redirect (wrap://test/3 - wrap://test/4) => uri (wrap://test/4)", + ] +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/histories/not_resolve.py b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/histories/not_resolve.py new file mode 100644 index 00000000..aa408c4e --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/histories/not_resolve.py @@ -0,0 +1,8 @@ +EXPECTED = [ + "wrap://test/no-match => TestAggregator", + [ + "wrap://test/no-match => Redirect (wrap://test/1 - wrap://test/2)", + "wrap://test/no-match => Redirect (wrap://test/2 - wrap://test/3)", + "wrap://test/no-match => Redirect (wrap://test/3 - wrap://test/4)", + ] +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/test_can_resolve.py b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/test_can_resolve.py new file mode 100644 index 00000000..9cfd6ee3 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/test_can_resolve.py @@ -0,0 +1,28 @@ +from polywrap_core import Uri, UriResolutionContext, build_clean_uri_history +from polywrap_client import PolywrapClient + + +def test_can_resolve_first(client: PolywrapClient, resolution_context: UriResolutionContext) -> None: + uri = Uri.from_str("test/1") + + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.can_resolve_first import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, Uri), "Expected a Uri result." + assert result.uri == "wrap://test/2" + + +def test_can_resolve_last(client: PolywrapClient, resolution_context: UriResolutionContext) -> None: + uri = Uri.from_str("test/3") + + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + print(build_clean_uri_history(resolution_context.get_history())) + + from .histories.can_resolve_last import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, Uri), "Expected a Uri result." + assert result.uri == "wrap://test/4" diff --git a/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/test_not_resolve.py b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/test_not_resolve.py new file mode 100644 index 00000000..4e9ff210 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/aggregator_resolver/test_not_resolve.py @@ -0,0 +1,15 @@ +from polywrap_core import Uri, UriResolutionContext, build_clean_uri_history +from polywrap_client import PolywrapClient + + +def test_no_match(client: PolywrapClient, resolution_context: UriResolutionContext) -> None: + uri = Uri.from_str("test/no-match") + + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.not_resolve import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, Uri), "Expected a Uri result." + assert result.uri == "wrap://test/no-match" + diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_resolve_package.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_resolve_package.py new file mode 100644 index 00000000..51b2d6bf --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_resolve_package.py @@ -0,0 +1,20 @@ +EXPECTED = [ + "wrap://test/package => UriResolverAggregator => package (wrap://test/package)", + [ + "wrap://test/package => Static - Miss", + "wrap://test/package => ExtendableUriResolver => package (wrap://test/package)", + [ + "wrap://test/package => ResolverExtension (wrap://package/test-resolver) => package (wrap://test/package)", + [ + "wrap://package/test-resolver => Client.load_wrapper => wrapper (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => UriResolverAggregator => package (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => Static - Package => package (wrap://package/test-resolver)" + ], + ], + "wrap://package/test-resolver => Wrapper.invoke", + ], + ], + ], +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_resolve_package_with_subinvoke.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_resolve_package_with_subinvoke.py new file mode 100644 index 00000000..0ff4c663 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_resolve_package_with_subinvoke.py @@ -0,0 +1,30 @@ +EXPECTED = [ + "wrap://test/package => UriResolverAggregator => package (wrap://test/package)", + [ + "wrap://test/package => Static - Miss", + "wrap://test/package => ExtendableUriResolver => package (wrap://test/package)", + [ + "wrap://test/package => ResolverExtension (wrap://package/test-subinvoke-resolver) => package (wrap://test/package)", + [ + "wrap://package/test-subinvoke-resolver => Client.load_wrapper => wrapper (wrap://package/test-subinvoke-resolver)", + [ + "wrap://package/test-subinvoke-resolver => UriResolverAggregator => package (wrap://package/test-subinvoke-resolver)", + [ + "wrap://package/test-subinvoke-resolver => Static - Package => package (wrap://package/test-subinvoke-resolver)" + ], + ], + "wrap://package/test-subinvoke-resolver => Wrapper.invoke", + [ + "wrap://package/test-resolver => Client.load_wrapper => wrapper (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => UriResolverAggregator => package (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => Static - Package => package (wrap://package/test-resolver)" + ], + ], + "wrap://package/test-resolver => Wrapper.invoke", + ], + ], + ], + ], +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_resolve_uri.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_resolve_uri.py new file mode 100644 index 00000000..ab794c14 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_resolve_uri.py @@ -0,0 +1,38 @@ +EXPECTED = [ + "wrap://test/from => UriResolverAggregator => uri (wrap://test/to)", + [ + "wrap://test/from => Package (wrap://package/test-resolver)", + "wrap://test/from => ExtendableUriResolver => uri (wrap://test/to)", + [ + "wrap://test/from => ResolverExtension (wrap://package/test-resolver) => uri (wrap://test/to)", + [ + "wrap://package/test-resolver => Client.load_wrapper => wrapper (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => UriResolverAggregator => package (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => Package (wrap://package/test-resolver) => package (wrap://package/test-resolver)" + ], + ], + "wrap://package/test-resolver => Wrapper.invoke", + ], + ], + ], + "wrap://test/to => UriResolverAggregator", + [ + "wrap://test/to => Package (wrap://package/test-resolver)", + "wrap://test/to => ExtendableUriResolver", + [ + "wrap://test/to => ResolverExtension (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => Client.load_wrapper => wrapper (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => UriResolverAggregator => package (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => Package (wrap://package/test-resolver) => package (wrap://package/test-resolver)" + ], + ], + "wrap://package/test-resolver => Wrapper.invoke", + ], + ], + ], +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_resolve_uri_with_subinvoke.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_resolve_uri_with_subinvoke.py new file mode 100644 index 00000000..20900ae1 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_resolve_uri_with_subinvoke.py @@ -0,0 +1,62 @@ +EXPECTED = [ + "wrap://test/from => UriResolverAggregator => uri (wrap://test/to)", + [ + "wrap://test/from => Package (wrap://package/test-subinvoke-resolver)", + "wrap://test/from => Package (wrap://package/test-resolver)", + "wrap://test/from => ExtendableUriResolver => uri (wrap://test/to)", + [ + "wrap://test/from => ResolverExtension (wrap://package/test-subinvoke-resolver) => uri (wrap://test/to)", + [ + "wrap://package/test-subinvoke-resolver => Client.load_wrapper => wrapper (wrap://package/test-subinvoke-resolver)", + [ + "wrap://package/test-subinvoke-resolver => UriResolverAggregator => package (wrap://package/test-subinvoke-resolver)", + [ + "wrap://package/test-subinvoke-resolver => Package (wrap://package/test-subinvoke-resolver) => package (wrap://package/test-subinvoke-resolver)" + ], + ], + "wrap://package/test-subinvoke-resolver => Wrapper.invoke", + [ + "wrap://package/test-resolver => Client.load_wrapper => wrapper (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => UriResolverAggregator => package (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => Package (wrap://package/test-subinvoke-resolver)", + "wrap://package/test-resolver => Package (wrap://package/test-resolver) => package (wrap://package/test-resolver)", + ], + ], + "wrap://package/test-resolver => Wrapper.invoke", + ], + ], + ], + ], + "wrap://test/to => UriResolverAggregator", + [ + "wrap://test/to => Package (wrap://package/test-subinvoke-resolver)", + "wrap://test/to => Package (wrap://package/test-resolver)", + "wrap://test/to => ExtendableUriResolver", + [ + "wrap://test/to => ResolverExtension (wrap://package/test-subinvoke-resolver)", + [ + "wrap://package/test-subinvoke-resolver => Client.load_wrapper => wrapper (wrap://package/test-subinvoke-resolver)", + [ + "wrap://package/test-subinvoke-resolver => UriResolverAggregator => package (wrap://package/test-subinvoke-resolver)", + [ + "wrap://package/test-subinvoke-resolver => Package (wrap://package/test-subinvoke-resolver) => package (wrap://package/test-subinvoke-resolver)" + ], + ], + "wrap://package/test-subinvoke-resolver => Wrapper.invoke", + [ + "wrap://package/test-resolver => Client.load_wrapper => wrapper (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => UriResolverAggregator => package (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => Package (wrap://package/test-subinvoke-resolver)", + "wrap://package/test-resolver => Package (wrap://package/test-resolver) => package (wrap://package/test-resolver)", + ], + ], + "wrap://package/test-resolver => Wrapper.invoke", + ], + ], + ], + ], +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_use_wasm_fs_resolver.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_use_wasm_fs_resolver.py new file mode 100644 index 00000000..4cadedbf --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/can_use_wasm_fs_resolver.py @@ -0,0 +1,30 @@ +import os +from polywrap_core import Uri +from polywrap_test_cases import get_path_to_test_wrappers + + +source_uri = Uri( + "fs", + os.path.join(get_path_to_test_wrappers(), "asyncify", "implementations", "as"), +) + +EXPECTED = [ + f"{source_uri} => UriResolverAggregator", + [ + f"{source_uri} => Package (wrap://package/test-fs-resolver)", + f"{source_uri} => ExtendableUriResolver", + [ + f"{source_uri} => ResolverExtension (wrap://package/test-fs-resolver)", + [ + "wrap://package/test-fs-resolver => Client.load_wrapper => wrapper (wrap://package/test-fs-resolver)", + [ + "wrap://package/test-fs-resolver => UriResolverAggregator => package (wrap://package/test-fs-resolver)", + [ + "wrap://package/test-fs-resolver => Package (wrap://package/test-fs-resolver) => package (wrap://package/test-fs-resolver)" + ], + ], + "wrap://package/test-fs-resolver => Wrapper.invoke", + ], + ], + ], +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/not_a_match.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/not_a_match.py new file mode 100644 index 00000000..57e6465c --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/not_a_match.py @@ -0,0 +1,20 @@ +EXPECTED = [ + "wrap://test/not-a-match => UriResolverAggregator", + [ + "wrap://test/not-a-match => Static - Miss", + "wrap://test/not-a-match => ExtendableUriResolver", + [ + "wrap://test/not-a-match => ResolverExtension (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => Client.load_wrapper => wrapper (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => UriResolverAggregator => package (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => Static - Package => package (wrap://package/test-resolver)" + ], + ], + "wrap://package/test-resolver => Wrapper.invoke", + ], + ], + ], +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/not_a_match_with_subinvoke.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/not_a_match_with_subinvoke.py new file mode 100644 index 00000000..81d2bd56 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/not_a_match_with_subinvoke.py @@ -0,0 +1,30 @@ +EXPECTED = [ + "wrap://test/not-a-match => UriResolverAggregator", + [ + "wrap://test/not-a-match => Static - Miss", + "wrap://test/not-a-match => ExtendableUriResolver", + [ + "wrap://test/not-a-match => ResolverExtension (wrap://package/test-subinvoke-resolver)", + [ + "wrap://package/test-subinvoke-resolver => Client.load_wrapper => wrapper (wrap://package/test-subinvoke-resolver)", + [ + "wrap://package/test-subinvoke-resolver => UriResolverAggregator => package (wrap://package/test-subinvoke-resolver)", + [ + "wrap://package/test-subinvoke-resolver => Static - Package => package (wrap://package/test-subinvoke-resolver)" + ], + ], + "wrap://package/test-subinvoke-resolver => Wrapper.invoke", + [ + "wrap://package/test-resolver => Client.load_wrapper => wrapper (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => UriResolverAggregator => package (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => Static - Package => package (wrap://package/test-resolver)" + ], + ], + "wrap://package/test-resolver => Wrapper.invoke", + ], + ], + ], + ], +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/not_found_extension.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/not_found_extension.py new file mode 100644 index 00000000..22dcd12b --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/not_found_extension.py @@ -0,0 +1,13 @@ +EXPECTED = [ + 'wrap://test/not-a-match => UriResolverAggregator => error (Unable to find URI wrap://test/undefined-resolver.\ncode: 28 URI NOT FOUND\nuri: wrap://test/undefined-resolver\nuriResolutionStack: [\n "wrap://test/undefined-resolver => UriResolverAggregator"\n])', + [ + 'wrap://test/not-a-match => ExtendableUriResolver => error (Unable to find URI wrap://test/undefined-resolver.\ncode: 28 URI NOT FOUND\nuri: wrap://test/undefined-resolver\nuriResolutionStack: [\n "wrap://test/undefined-resolver => UriResolverAggregator"\n])', + [ + 'wrap://test/not-a-match => ResolverExtension (wrap://test/undefined-resolver) => error (Unable to find URI wrap://test/undefined-resolver.\ncode: 28 URI NOT FOUND\nuri: wrap://test/undefined-resolver\nuriResolutionStack: [\n "wrap://test/undefined-resolver => UriResolverAggregator"\n])', + [ + 'wrap://test/undefined-resolver => Client.loadWrapper => error (Unable to find URI wrap://test/undefined-resolver.\ncode: 28 URI NOT FOUND\nuri: wrap://test/undefined-resolver\nuriResolutionStack: [\n "wrap://test/undefined-resolver => UriResolverAggregator"\n])', + ["wrap://test/undefined-resolver => UriResolverAggregator"], + ], + ], + ], +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/shows_plugin_extension_error.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/shows_plugin_extension_error.py new file mode 100644 index 00000000..6dd11d75 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/shows_plugin_extension_error.py @@ -0,0 +1,20 @@ +EXPECTED = [ + 'wrap://test/error => UriResolverAggregator => error (Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} )', + [ + "wrap://test/error => StaticResolver - Miss", + 'wrap://test/error => ExtendableUriResolver => error (Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} )', + [ + 'wrap://test/error => ResolverExtension (wrap://package/test-resolver) => error (Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} )', + [ + "wrap://package/test-resolver => Client.loadWrapper => wrapper (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => UriResolverAggregator => package (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => StaticResolver - Package (wrap://package/test-resolver) => package (wrap://package/test-resolver)" + ], + ], + 'wrap://package/test-resolver => Client.invokeWrapper => error (Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} )', + ], + ], + ], +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/shows_plugin_extension_error_with_subinvoke.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/shows_plugin_extension_error_with_subinvoke.py new file mode 100644 index 00000000..f6451065 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/shows_plugin_extension_error_with_subinvoke.py @@ -0,0 +1,30 @@ +EXPECTED = [ + 'wrap://test/error => UriResolverAggregator => error (__wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { , row: 35, col: 21 }\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/subinvoke-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { , row: 177, col: 15 })', + [ + "wrap://test/error => StaticResolver - Miss", + 'wrap://test/error => ExtendableUriResolver => error (__wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { , row: 35, col: 21 }\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/subinvoke-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { , row: 177, col: 15 })', + [ + 'wrap://test/error => ResolverExtension (wrap://package/subinvoke-resolver) => error (__wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { , row: 35, col: 21 }\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/subinvoke-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { , row: 177, col: 15 })', + [ + "wrap://package/subinvoke-resolver => Client.loadWrapper => wrapper (wrap://package/subinvoke-resolver)", + [ + "wrap://package/subinvoke-resolver => UriResolverAggregator => package (wrap://package/subinvoke-resolver)", + [ + "wrap://package/subinvoke-resolver => StaticResolver - Package (wrap://package/subinvoke-resolver) => package (wrap://package/subinvoke-resolver)" + ], + ], + 'wrap://package/subinvoke-resolver => Client.invokeWrapper => error (__wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { , row: 35, col: 21 }\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/subinvoke-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { , row: 177, col: 15 })', + [ + "wrap://package/test-resolver => Client.loadWrapper => wrapper (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => UriResolverAggregator => package (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => StaticResolver - Package (wrap://package/test-resolver) => package (wrap://package/test-resolver)" + ], + ], + 'wrap://package/test-resolver => Client.invokeWrapper => error (__wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { , row: 35, col: 21 })', + ], + ], + ], + ], +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/shows_wasm_extension_error.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/shows_wasm_extension_error.py new file mode 100644 index 00000000..e2eb9107 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/shows_wasm_extension_error.py @@ -0,0 +1,20 @@ +EXPECTED = [ + 'wrap://test/error => UriResolverAggregator => error (__wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { file: "src/wrap/module/wrapped.rs", row: 35, col: 21 })', + [ + "wrap://test/error => StaticResolver - Miss", + 'wrap://test/error => ExtendableUriResolver => error (__wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { file: "src/wrap/module/wrapped.rs", row: 35, col: 21 })', + [ + 'wrap://test/error => ResolverExtension (wrap://package/test-resolver) => error (__wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { file: "src/wrap/module/wrapped.rs", row: 35, col: 21 })', + [ + "wrap://package/test-resolver => Client.loadWrapper => wrapper (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => UriResolverAggregator => package (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => StaticResolver - Package (wrap://package/test-resolver) => package (wrap://package/test-resolver)" + ], + ], + 'wrap://package/test-resolver => Client.invokeWrapper => error (__wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { file: "src/wrap/module/wrapped.rs", row: 35, col: 21 })', + ], + ], + ], +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/shows_wasm_extension_error_with_subinvoke.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/shows_wasm_extension_error_with_subinvoke.py new file mode 100644 index 00000000..cdd2b285 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/histories/shows_wasm_extension_error_with_subinvoke.py @@ -0,0 +1,30 @@ +EXPECTED = [ + 'wrap://test/error => UriResolverAggregator => error (SubInvocation exception encountered\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/subinvoke-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { file: "src/wrap/module/wrapped.rs", row: 35, col: 21 }\n\nAnother exception was encountered during execution:\nWrapError: __wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { file: "src/wrap/module/wrapped.rs", row: 35, col: 21 })', + [ + "wrap://test/error => StaticResolver - Miss", + 'wrap://test/error => ExtendableUriResolver => error (SubInvocation exception encountered\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/subinvoke-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { file: "src/wrap/module/wrapped.rs", row: 35, col: 21 }\n\nAnother exception was encountered during execution:\nWrapError: __wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { file: "src/wrap/module/wrapped.rs", row: 35, col: 21 })', + [ + 'wrap://test/error => ResolverExtension (wrap://package/subinvoke-resolver) => error (SubInvocation exception encountered\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/subinvoke-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { file: "src/wrap/module/wrapped.rs", row: 35, col: 21 }\n\nAnother exception was encountered during execution:\nWrapError: __wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { file: "src/wrap/module/wrapped.rs", row: 35, col: 21 })', + [ + "wrap://package/subinvoke-resolver => Client.loadWrapper => wrapper (wrap://package/subinvoke-resolver)", + [ + "wrap://package/subinvoke-resolver => UriResolverAggregator => package (wrap://package/subinvoke-resolver)", + [ + "wrap://package/subinvoke-resolver => StaticResolver - Package (wrap://package/subinvoke-resolver) => package (wrap://package/subinvoke-resolver)" + ], + ], + 'wrap://package/subinvoke-resolver => Client.invokeWrapper => error (SubInvocation exception encountered\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/subinvoke-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { file: "src/wrap/module/wrapped.rs", row: 35, col: 21 }\n\nAnother exception was encountered during execution:\nWrapError: __wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { file: "src/wrap/module/wrapped.rs", row: 35, col: 21 })', + [ + "wrap://package/test-resolver => Client.loadWrapper => wrapper (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => UriResolverAggregator => package (wrap://package/test-resolver)", + [ + "wrap://package/test-resolver => StaticResolver - Package (wrap://package/test-resolver) => package (wrap://package/test-resolver)" + ], + ], + 'wrap://package/test-resolver => Client.invokeWrapper => error (__wrap_abort: Test error\ncode: 51 WRAPPER INVOKE ABORTED\nuri: wrap://package/test-resolver\nmethod: tryResolveUri\nargs: {\n "authority": "test",\n "path": "error"\n} \nsource: { file: "src/wrap/module/wrapped.rs", row: 35, col: 21 })', + ], + ], + ], + ], +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/mocker.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/mocker.py new file mode 100644 index 00000000..6108f930 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/mocker.py @@ -0,0 +1,71 @@ +import os +from typing import Dict, Optional +from polywrap_core import Any, InvokerClient, Uri, UriPackage +from polywrap_plugin import PluginModule, PluginPackage +from polywrap_uri_resolvers import ( + MaybeUriOrManifest, + WasmPackage, +) +from polywrap_test_cases import get_path_to_test_wrappers + + +class MockPluginExtensionResolver(PluginModule[None]): + URI = Uri.from_str("wrap://package/test-resolver") + + def __init__(self): + super().__init__(None) + + def tryResolveUri( + self, args: Dict[str, Any], *_: Any + ) -> Optional[MaybeUriOrManifest]: + if args.get("authority") != "test": + return None + + match args.get("path"): + case "from": + return {"uri": Uri.from_str("test/to").uri} + case "package": + return {"manifest": b"test"} + case "error": + raise ValueError("test error") + case _: + return None + + +def mock_plugin_extension_resolver(): + return PluginPackage(MockPluginExtensionResolver(), NotImplemented) + + +class MockSubinvokePluginResolver(PluginModule[None]): + URI = Uri.from_str("wrap://package/test-subinvoke-resolver") + + def __init__(self): + super().__init__(None) + + def tryResolveUri( + self, args: Dict[str, Any], client: InvokerClient, *_: Any + ) -> Optional[MaybeUriOrManifest]: + return client.invoke( + uri=Uri.from_str("package/test-resolver"), method="tryResolveUri", args=args + ) + + +def mock_subinvoke_plugin_resolver() -> PluginPackage[None]: + return PluginPackage(MockSubinvokePluginResolver(), NotImplemented) + + +def mock_fs_wasm_package_resolver() -> UriPackage: + wrapper_module_path = os.path.join( + get_path_to_test_wrappers(), "resolver", "02-fs", "implementations", "as", "wrap.wasm" + ) + wrapper_manifest_path = os.path.join( + get_path_to_test_wrappers(), "resolver", "02-fs", "implementations", "as", "wrap.info" + ) + with open(wrapper_module_path, "rb") as f: + module = f.read() + + with open(wrapper_manifest_path, "rb") as f: + manifest = f.read() + + package = WasmPackage(NotImplemented, manifest=manifest, wasm_module=module) + return UriPackage(uri=Uri.from_str("package/test-fs-resolver"),package=package) diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_can_resolve_package.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_can_resolve_package.py new file mode 100644 index 00000000..dfc439e0 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_can_resolve_package.py @@ -0,0 +1,60 @@ +from polywrap_client import PolywrapClient +from polywrap_core import ( + ClientConfig, + Uri, + UriPackage, + UriResolutionContext, + build_clean_uri_history, +) +from polywrap_uri_resolvers import ( + ExtendableUriResolver, + RecursiveResolver, + StaticResolver, + UriResolverAggregator, +) +import pytest + +from .mocker import mock_plugin_extension_resolver, MockPluginExtensionResolver + + +@pytest.fixture +def client() -> PolywrapClient: + resolver = RecursiveResolver( + UriResolverAggregator( + [ + StaticResolver( + { + MockPluginExtensionResolver.URI: UriPackage( + uri=MockPluginExtensionResolver.URI, + package=mock_plugin_extension_resolver(), + ) + } + ), + ExtendableUriResolver(), + ] + ) + ) + return PolywrapClient( + ClientConfig( + resolver=resolver, + interfaces={ + ExtendableUriResolver.DEFAULT_EXT_INTERFACE_URIS[0]: [ + MockPluginExtensionResolver.URI + ] + }, + ) + ) + + +def test_can_resolve_package_with_plugin_extension(client: PolywrapClient) -> None: + resolution_context = UriResolutionContext() + source_uri = Uri.from_str("test/package") + + result = client.try_resolve_uri( + uri=source_uri, resolution_context=resolution_context + ) + + from .histories.can_resolve_package import EXPECTED + + assert isinstance(result, UriPackage), "Expected a UriPackage result." + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_can_resolve_package_with_subinvoke.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_can_resolve_package_with_subinvoke.py new file mode 100644 index 00000000..692c8862 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_can_resolve_package_with_subinvoke.py @@ -0,0 +1,64 @@ +from polywrap_client import PolywrapClient +from polywrap_core import ( + ClientConfig, + Uri, + UriPackage, + UriResolutionContext, + build_clean_uri_history, +) +from polywrap_uri_resolvers import ( + ExtendableUriResolver, + RecursiveResolver, + StaticResolver, + UriResolverAggregator, +) +import pytest + +from .mocker import mock_subinvoke_plugin_resolver, mock_plugin_extension_resolver, MockPluginExtensionResolver, MockSubinvokePluginResolver + + +@pytest.fixture +def client() -> PolywrapClient: + resolver = RecursiveResolver( + UriResolverAggregator( + [ + StaticResolver( + { + MockPluginExtensionResolver.URI: UriPackage( + uri=MockPluginExtensionResolver.URI, + package=mock_plugin_extension_resolver(), + ), + MockSubinvokePluginResolver.URI: UriPackage( + uri=MockSubinvokePluginResolver.URI, + package=mock_subinvoke_plugin_resolver(), + ), + } + ), + ExtendableUriResolver(), + ] + ) + ) + return PolywrapClient( + ClientConfig( + resolver=resolver, + interfaces={ + ExtendableUriResolver.DEFAULT_EXT_INTERFACE_URIS[0]: [ + MockSubinvokePluginResolver.URI + ] + }, + ) + ) + + +def test_can_resolve_package_with_plugin_extension(client: PolywrapClient) -> None: + resolution_context = UriResolutionContext() + source_uri = Uri.from_str("test/package") + + result = client.try_resolve_uri( + uri=source_uri, resolution_context=resolution_context + ) + + from .histories.can_resolve_package_with_subinvoke import EXPECTED + print(build_clean_uri_history(resolution_context.get_history())) + assert isinstance(result, UriPackage), "Expected a UriPackage result." + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_can_resolve_uri.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_can_resolve_uri.py new file mode 100644 index 00000000..18d28e72 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_can_resolve_uri.py @@ -0,0 +1,56 @@ +from polywrap_client import PolywrapClient +from polywrap_core import ( + ClientConfig, + Uri, + UriResolutionContext, + build_clean_uri_history, +) +from polywrap_uri_resolvers import ( + ExtendableUriResolver, + RecursiveResolver, + UriResolverAggregator, + PackageResolver, +) +import pytest + +from .mocker import mock_plugin_extension_resolver, MockPluginExtensionResolver + + +@pytest.fixture +def client() -> PolywrapClient: + resolver = RecursiveResolver( + UriResolverAggregator( + [ + PackageResolver( + MockPluginExtensionResolver.URI, + mock_plugin_extension_resolver(), + ), + ExtendableUriResolver(), + ] + ) + ) + return PolywrapClient( + ClientConfig( + resolver=resolver, + interfaces={ + ExtendableUriResolver.DEFAULT_EXT_INTERFACE_URIS[0]: [ + MockPluginExtensionResolver.URI + ] + }, + ) + ) + + +def test_can_resolve_uri_with_plugin_extension(client: PolywrapClient) -> None: + resolution_context = UriResolutionContext() + source_uri = Uri.from_str("test/from") + redirected_uri = Uri.from_str("test/to") + + result = client.try_resolve_uri( + uri=source_uri, resolution_context=resolution_context + ) + + from .histories.can_resolve_uri import EXPECTED + assert isinstance(result, Uri), "Expected a Uri result." + assert result == redirected_uri + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_can_resolve_uri_with_subinvoke.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_can_resolve_uri_with_subinvoke.py new file mode 100644 index 00000000..bc57abb0 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_can_resolve_uri_with_subinvoke.py @@ -0,0 +1,60 @@ +from polywrap_client import PolywrapClient +from polywrap_core import ( + ClientConfig, + Uri, + UriResolutionContext, + build_clean_uri_history, +) +from polywrap_uri_resolvers import ( + ExtendableUriResolver, + RecursiveResolver, + UriResolverAggregator, + PackageResolver, +) +import pytest + +from .mocker import mock_subinvoke_plugin_resolver, mock_plugin_extension_resolver, MockPluginExtensionResolver, MockSubinvokePluginResolver + + +@pytest.fixture +def client() -> PolywrapClient: + resolver = RecursiveResolver( + UriResolverAggregator( + [ + PackageResolver( + MockSubinvokePluginResolver.URI, + mock_subinvoke_plugin_resolver(), + ), + PackageResolver( + MockPluginExtensionResolver.URI, + mock_plugin_extension_resolver(), + ), + ExtendableUriResolver(), + ] + ) + ) + return PolywrapClient( + ClientConfig( + resolver=resolver, + interfaces={ + ExtendableUriResolver.DEFAULT_EXT_INTERFACE_URIS[0]: [ + MockSubinvokePluginResolver.URI + ] + }, + ) + ) + + +def test_can_resolve_uri_with_plugin_extension(client: PolywrapClient) -> None: + resolution_context = UriResolutionContext() + source_uri = Uri.from_str("test/from") + redirected_uri = Uri.from_str("test/to") + + result = client.try_resolve_uri( + uri=source_uri, resolution_context=resolution_context + ) + + from .histories.can_resolve_uri_with_subinvoke import EXPECTED + assert isinstance(result, Uri), "Expected a Uri result." + assert result == redirected_uri + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_not_a_match.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_not_a_match.py new file mode 100644 index 00000000..fd1a124f --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_not_a_match.py @@ -0,0 +1,59 @@ +from polywrap_client import PolywrapClient +from polywrap_core import ( + ClientConfig, + Uri, + UriPackage, + UriResolutionContext, + build_clean_uri_history, +) +from polywrap_uri_resolvers import ( + ExtendableUriResolver, + RecursiveResolver, + StaticResolver, + UriResolverAggregator, +) +import pytest + +from .mocker import mock_plugin_extension_resolver, MockPluginExtensionResolver + + +@pytest.fixture +def client() -> PolywrapClient: + resolver = RecursiveResolver( + UriResolverAggregator( + [ + StaticResolver( + { + MockPluginExtensionResolver.URI: UriPackage( + uri=MockPluginExtensionResolver.URI, + package=mock_plugin_extension_resolver(), + ) + } + ), + ExtendableUriResolver(), + ] + ) + ) + return PolywrapClient( + ClientConfig( + resolver=resolver, + interfaces={ + ExtendableUriResolver.DEFAULT_EXT_INTERFACE_URIS[0]: [ + MockPluginExtensionResolver.URI + ] + }, + ) + ) + + +def test_can_resolve_uri_with_plugin_extension(client: PolywrapClient) -> None: + resolution_context = UriResolutionContext() + source_uri = Uri.from_str("test/not-a-match") + + result = client.try_resolve_uri( + uri=source_uri, resolution_context=resolution_context + ) + + from .histories.not_a_match import EXPECTED + assert isinstance(result, Uri), "Expected a Uri result." + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_not_a_match_with_subinvoke.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_not_a_match_with_subinvoke.py new file mode 100644 index 00000000..c05c6c5c --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_not_a_match_with_subinvoke.py @@ -0,0 +1,65 @@ +from polywrap_client import PolywrapClient +from polywrap_core import ( + ClientConfig, + Uri, + UriPackage, + UriResolutionContext, + build_clean_uri_history, +) +from polywrap_uri_resolvers import ( + ExtendableUriResolver, + RecursiveResolver, + StaticResolver, + UriResolverAggregator, +) +import pytest + +from .mocker import MockSubinvokePluginResolver, mock_plugin_extension_resolver, MockPluginExtensionResolver, mock_subinvoke_plugin_resolver + + + +@pytest.fixture +def client() -> PolywrapClient: + resolver = RecursiveResolver( + UriResolverAggregator( + [ + StaticResolver( + { + MockPluginExtensionResolver.URI: UriPackage( + uri=MockPluginExtensionResolver.URI, + package=mock_plugin_extension_resolver(), + ), + MockSubinvokePluginResolver.URI: UriPackage( + uri=MockSubinvokePluginResolver.URI, + package=mock_subinvoke_plugin_resolver(), + ), + } + ), + ExtendableUriResolver(), + ] + ) + ) + return PolywrapClient( + ClientConfig( + resolver=resolver, + interfaces={ + ExtendableUriResolver.DEFAULT_EXT_INTERFACE_URIS[0]: [ + MockSubinvokePluginResolver.URI + ] + }, + ) + ) + + + +def test_can_resolve_uri_with_plugin_extension(client: PolywrapClient) -> None: + resolution_context = UriResolutionContext() + source_uri = Uri.from_str("test/not-a-match") + + result = client.try_resolve_uri( + uri=source_uri, resolution_context=resolution_context + ) + + from .histories.not_a_match_with_subinvoke import EXPECTED + assert isinstance(result, Uri), "Expected a Uri result." + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_not_found_extension.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_not_found_extension.py new file mode 100644 index 00000000..a456870d --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_not_found_extension.py @@ -0,0 +1,44 @@ +from polywrap_client import PolywrapClient +from polywrap_core import ( + ClientConfig, + Uri, + UriResolutionContext, +) +from polywrap_uri_resolvers import ( + ExtendableUriResolver, + RecursiveResolver, + UriResolverAggregator, + UriResolverExtensionNotFoundError, +) +import pytest + + +@pytest.fixture +def client() -> PolywrapClient: + resolver = RecursiveResolver( + UriResolverAggregator( + [ + ExtendableUriResolver(), + ] + ) + ) + return PolywrapClient( + ClientConfig( + resolver=resolver, + interfaces={ + ExtendableUriResolver.DEFAULT_EXT_INTERFACE_URIS[0]: [ + Uri.from_str("test/undefined-resolver") + ] + }, + ) + ) + + +def test_can_resolve_uri_with_plugin_extension(client: PolywrapClient) -> None: + resolution_context = UriResolutionContext() + source_uri = Uri.from_str("test/not-a-match") + + with pytest.raises(UriResolverExtensionNotFoundError): + client.try_resolve_uri( + uri=source_uri, resolution_context=resolution_context + ) diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_shows_plugin_extension_error.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_shows_plugin_extension_error.py new file mode 100644 index 00000000..7dcd60bf --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_shows_plugin_extension_error.py @@ -0,0 +1,59 @@ +from polywrap_client import PolywrapClient +from polywrap_core import ( + ClientConfig, + Uri, + UriPackage, + UriResolutionContext, +) +from polywrap_uri_resolvers import ( + ExtendableUriResolver, + RecursiveResolver, + StaticResolver, + UriResolverAggregator, + UriResolverExtensionError, +) +import pytest + +from .mocker import mock_plugin_extension_resolver, MockPluginExtensionResolver + + +@pytest.fixture +def client() -> PolywrapClient: + resolver = RecursiveResolver( + UriResolverAggregator( + [ + StaticResolver( + { + MockPluginExtensionResolver.URI: UriPackage( + uri=MockPluginExtensionResolver.URI, + package=mock_plugin_extension_resolver(), + ) + } + ), + ExtendableUriResolver(), + ] + ) + ) + return PolywrapClient( + ClientConfig( + resolver=resolver, + interfaces={ + ExtendableUriResolver.DEFAULT_EXT_INTERFACE_URIS[0]: [ + MockPluginExtensionResolver.URI + ] + }, + ) + ) + + +def test_shows_error_with_plugin_extension(client: PolywrapClient) -> None: + resolution_context = UriResolutionContext() + source_uri = Uri.from_str("test/error") + + with pytest.raises(UriResolverExtensionError) as excinfo: + client.try_resolve_uri(uri=source_uri, resolution_context=resolution_context) + + assert ( + excinfo.value.args[0] + == f"Failed to resolve uri: {source_uri}, using extension resolver: ({MockPluginExtensionResolver.URI})" + ) diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_shows_plugin_extension_error_with_subinvoke.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_shows_plugin_extension_error_with_subinvoke.py new file mode 100644 index 00000000..c11c6dc6 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_shows_plugin_extension_error_with_subinvoke.py @@ -0,0 +1,64 @@ +from polywrap_client import PolywrapClient +from polywrap_core import ( + ClientConfig, + Uri, + UriPackage, + UriResolutionContext, +) +from polywrap_uri_resolvers import ( + ExtendableUriResolver, + RecursiveResolver, + StaticResolver, + UriResolverAggregator, + UriResolverExtensionError, +) +import pytest + +from .mocker import mock_subinvoke_plugin_resolver, mock_plugin_extension_resolver, MockPluginExtensionResolver, MockSubinvokePluginResolver + + +@pytest.fixture +def client() -> PolywrapClient: + resolver = RecursiveResolver( + UriResolverAggregator( + [ + StaticResolver( + { + MockSubinvokePluginResolver.URI: UriPackage( + uri=MockSubinvokePluginResolver.URI, + package=mock_subinvoke_plugin_resolver(), + ), + MockPluginExtensionResolver.URI: UriPackage( + uri=MockPluginExtensionResolver.URI, + package=mock_plugin_extension_resolver(), + ), + } + ), + ExtendableUriResolver(), + ] + ) + ) + return PolywrapClient( + ClientConfig( + resolver=resolver, + interfaces={ + ExtendableUriResolver.DEFAULT_EXT_INTERFACE_URIS[0]: [ + MockSubinvokePluginResolver.URI + ] + }, + ) + ) + + + +def test_shows_error_with_plugin_extension_subinvoke(client: PolywrapClient) -> None: + resolution_context = UriResolutionContext() + source_uri = Uri.from_str("test/error") + + with pytest.raises(UriResolverExtensionError) as excinfo: + client.try_resolve_uri(uri=source_uri, resolution_context=resolution_context) + + assert ( + excinfo.value.args[0] + == f"Failed to resolve uri: {source_uri}, using extension resolver: ({MockSubinvokePluginResolver.URI})" + ) diff --git a/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_use_wasm_fs_resolver.py b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_use_wasm_fs_resolver.py new file mode 100644 index 00000000..923b7e1d --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/extension_resolver/test_use_wasm_fs_resolver.py @@ -0,0 +1,60 @@ +import os +from polywrap_client import PolywrapClient +from polywrap_core import ( + ClientConfig, + Uri, + UriResolutionContext, + build_clean_uri_history, +) +from polywrap_uri_resolvers import ( + ExtendableUriResolver, + RecursiveResolver, + UriResolverAggregator, + PackageResolver, +) +from polywrap_test_cases import get_path_to_test_wrappers +import pytest + +from .mocker import mock_fs_wasm_package_resolver + + +@pytest.fixture +def client() -> PolywrapClient: + uri_package = mock_fs_wasm_package_resolver() + resolver = RecursiveResolver( + UriResolverAggregator( + [ + PackageResolver( + uri_package.uri, + uri_package.package, + ), + ExtendableUriResolver(), + ] + ) + ) + return PolywrapClient( + ClientConfig( + resolver=resolver, + interfaces={ + ExtendableUriResolver.DEFAULT_EXT_INTERFACE_URIS[0]: [uri_package.uri] + }, + ) + ) + + +def test_can_use_wasm_fs_resolver(client: PolywrapClient) -> None: + resolution_context = UriResolutionContext() + source_uri = Uri( + "fs", + os.path.join(get_path_to_test_wrappers(), "asyncify", "implementations", "as"), + ) + + result = client.try_resolve_uri( + uri=source_uri, resolution_context=resolution_context + ) + + from .histories.can_use_wasm_fs_resolver import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + # Note: real wasm fs resolver should returns a UriPackage, not a Uri. + assert isinstance(result, Uri), "Expected a Uri result." \ No newline at end of file diff --git a/packages/polywrap-uri-resolvers/tests/integration/package_resolver/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/package_resolver/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/package_resolver/conftest.py b/packages/polywrap-uri-resolvers/tests/integration/package_resolver/conftest.py new file mode 100644 index 00000000..2c7c4342 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/package_resolver/conftest.py @@ -0,0 +1,14 @@ +import pytest +from polywrap_core import Uri, UriResolutionContext, ClientConfig +from polywrap_client import PolywrapClient +from polywrap_uri_resolvers import PackageResolver + +@pytest.fixture +def client() -> PolywrapClient: + resolver = PackageResolver(Uri.from_str("test/package"), NotImplemented) + return PolywrapClient(ClientConfig(resolver=resolver)) + +@pytest.fixture +def resolution_context() -> UriResolutionContext: + return UriResolutionContext() + diff --git a/packages/polywrap-uri-resolvers/tests/integration/package_resolver/histories/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/package_resolver/histories/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/package_resolver/histories/not_resolve_package.py b/packages/polywrap-uri-resolvers/tests/integration/package_resolver/histories/not_resolve_package.py new file mode 100644 index 00000000..b68a6d8d --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/package_resolver/histories/not_resolve_package.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/not-a-match => Package (wrap://test/package)" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/package_resolver/histories/resolve_package.py b/packages/polywrap-uri-resolvers/tests/integration/package_resolver/histories/resolve_package.py new file mode 100644 index 00000000..dea27dbe --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/package_resolver/histories/resolve_package.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/package => Package (wrap://test/package) => package (wrap://test/package)" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/package_resolver/test_not_resolve_package.py b/packages/polywrap-uri-resolvers/tests/integration/package_resolver/test_not_resolve_package.py new file mode 100644 index 00000000..e3e66a52 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/package_resolver/test_not_resolve_package.py @@ -0,0 +1,14 @@ +from polywrap_core import Uri, UriResolutionContext, build_clean_uri_history +from polywrap_client import PolywrapClient + + +def test_not_resolve_package(client: PolywrapClient, resolution_context: UriResolutionContext) -> None: + uri = Uri.from_str("test/not-a-match") + + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.not_resolve_package import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, Uri), "Expected a Uri result." + assert result.uri == "wrap://test/not-a-match" diff --git a/packages/polywrap-uri-resolvers/tests/integration/package_resolver/test_resolve_package.py b/packages/polywrap-uri-resolvers/tests/integration/package_resolver/test_resolve_package.py new file mode 100644 index 00000000..7f3d7830 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/package_resolver/test_resolve_package.py @@ -0,0 +1,15 @@ +from polywrap_core import Uri, UriResolutionContext, UriPackage, build_clean_uri_history +from polywrap_client import PolywrapClient + + + +def test_resolve_package(client: PolywrapClient, resolution_context: UriResolutionContext) -> None: + uri = Uri.from_str("test/package") + + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.resolve_package import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, UriPackage), "Expected a UriPackage result." + assert result.uri.uri == "wrap://test/package" diff --git a/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/conftest.py b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/conftest.py new file mode 100644 index 00000000..a120a5c1 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/conftest.py @@ -0,0 +1,46 @@ +import pytest +from polywrap_core import ( + ClientConfig, + InvokerClient, + Uri, + UriPackageOrWrapper, + UriResolutionContext, + UriResolutionStep, +) +from polywrap_client import PolywrapClient +from polywrap_uri_resolvers import RecursiveResolver + + +class SimpleRedirectResolver: + def try_resolve_uri( + self, uri: Uri, client: InvokerClient, resolution_context: UriResolutionContext + ) -> UriPackageOrWrapper: + result: UriPackageOrWrapper + + if uri.uri == "wrap://test/1": + result = Uri.from_str("test/2") + elif uri.uri == "wrap://test/2": + result = Uri.from_str("test/3") + elif uri.uri == "wrap://test/3": + result = Uri.from_str("test/4") + else: + result = uri + + resolution_context.track_step( + UriResolutionStep( + source_uri=uri, result=result, description="SimpleRedirectResolver" + ) + ) + + return result + + +@pytest.fixture +def simple_redirect_resolver() -> SimpleRedirectResolver: + return SimpleRedirectResolver() + + +@pytest.fixture +def client(simple_redirect_resolver: SimpleRedirectResolver) -> PolywrapClient: + resolver = RecursiveResolver(simple_redirect_resolver) + return PolywrapClient(ClientConfig(resolver=resolver)) diff --git a/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/histories/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/histories/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/histories/infinite_loop.py b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/histories/infinite_loop.py new file mode 100644 index 00000000..20e7be22 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/histories/infinite_loop.py @@ -0,0 +1,5 @@ +EXPECTED = [ + "wrap://test/1 => InfiniteRedirectResolver => uri (wrap://test/2)", + "wrap://test/2 => InfiniteRedirectResolver => uri (wrap://test/3)", + "wrap://test/3 => InfiniteRedirectResolver => uri (wrap://test/1)", +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/histories/no_resolve.py b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/histories/no_resolve.py new file mode 100644 index 00000000..98e9f8e0 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/histories/no_resolve.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/not-a-match => SimpleRedirectResolver" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/histories/recursive_resolve.py b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/histories/recursive_resolve.py new file mode 100644 index 00000000..508d0957 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/histories/recursive_resolve.py @@ -0,0 +1,6 @@ +EXPECTED = [ + "wrap://test/1 => SimpleRedirectResolver => uri (wrap://test/2)", + "wrap://test/2 => SimpleRedirectResolver => uri (wrap://test/3)", + "wrap://test/3 => SimpleRedirectResolver => uri (wrap://test/4)", + "wrap://test/4 => SimpleRedirectResolver" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/test_infinite_loop.py b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/test_infinite_loop.py new file mode 100644 index 00000000..51041075 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/test_infinite_loop.py @@ -0,0 +1,58 @@ +import pytest +from polywrap_core import ( + ClientConfig, + InvokerClient, + Uri, + UriPackageOrWrapper, + UriResolutionContext, + UriResolutionStep, + build_clean_uri_history, +) +from polywrap_client import PolywrapClient +from polywrap_uri_resolvers import RecursiveResolver, InfiniteLoopError + + +class InfiniteRedirectResolver: + def try_resolve_uri( + self, uri: Uri, client: InvokerClient, resolution_context: UriResolutionContext + ) -> UriPackageOrWrapper: + result: UriPackageOrWrapper + + if uri.uri == "wrap://test/1": + result = Uri.from_str("test/2") + elif uri.uri == "wrap://test/2": + result = Uri.from_str("test/3") + elif uri.uri == "wrap://test/3": + result = Uri.from_str("test/1") + else: + result = uri + + resolution_context.track_step( + UriResolutionStep( + source_uri=uri, result=result, description="InfiniteRedirectResolver" + ) + ) + + return result + + +@pytest.fixture +def infinite_redirect_resolver() -> InfiniteRedirectResolver: + return InfiniteRedirectResolver() + + +@pytest.fixture +def client(infinite_redirect_resolver: InfiniteRedirectResolver) -> PolywrapClient: + resolver = RecursiveResolver(infinite_redirect_resolver) + return PolywrapClient(ClientConfig(resolver=resolver)) + + +def test_infinite_loop(client: PolywrapClient): + uri = Uri.from_str("test/1") + resolution_context = UriResolutionContext() + + with pytest.raises(InfiniteLoopError) as excinfo: + client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + from .histories.infinite_loop import EXPECTED + assert excinfo.value.uri == uri + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED diff --git a/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/test_not_resolve.py b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/test_not_resolve.py new file mode 100644 index 00000000..ab503464 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/test_not_resolve.py @@ -0,0 +1,20 @@ +from polywrap_core import ( + Uri, + UriResolutionContext, + build_clean_uri_history +) +from polywrap_client import PolywrapClient + + +def test_not_resolve_uri(client: PolywrapClient) -> None: + uri = Uri.from_str("test/not-a-match") + + resolution_context = UriResolutionContext() + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + + from .histories.no_resolve import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, Uri), "Expected a Uri result." + assert result.uri == "wrap://test/not-a-match" diff --git a/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/test_recursive_resolve.py b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/test_recursive_resolve.py new file mode 100644 index 00000000..cf2fe82a --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/recursive_resolver/test_recursive_resolve.py @@ -0,0 +1,19 @@ +from polywrap_core import ( + Uri, + UriResolutionContext, + build_clean_uri_history +) +from polywrap_client import PolywrapClient + + +def test_recursive_resolve_uri(client: PolywrapClient) -> None: + uri = Uri.from_str("test/1") + + resolution_context = UriResolutionContext() + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.recursive_resolve import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, Uri), "Expected a Uri result." + assert result.uri == "wrap://test/4" diff --git a/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/conftest.py b/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/conftest.py new file mode 100644 index 00000000..12650fad --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/conftest.py @@ -0,0 +1,14 @@ +import pytest +from polywrap_core import Uri, UriResolutionContext, ClientConfig +from polywrap_client import PolywrapClient +from polywrap_uri_resolvers import RedirectResolver + +@pytest.fixture +def client() -> PolywrapClient: + resolver = RedirectResolver(Uri.from_str("test/from"), Uri.from_str("test/to")) + return PolywrapClient(ClientConfig(resolver=resolver)) + +@pytest.fixture +def resolution_context() -> UriResolutionContext: + return UriResolutionContext() + diff --git a/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/histories/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/histories/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/histories/can_redirect.py b/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/histories/can_redirect.py new file mode 100644 index 00000000..1628caf8 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/histories/can_redirect.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/from => Redirect (wrap://test/from - wrap://test/to) => uri (wrap://test/to)" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/histories/not_redirect.py b/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/histories/not_redirect.py new file mode 100644 index 00000000..583ef804 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/histories/not_redirect.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/not-a-match => Redirect (wrap://test/from - wrap://test/to)" +] \ No newline at end of file diff --git a/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/test_can_redirect_uri.py b/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/test_can_redirect_uri.py new file mode 100644 index 00000000..c8af0058 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/test_can_redirect_uri.py @@ -0,0 +1,17 @@ +from polywrap_core import Uri, UriResolutionContext, build_clean_uri_history +from polywrap_client import PolywrapClient + + +def test_can_redirect_uri( + client: PolywrapClient, resolution_context: UriResolutionContext +) -> None: + uri = Uri.from_str("test/from") + + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.can_redirect import EXPECTED + + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, Uri), "Expected a Uri result." + assert result.uri == "wrap://test/to" diff --git a/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/test_not_redirect_uri.py b/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/test_not_redirect_uri.py new file mode 100644 index 00000000..7a6fe0f9 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/redirect_resolver/test_not_redirect_uri.py @@ -0,0 +1,17 @@ +from polywrap_core import Uri, UriResolutionContext, UriPackage, build_clean_uri_history +from polywrap_client import PolywrapClient + + +def test_not_redirect_uri( + client: PolywrapClient, resolution_context: UriResolutionContext +) -> None: + uri = Uri.from_str("test/not-a-match") + + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.not_redirect import EXPECTED + + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, Uri), "Expected a Uri result." + assert result.uri == "wrap://test/not-a-match" diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/conftest.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/conftest.py new file mode 100644 index 00000000..1ceebe11 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/conftest.py @@ -0,0 +1,65 @@ +import pytest +from polywrap_core import ( + ClientConfig, + InvokerClient, + Uri, + UriPackageOrWrapper, + UriResolutionContext, + UriResolutionStep, + UriWrapper, + UriPackage, +) +from polywrap_client import PolywrapClient +from polywrap_uri_resolvers import ( + RecursiveResolver, + ResolutionResultCacheResolver, + UriResolutionError, + UriResolver, + InMemoryResolutionResultCache, +) + + +class TestResolver(UriResolver): + def try_resolve_uri( + self, uri: Uri, client: InvokerClient, resolution_context: UriResolutionContext + ) -> UriPackageOrWrapper: + result: UriPackageOrWrapper + + if uri.uri == "wrap://test/package": + result = UriPackage(uri=uri, package=NotImplemented) + elif uri.uri == "wrap://test/wrapper": + result = UriWrapper(uri=uri, wrapper=NotImplemented) + elif uri.uri == "wrap://test/from": + result = Uri.from_str("test/to") + elif uri.uri == "wrap://test/A": + result = Uri.from_str("test/B") + elif uri.uri == "wrap://test/B": + result = Uri.from_str("test/wrapper") + elif uri.uri == "wrap://test/error": + raise UriResolutionError("A test error") + else: + raise UriResolutionError(f"Unexpected URI: {uri.uri}") + + resolution_context.track_step( + UriResolutionStep(source_uri=uri, result=result, description="TestResolver") + ) + + return result + + +@pytest.fixture +def client(): + resolver = ResolutionResultCacheResolver( + TestResolver(), cache=InMemoryResolutionResultCache() + ) + return PolywrapClient(ClientConfig(resolver=resolver)) + + +@pytest.fixture +def recursive_client(): + resolver = RecursiveResolver( + ResolutionResultCacheResolver( + TestResolver(), cache=InMemoryResolutionResultCache() + ) + ) + return PolywrapClient(ClientConfig(resolver=resolver)) diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/error_with_cache.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/error_with_cache.py new file mode 100644 index 00000000..c9bcf5a3 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/error_with_cache.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/error => ResolutionResultCacheResolver (Cache) => error (A test error)" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/error_without_cache.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/error_without_cache.py new file mode 100644 index 00000000..e0fbe0f3 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/error_without_cache.py @@ -0,0 +1,4 @@ +EXPECTED = [ + "wrap://test/error => ResolutionResultCacheResolver => error (A test error)", + ["wrap://test/error => TestResolver => error (A test error)"] +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/package_with_cache.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/package_with_cache.py new file mode 100644 index 00000000..a44f4484 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/package_with_cache.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/package => ResolutionResultCacheResolver (Cache) => package (wrap://test/package)" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/package_without_cache.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/package_without_cache.py new file mode 100644 index 00000000..be244bd6 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/package_without_cache.py @@ -0,0 +1,6 @@ +EXPECTED = [ + "wrap://test/package => ResolutionResultCacheResolver => package (wrap://test/package)", + [ + "wrap://test/package => TestResolver => package (wrap://test/package)" + ] +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/uri_with_cache.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/uri_with_cache.py new file mode 100644 index 00000000..b0d4f0f4 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/uri_with_cache.py @@ -0,0 +1 @@ +EXPECTED = ["wrap://test/from => ResolutionResultCacheResolver (Cache) => uri (wrap://test/to)"] diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/uri_without_cache.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/uri_without_cache.py new file mode 100644 index 00000000..a7c38388 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/uri_without_cache.py @@ -0,0 +1,6 @@ +EXPECTED = [ + "wrap://test/from => ResolutionResultCacheResolver => uri (wrap://test/to)", + [ + "wrap://test/from => TestResolver => uri (wrap://test/to)" + ] +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/wrapper_with_cache.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/wrapper_with_cache.py new file mode 100644 index 00000000..39792f38 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/wrapper_with_cache.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/wrapper => ResolutionResultCacheResolver (Cache) => wrapper (wrap://test/wrapper)" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/wrapper_without_cache.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/wrapper_without_cache.py new file mode 100644 index 00000000..700f278c --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/histories/wrapper_without_cache.py @@ -0,0 +1,4 @@ +EXPECTED = [ + "wrap://test/wrapper => ResolutionResultCacheResolver => wrapper (wrap://test/wrapper)", + ["wrap://test/wrapper => TestResolver => wrapper (wrap://test/wrapper)"] +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_cached_error.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_cached_error.py new file mode 100644 index 00000000..a6ab5a9d --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_cached_error.py @@ -0,0 +1,31 @@ +from polywrap_core import ( + Uri, + UriResolutionContext, +) +from polywrap_client import PolywrapClient +from polywrap_uri_resolvers import UriResolutionError +import pytest + + +def test_cached_error(client: PolywrapClient): + client._config.resolver.cache_errors = True # type: ignore + + resolution_context = UriResolutionContext() + with pytest.raises(UriResolutionError) as exc_info_1: + client.try_resolve_uri( + uri=Uri.from_str("test/error"), resolution_context=resolution_context + ) + + assert exc_info_1.value.__class__.__name__ == "UriResolutionError" + assert exc_info_1.value.args[0] == "A test error" + + resolution_context = UriResolutionContext() + with pytest.raises(UriResolutionError) as exc_info_2: + client.try_resolve_uri( + uri=Uri.from_str("test/error"), resolution_context=resolution_context + ) + + assert exc_info_2.value.__class__.__name__ == "UriResolutionError" + assert exc_info_2.value.args[0] == "A test error" + + assert exc_info_1.value is exc_info_2.value diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_cached_package.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_cached_package.py new file mode 100644 index 00000000..92189d84 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_cached_package.py @@ -0,0 +1,29 @@ +from polywrap_core import ( + Uri, + UriResolutionContext, + UriPackage, + build_clean_uri_history, +) +from polywrap_client import PolywrapClient + + +def test_cached_package(client: PolywrapClient): + uri = Uri.from_str("test/package") + + resolution_context = UriResolutionContext() + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.package_without_cache import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, UriPackage), "Expected a UriPackage result." + assert result.uri.uri == "wrap://test/package" + + resolution_context = UriResolutionContext() + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.package_with_cache import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, UriPackage), "Expected a UriPackage result." + assert result.uri.uri == "wrap://test/package" diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_cached_uri.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_cached_uri.py new file mode 100644 index 00000000..7bc9fddb --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_cached_uri.py @@ -0,0 +1,30 @@ +from polywrap_core import ( + Uri, + UriResolutionContext, + build_clean_uri_history, +) +from polywrap_client import PolywrapClient + + +def test_cached_uri(client: PolywrapClient): + uri = Uri.from_str("test/from") + + resolution_context = UriResolutionContext() + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.uri_without_cache import EXPECTED + + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, Uri), "Expected a Uri result." + assert result.uri == "wrap://test/to" + + resolution_context = UriResolutionContext() + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.uri_with_cache import EXPECTED + + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, Uri), "Expected a Uri result." + assert result.uri == "wrap://test/to" diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_cached_wrapper.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_cached_wrapper.py new file mode 100644 index 00000000..150e8d5c --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_cached_wrapper.py @@ -0,0 +1,29 @@ +from polywrap_core import ( + Uri, + UriResolutionContext, + UriWrapper, + build_clean_uri_history, +) +from polywrap_client import PolywrapClient + + +def test_cached_wrapper(client: PolywrapClient): + uri = Uri.from_str("test/wrapper") + + resolution_context = UriResolutionContext() + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.wrapper_without_cache import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, UriWrapper), "Expected a UriWrapper result." + assert result.uri.uri == "wrap://test/wrapper" + + resolution_context = UriResolutionContext() + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.wrapper_with_cache import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, UriWrapper), "Expected a UriWrapper result." + assert result.uri.uri == "wrap://test/wrapper" diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_not_cached_error.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_not_cached_error.py new file mode 100644 index 00000000..93b8341b --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_not_cached_error.py @@ -0,0 +1,29 @@ +from polywrap_core import ( + Uri, + UriResolutionContext, +) +from polywrap_client import PolywrapClient +from polywrap_uri_resolvers import UriResolutionError +import pytest + + +def test_not_cached_error(client: PolywrapClient): + resolution_context = UriResolutionContext() + with pytest.raises(UriResolutionError) as exc_info_1: + client.try_resolve_uri( + uri=Uri.from_str("test/error"), resolution_context=resolution_context + ) + + assert exc_info_1.value.__class__.__name__ == "UriResolutionError" + assert exc_info_1.value.args[0] == "A test error" + + resolution_context = UriResolutionContext() + with pytest.raises(UriResolutionError) as exc_info_2: + client.try_resolve_uri( + uri=Uri.from_str("test/error"), resolution_context=resolution_context + ) + + assert exc_info_2.value.__class__.__name__ == "UriResolutionError" + assert exc_info_2.value.args[0] == "A test error" + + assert exc_info_1.value is not exc_info_2.value diff --git a/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_resolution_path.py b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_resolution_path.py new file mode 100644 index 00000000..a90bbcf5 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/resolution_result_cache_resolver/test_resolution_path.py @@ -0,0 +1,23 @@ +from polywrap_client import PolywrapClient +from polywrap_core import Uri, UriResolutionContext + + +def test_same_resolution_path_after_caching(recursive_client: PolywrapClient): + uri = Uri.from_str("test/A") + expected_path = [ + Uri.from_str("wrap://test/A"), + Uri.from_str("wrap://test/B"), + Uri.from_str("wrap://test/wrapper"), + ] + + resolution_context = UriResolutionContext() + recursive_client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + resolution_path = resolution_context.get_resolution_path() + assert resolution_path == expected_path + + resolution_context = UriResolutionContext() + recursive_client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + resolution_path = resolution_context.get_resolution_path() + assert resolution_path == expected_path diff --git a/packages/polywrap-uri-resolvers/tests/integration/static_resolver/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/static_resolver/conftest.py b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/conftest.py new file mode 100644 index 00000000..23559a3d --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/conftest.py @@ -0,0 +1,31 @@ +import pytest +from polywrap_core import ( + Uri, + UriPackage, + UriResolutionContext, + ClientConfig, + UriWrapper, +) +from polywrap_client import PolywrapClient +from polywrap_uri_resolvers import StaticResolver + + +@pytest.fixture +def client() -> PolywrapClient: + resolver = StaticResolver( + { + Uri.from_str("test/from"): Uri.from_str("test/to"), + Uri.from_str("test/package"): UriPackage( + uri=Uri.from_str("test/package"), package=NotImplemented + ), + Uri.from_str("test/wrapper"): UriWrapper( + uri=Uri.from_str("test/wrapper"), wrapper=NotImplemented + ), + } + ) + return PolywrapClient(ClientConfig(resolver=resolver)) + + +@pytest.fixture +def resolution_context() -> UriResolutionContext: + return UriResolutionContext() diff --git a/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/can_redirect.py b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/can_redirect.py new file mode 100644 index 00000000..2b61d564 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/can_redirect.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/from => Static - Redirect (wrap://test/from - wrap://test/to) => uri (wrap://test/to)" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/can_resolve_package.py b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/can_resolve_package.py new file mode 100644 index 00000000..5502638a --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/can_resolve_package.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/package => Static - Package => package (wrap://test/package)" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/can_resolve_wrapper.py b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/can_resolve_wrapper.py new file mode 100644 index 00000000..29e09e5e --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/can_resolve_wrapper.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/wrapper => Static - Wrapper => wrapper (wrap://test/wrapper)" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/not_resolve.py b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/not_resolve.py new file mode 100644 index 00000000..17635786 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/histories/not_resolve.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/no-match => Static - Miss" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/static_resolver/test_can_redirect.py b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/test_can_redirect.py new file mode 100644 index 00000000..c8af0058 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/test_can_redirect.py @@ -0,0 +1,17 @@ +from polywrap_core import Uri, UriResolutionContext, build_clean_uri_history +from polywrap_client import PolywrapClient + + +def test_can_redirect_uri( + client: PolywrapClient, resolution_context: UriResolutionContext +) -> None: + uri = Uri.from_str("test/from") + + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.can_redirect import EXPECTED + + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, Uri), "Expected a Uri result." + assert result.uri == "wrap://test/to" diff --git a/packages/polywrap-uri-resolvers/tests/integration/static_resolver/test_can_resolve_package.py b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/test_can_resolve_package.py new file mode 100644 index 00000000..e7b885bb --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/test_can_resolve_package.py @@ -0,0 +1,15 @@ +from polywrap_core import Uri, UriResolutionContext, UriPackage, build_clean_uri_history +from polywrap_client import PolywrapClient + + + +def test_resolve_package(client: PolywrapClient, resolution_context: UriResolutionContext) -> None: + uri = Uri.from_str("test/package") + + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.can_resolve_package import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, UriPackage), "Expected a UriPackage result." + assert result.uri.uri == "wrap://test/package" diff --git a/packages/polywrap-uri-resolvers/tests/integration/static_resolver/test_can_resolve_wrapper.py b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/test_can_resolve_wrapper.py new file mode 100644 index 00000000..803cfd5a --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/test_can_resolve_wrapper.py @@ -0,0 +1,14 @@ +from polywrap_core import Uri, UriResolutionContext, UriWrapper, build_clean_uri_history +from polywrap_client import PolywrapClient + + +def test_resolve_wrapper(client: PolywrapClient, resolution_context: UriResolutionContext) -> None: + uri = Uri.from_str("test/wrapper") + + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.can_resolve_wrapper import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, UriWrapper), "Expected a UriWrapper result." + assert result.uri.uri == "wrap://test/wrapper" diff --git a/packages/polywrap-uri-resolvers/tests/integration/static_resolver/test_not_resolve.py b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/test_not_resolve.py new file mode 100644 index 00000000..4e9ff210 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/static_resolver/test_not_resolve.py @@ -0,0 +1,15 @@ +from polywrap_core import Uri, UriResolutionContext, build_clean_uri_history +from polywrap_client import PolywrapClient + + +def test_no_match(client: PolywrapClient, resolution_context: UriResolutionContext) -> None: + uri = Uri.from_str("test/no-match") + + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.not_resolve import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, Uri), "Expected a Uri result." + assert result.uri == "wrap://test/no-match" + diff --git a/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/conftest.py b/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/conftest.py new file mode 100644 index 00000000..2e17944f --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/conftest.py @@ -0,0 +1,14 @@ +import pytest +from polywrap_core import Uri, UriResolutionContext, ClientConfig +from polywrap_client import PolywrapClient +from polywrap_uri_resolvers import WrapperResolver + +@pytest.fixture +def client() -> PolywrapClient: + resolver = WrapperResolver(Uri.from_str("test/wrapper"), NotImplemented) + return PolywrapClient(ClientConfig(resolver=resolver)) + +@pytest.fixture +def resolution_context() -> UriResolutionContext: + return UriResolutionContext() + diff --git a/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/histories/__init__.py b/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/histories/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/histories/not_resolve_wrapper.py b/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/histories/not_resolve_wrapper.py new file mode 100644 index 00000000..2c53be78 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/histories/not_resolve_wrapper.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/not-a-match => Wrapper (wrap://test/wrapper)" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/histories/resolve_wrapper.py b/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/histories/resolve_wrapper.py new file mode 100644 index 00000000..a46b9cda --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/histories/resolve_wrapper.py @@ -0,0 +1,3 @@ +EXPECTED = [ + "wrap://test/wrapper => Wrapper (wrap://test/wrapper) => wrapper (wrap://test/wrapper)" +] diff --git a/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/test_not_resolve_wrapper.py b/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/test_not_resolve_wrapper.py new file mode 100644 index 00000000..fcebe6af --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/test_not_resolve_wrapper.py @@ -0,0 +1,17 @@ +from polywrap_core import Uri, UriResolutionContext, build_clean_uri_history +from polywrap_client import PolywrapClient + + +def test_not_resolve_wrapper( + client: PolywrapClient, resolution_context: UriResolutionContext +) -> None: + uri = Uri.from_str("test/not-a-match") + + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.not_resolve_wrapper import EXPECTED + + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, Uri), "Expected a Uri result." + assert result.uri == "wrap://test/not-a-match" diff --git a/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/test_resolve_wrapper.py b/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/test_resolve_wrapper.py new file mode 100644 index 00000000..fbdb4a48 --- /dev/null +++ b/packages/polywrap-uri-resolvers/tests/integration/wrapper_resolver/test_resolve_wrapper.py @@ -0,0 +1,14 @@ +from polywrap_core import Uri, UriResolutionContext, UriWrapper, build_clean_uri_history +from polywrap_client import PolywrapClient + + +def test_resolve_wrapper(client: PolywrapClient, resolution_context: UriResolutionContext) -> None: + uri = Uri.from_str("test/wrapper") + + result = client.try_resolve_uri(uri=uri, resolution_context=resolution_context) + + from .histories.resolve_wrapper import EXPECTED + assert build_clean_uri_history(resolution_context.get_history()) == EXPECTED + + assert isinstance(result, UriWrapper), "Expected a UriWrapper result." + assert result.uri.uri == "wrap://test/wrapper" diff --git a/packages/polywrap-uri-resolvers/tests/test_static_resolver.py b/packages/polywrap-uri-resolvers/tests/test_static_resolver.py deleted file mode 100644 index 2ddeae58..00000000 --- a/packages/polywrap-uri-resolvers/tests/test_static_resolver.py +++ /dev/null @@ -1,70 +0,0 @@ -# import pytest -# from pathlib import Path - -# from polywrap_result import Ok, Err, Result -# from polywrap_wasm import WRAP_MANIFEST_PATH, WRAP_MODULE_PATH, IFileReader, WasmPackage, WasmWrapper -# from polywrap_core import UriPackage, Uri, UriResolutionContext, UriWrapper, IWrapPackage -# from polywrap_client import PolywrapClient -# from polywrap_uri_resolvers import StaticResolver -# from polywrap_manifest import deserialize_wrap_manifest - - -# @pytest.fixture -# def simple_wrap_module(): -# wrap_path = Path(__file__).parent / "cases" / "simple" / "wrap.wasm" -# with open(wrap_path, "rb") as f: -# yield f.read() - - -# @pytest.fixture -# def simple_wrap_manifest(): -# wrap_path = Path(__file__).parent / "cases" / "simple" / "wrap.info" -# with open(wrap_path, "rb") as f: -# yield f.read() - -# @pytest.fixture -# def simple_file_reader(simple_wrap_module: bytes, simple_wrap_manifest: bytes): -# class FileReader(IFileReader): -# async def read_file(self, file_path: str) -> Result[bytes]: -# if file_path == WRAP_MODULE_PATH: -# return Ok(simple_wrap_module) -# if file_path == WRAP_MANIFEST_PATH: -# return Ok(simple_wrap_manifest) -# return Err.from_str(f"FileNotFound: {file_path}") - -# yield FileReader() - -# @pytest.mark.asyncio -# async def test_static_resolver( -# simple_file_reader: IFileReader, -# simple_wrap_module: bytes, -# simple_wrap_manifest: bytes -# ): -# package = WasmPackage(simple_file_reader) - -# manifest = deserialize_wrap_manifest(simple_wrap_manifest).unwrap() -# wrapper = WasmWrapper(simple_file_reader, simple_wrap_module, manifest) - -# uri_wrapper = UriWrapper(uri=Uri("ens/wrapper.eth"), wrapper=wrapper) -# uri_package = UriPackage(uri=Uri("ens/package.eth"), package=package) - -# resolver = StaticResolver.from_list([ uri_package, uri_wrapper, [ -# UriPackage(uri=Uri("ens/nested-package.eth"), package=package) -# ]]).unwrap() - -# resolution_context = UriResolutionContext() -# result = await resolver.try_resolve_uri(Uri("ens/package.eth"), PolywrapClient(), resolution_context) - -# assert result.is_ok -# assert isinstance((result.unwrap()).package, IWrapPackage) - -# result = await resolver.try_resolve_uri(Uri("ens/wrapper.eth"), PolywrapClient(), resolution_context) - -# assert result.is_ok -# assert isinstance((result.unwrap()).wrapper, WasmWrapper) - -# result = await resolver.try_resolve_uri(Uri("ens/nested-package.eth"), PolywrapClient(), resolution_context) - -# assert result.is_ok -# assert isinstance((result.unwrap()).package, IWrapPackage) - diff --git a/packages/polywrap-uri-resolvers/tests/unit/__init__.py b/packages/polywrap-uri-resolvers/tests/unit/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/polywrap-uri-resolvers/tests/cases/simple/wrap.info b/packages/polywrap-uri-resolvers/tests/unit/cases/simple/wrap.info similarity index 100% rename from packages/polywrap-uri-resolvers/tests/cases/simple/wrap.info rename to packages/polywrap-uri-resolvers/tests/unit/cases/simple/wrap.info diff --git a/packages/polywrap-uri-resolvers/tests/cases/simple/wrap.wasm b/packages/polywrap-uri-resolvers/tests/unit/cases/simple/wrap.wasm similarity index 100% rename from packages/polywrap-uri-resolvers/tests/cases/simple/wrap.wasm rename to packages/polywrap-uri-resolvers/tests/unit/cases/simple/wrap.wasm diff --git a/packages/polywrap-uri-resolvers/tests/test_file_resolver.py b/packages/polywrap-uri-resolvers/tests/unit/test_file_resolver.py similarity index 76% rename from packages/polywrap-uri-resolvers/tests/test_file_resolver.py rename to packages/polywrap-uri-resolvers/tests/unit/test_file_resolver.py index 9444620e..c7b28aa9 100644 --- a/packages/polywrap-uri-resolvers/tests/test_file_resolver.py +++ b/packages/polywrap-uri-resolvers/tests/unit/test_file_resolver.py @@ -14,12 +14,11 @@ def fs_resolver(file_reader: FileReader): return FsUriResolver(file_reader=file_reader) -@pytest.mark.asyncio -async def test_file_resolver(fs_resolver: UriResolver): +def test_file_resolver(fs_resolver: UriResolver): path = Path(__file__).parent / "cases" / "simple" uri = Uri.from_str(f"wrap://fs/{path}") - result = await fs_resolver.try_resolve_uri(uri, None, None) # type: ignore + result = fs_resolver.try_resolve_uri(uri, None, None) # type: ignore assert result assert isinstance(result, UriPackage) diff --git a/packages/polywrap-uri-resolvers/tox.ini b/packages/polywrap-uri-resolvers/tox.ini index 2aa32861..3ba7cd01 100644 --- a/packages/polywrap-uri-resolvers/tox.ini +++ b/packages/polywrap-uri-resolvers/tox.ini @@ -4,6 +4,7 @@ envlist = py310 [testenv] commands = + python -m polywrap_test_cases pytest tests/ [testenv:lint] diff --git a/packages/polywrap-wasm/polywrap_wasm/__init__.py b/packages/polywrap-wasm/polywrap_wasm/__init__.py index efc5276d..978aa2e1 100644 --- a/packages/polywrap-wasm/polywrap_wasm/__init__.py +++ b/packages/polywrap-wasm/polywrap_wasm/__init__.py @@ -1,8 +1,5 @@ """This module contains the runtime for executing Wasm wrappers.""" -from .buffer import * from .errors import * -from .exports import * -from .imports import * from .inmemory_file_reader import * from .wasm_package import * from .wasm_wrapper import * diff --git a/packages/polywrap-wasm/polywrap_wasm/constants.py b/packages/polywrap-wasm/polywrap_wasm/constants.py index 7645df03..3fcc99cd 100644 --- a/packages/polywrap-wasm/polywrap_wasm/constants.py +++ b/packages/polywrap-wasm/polywrap_wasm/constants.py @@ -1,3 +1,5 @@ """This module contains the constants used by polywrap-wasm package.""" WRAP_MANIFEST_PATH = "wrap.info" WRAP_MODULE_PATH = "wrap.wasm" + +__all__ = ["WRAP_MANIFEST_PATH", "WRAP_MODULE_PATH"] diff --git a/packages/polywrap-wasm/polywrap_wasm/errors.py b/packages/polywrap-wasm/polywrap_wasm/errors.py index 31b9bae9..07a6b58f 100644 --- a/packages/polywrap-wasm/polywrap_wasm/errors.py +++ b/packages/polywrap-wasm/polywrap_wasm/errors.py @@ -12,3 +12,10 @@ class WasmExportNotFoundError(WasmError): class WasmMemoryError(WasmError): """Raises when the Wasm memory is not found.""" + + +__all__ = [ + "WasmError", + "WasmExportNotFoundError", + "WasmMemoryError", +] diff --git a/packages/polywrap-wasm/polywrap_wasm/imports/get_implementations.py b/packages/polywrap-wasm/polywrap_wasm/imports/get_implementations.py index 3ecd35f6..994ff671 100644 --- a/packages/polywrap-wasm/polywrap_wasm/imports/get_implementations.py +++ b/packages/polywrap-wasm/polywrap_wasm/imports/get_implementations.py @@ -24,6 +24,11 @@ def wrap_get_implementations(self, uri_ptr: int, uri_len: int) -> bool: uri_len, ) ) + if not self.invoker: + raise WrapAbortError( + invoke_options=self.state.invoke_options, + message="Expected invoker to be defined got None", + ) try: maybe_implementations = self.invoker.get_implementations(uri=uri) implementations: List[str] = ( @@ -35,8 +40,8 @@ def wrap_get_implementations(self, uri_ptr: int, uri_len: int) -> bool: return len(implementations) > 0 except Exception as err: raise WrapAbortError( - self.state.invoke_options, - f"failed calling invoker.get_implementations({repr(uri)})", + invoke_options=self.state.invoke_options, + message=f"failed calling invoker.get_implementations({repr(uri)})", ) from err def wrap_get_implementations_result_len(self) -> int: @@ -59,6 +64,12 @@ def wrap_get_implementations_result(self, ptr: int) -> None: self.write_bytes(ptr, result) def _get_get_implementations_result(self, export_name: str): + if not self.invoker: + raise WrapAbortError( + invoke_options=self.state.invoke_options, + message="Expected invoker to be defined got None", + ) + if not self.state.get_implementations_result: raise WrapAbortError( self.state.invoke_options, diff --git a/packages/polywrap-wasm/polywrap_wasm/imports/subinvoke.py b/packages/polywrap-wasm/polywrap_wasm/imports/subinvoke.py index 78ecd91f..a1cdd5aa 100644 --- a/packages/polywrap-wasm/polywrap_wasm/imports/subinvoke.py +++ b/packages/polywrap-wasm/polywrap_wasm/imports/subinvoke.py @@ -1,15 +1,10 @@ """This module contains the subinvoke imports for the Wasm module.""" -import asyncio -from concurrent.futures import ThreadPoolExecutor - -from polywrap_core import InvokerOptions, Uri, WrapAbortError +from polywrap_core import Uri, WrapAbortError from polywrap_msgpack import msgpack_encode from ..types import InvokeResult from .types import BaseWrapImports -pool = ThreadPoolExecutor() - class WrapSubinvokeImports(BaseWrapImports): """Defines the subinvoke family of imports for the Wasm module.""" @@ -42,18 +37,19 @@ def wrap_subinvoke( method = self._get_subinvoke_method(method_ptr, method_len) args = self._get_subinvoke_args(args_ptr, args_len) + if not self.invoker: + raise WrapAbortError( + invoke_options=self.state.invoke_options, + message="Expected invoker to be defined got None", + ) + try: - result = pool.submit( - asyncio.run, - self.invoker.invoke( - InvokerOptions( - uri=uri, - method=method, - args=args, - encode_result=True, - ) - ), - ).result() + result = self.invoker.invoke( + uri=uri, + method=method, + args=args, + encode_result=True, + ) if isinstance(result, bytes): self.state.subinvoke_result = InvokeResult(result=result) return True diff --git a/packages/polywrap-wasm/polywrap_wasm/imports/types/base_wrap_imports.py b/packages/polywrap-wasm/polywrap_wasm/imports/types/base_wrap_imports.py index 58d4192e..46e7d9fc 100644 --- a/packages/polywrap-wasm/polywrap_wasm/imports/types/base_wrap_imports.py +++ b/packages/polywrap-wasm/polywrap_wasm/imports/types/base_wrap_imports.py @@ -2,8 +2,9 @@ from __future__ import annotations from abc import ABC +from typing import Optional -from polywrap_core import Invoker, UriPackageOrWrapper +from polywrap_core import Invoker from wasmtime import Memory, Store from ...buffer import read_bytes, read_string, write_bytes, write_string @@ -16,7 +17,7 @@ class BaseWrapImports(ABC): memory: Memory store: Store state: State - invoker: Invoker[UriPackageOrWrapper] + invoker: Optional[Invoker] def read_string(self, ptr: int, length: int) -> str: """Read a UTF-8 encoded string from the memory buffer.""" diff --git a/packages/polywrap-wasm/polywrap_wasm/imports/utils/__init__.py b/packages/polywrap-wasm/polywrap_wasm/imports/utils/__init__.py deleted file mode 100644 index bcc32367..00000000 --- a/packages/polywrap-wasm/polywrap_wasm/imports/utils/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -"""This module contains utility functions for the Wasm imports.""" -from .unsync_invoke import * diff --git a/packages/polywrap-wasm/polywrap_wasm/imports/utils/unsync_invoke.py b/packages/polywrap-wasm/polywrap_wasm/imports/utils/unsync_invoke.py deleted file mode 100644 index 600a5c59..00000000 --- a/packages/polywrap-wasm/polywrap_wasm/imports/utils/unsync_invoke.py +++ /dev/null @@ -1,13 +0,0 @@ -"""This module contains the unsync_invoke function.""" -from typing import Any - -from polywrap_core import Invoker, InvokerOptions, UriPackageOrWrapper -from unsync import Unfuture, unsync - - -@unsync -async def unsync_invoke( - invoker: Invoker[UriPackageOrWrapper], options: InvokerOptions[UriPackageOrWrapper] -) -> Unfuture[Any]: - """Perform an unsync invoke call.""" - return await invoker.invoke(options) diff --git a/packages/polywrap-wasm/polywrap_wasm/imports/wrap_imports.py b/packages/polywrap-wasm/polywrap_wasm/imports/wrap_imports.py index afefacfa..7246dbf6 100644 --- a/packages/polywrap-wasm/polywrap_wasm/imports/wrap_imports.py +++ b/packages/polywrap-wasm/polywrap_wasm/imports/wrap_imports.py @@ -3,7 +3,9 @@ # pylint: disable=too-many-ancestors from __future__ import annotations -from polywrap_core import Invoker, UriPackageOrWrapper +from typing import Optional + +from polywrap_core import Invoker from wasmtime import Memory, Store from ..types.state import State @@ -39,7 +41,7 @@ def __init__( memory: Memory, store: Store, state: State, - invoker: Invoker[UriPackageOrWrapper], + invoker: Optional[Invoker], ) -> None: """Initialize the WrapImports instance. diff --git a/packages/polywrap-wasm/polywrap_wasm/inmemory_file_reader.py b/packages/polywrap-wasm/polywrap_wasm/inmemory_file_reader.py index ea3d466f..da5c90d5 100644 --- a/packages/polywrap-wasm/polywrap_wasm/inmemory_file_reader.py +++ b/packages/polywrap-wasm/polywrap_wasm/inmemory_file_reader.py @@ -31,7 +31,7 @@ def __init__( self._wasm_manifest = wasm_manifest self._base_file_reader = base_file_reader - async def read_file(self, file_path: str) -> bytes: + def read_file(self, file_path: str) -> bytes: """Read a file from memory. Args: @@ -44,4 +44,7 @@ async def read_file(self, file_path: str) -> bytes: return self._wasm_module if file_path == WRAP_MANIFEST_PATH and self._wasm_manifest: return self._wasm_manifest - return await self._base_file_reader.read_file(file_path=file_path) + return self._base_file_reader.read_file(file_path=file_path) + + +__all__ = ["InMemoryFileReader"] diff --git a/packages/polywrap-wasm/polywrap_wasm/instance.py b/packages/polywrap-wasm/polywrap_wasm/instance.py index 0028cbb1..c1f4de53 100644 --- a/packages/polywrap-wasm/polywrap_wasm/instance.py +++ b/packages/polywrap-wasm/polywrap_wasm/instance.py @@ -1,5 +1,7 @@ """This module contains the imports of the Wasm wrapper module.""" -from polywrap_core import Invoker, UriPackageOrWrapper +from typing import Optional + +from polywrap_core import Invoker from wasmtime import Instance, Linker, Module, Store from .imports import WrapImports @@ -12,7 +14,7 @@ def create_instance( store: Store, module: bytes, state: State, - invoker: Invoker[UriPackageOrWrapper], + invoker: Optional[Invoker], ) -> Instance: """Create a Wasm instance for a Wasm module. diff --git a/packages/polywrap-wasm/polywrap_wasm/types/state.py b/packages/polywrap-wasm/polywrap_wasm/types/state.py index d9e18e5d..a09ecad6 100644 --- a/packages/polywrap-wasm/polywrap_wasm/types/state.py +++ b/packages/polywrap-wasm/polywrap_wasm/types/state.py @@ -1,12 +1,31 @@ """This module contains the State type for holding the state of a Wasm wrapper.""" from dataclasses import dataclass -from typing import Generic, Optional, TypeVar +from typing import Any, Generic, Optional, TypeVar -from polywrap_core import InvokeOptions, UriPackageOrWrapper +from polywrap_core import Uri, UriResolutionContext E = TypeVar("E") +@dataclass(kw_only=True, slots=True) +class InvokeOptions: + """InvokeOptions is a dataclass that holds the options for an invocation. + + Attributes: + uri: The URI of the wrapper. + method: The method to invoke. + args: The arguments to pass to the method. + env: The environment variables to set for the invocation. + resolution_context: A URI resolution context. + """ + + uri: Uri + method: str + args: Optional[dict[str, Any]] = None + env: Optional[dict[str, Any]] = None + resolution_context: Optional[UriResolutionContext] = None + + @dataclass(kw_only=True, slots=True) class InvokeResult(Generic[E]): """InvokeResult is a dataclass that holds the result of an invocation. @@ -39,7 +58,7 @@ class State: get_implementations_result: The result of a get implementations call. """ - invoke_options: InvokeOptions[UriPackageOrWrapper] + invoke_options: InvokeOptions invoke_result: Optional[InvokeResult[str]] = None subinvoke_result: Optional[InvokeResult[Exception]] = None get_implementations_result: Optional[bytes] = None diff --git a/packages/polywrap-wasm/polywrap_wasm/wasm_package.py b/packages/polywrap-wasm/polywrap_wasm/wasm_package.py index 55f43d62..7ab92c74 100644 --- a/packages/polywrap-wasm/polywrap_wasm/wasm_package.py +++ b/packages/polywrap-wasm/polywrap_wasm/wasm_package.py @@ -1,21 +1,19 @@ """This module contains the WasmPackage type for loading a Wasm package.""" from typing import Optional, Union -from polywrap_core import ( - FileReader, - GetManifestOptions, - UriPackageOrWrapper, - WrapPackage, - Wrapper, +from polywrap_core import FileReader, WrapPackage, Wrapper +from polywrap_manifest import ( + AnyWrapManifest, + DeserializeManifestOptions, + deserialize_wrap_manifest, ) -from polywrap_manifest import AnyWrapManifest, deserialize_wrap_manifest from .constants import WRAP_MANIFEST_PATH, WRAP_MODULE_PATH from .inmemory_file_reader import InMemoryFileReader from .wasm_wrapper import WasmWrapper -class WasmPackage(WrapPackage[UriPackageOrWrapper]): +class WasmPackage(WrapPackage): """WasmPackage is a type that represents a Wasm WRAP package. Attributes: @@ -43,8 +41,8 @@ def __init__( else file_reader ) - async def get_manifest( - self, options: Optional[GetManifestOptions] = None + def get_manifest( + self, options: Optional[DeserializeManifestOptions] = None ) -> AnyWrapManifest: """Get the manifest of the wrapper. @@ -54,13 +52,13 @@ async def get_manifest( if isinstance(self.manifest, AnyWrapManifest): return self.manifest - encoded_manifest = self.manifest or await self.file_reader.read_file( + encoded_manifest = self.manifest or self.file_reader.read_file( WRAP_MANIFEST_PATH ) manifest = deserialize_wrap_manifest(encoded_manifest, options) return manifest - async def get_wasm_module(self) -> bytes: + def get_wasm_module(self) -> bytes: """Get the Wasm module of the wrapper if it exists or return an error. Returns: @@ -69,13 +67,16 @@ async def get_wasm_module(self) -> bytes: if isinstance(self.wasm_module, bytes): return self.wasm_module - wasm_module = await self.file_reader.read_file(WRAP_MODULE_PATH) + wasm_module = self.file_reader.read_file(WRAP_MODULE_PATH) self.wasm_module = wasm_module return self.wasm_module - async def create_wrapper(self) -> Wrapper[UriPackageOrWrapper]: + def create_wrapper(self) -> Wrapper: """Create a new WasmWrapper instance.""" - wasm_module = await self.get_wasm_module() - wasm_manifest = await self.get_manifest() + wasm_module = self.get_wasm_module() + wasm_manifest = self.get_manifest() return WasmWrapper(self.file_reader, wasm_module, wasm_manifest) + + +__all__ = ["WasmPackage"] diff --git a/packages/polywrap-wasm/polywrap_wasm/wasm_wrapper.py b/packages/polywrap-wasm/polywrap_wasm/wasm_wrapper.py index 00ad2a12..a15fab67 100644 --- a/packages/polywrap-wasm/polywrap_wasm/wasm_wrapper.py +++ b/packages/polywrap-wasm/polywrap_wasm/wasm_wrapper.py @@ -1,14 +1,14 @@ """This module contains the WasmWrapper class for invoking Wasm wrappers.""" +# pylint: disable=too-many-locals from textwrap import dedent -from typing import Union +from typing import Any, Dict, Optional, Union from polywrap_core import ( FileReader, - GetFileOptions, InvocableResult, - InvokeOptions, Invoker, - UriPackageOrWrapper, + Uri, + UriResolutionContext, WrapAbortError, WrapError, Wrapper, @@ -19,10 +19,10 @@ from .exports import WrapExports from .instance import create_instance -from .types.state import State +from .types.state import InvokeOptions, State -class WasmWrapper(Wrapper[UriPackageOrWrapper]): +class WasmWrapper(Wrapper): """WasmWrapper implements the Wrapper interface for Wasm wrappers. Attributes: @@ -51,7 +51,9 @@ def get_wasm_module(self) -> bytes: """Get the Wasm module of the wrapper.""" return self.wasm_module - async def get_file(self, options: GetFileOptions) -> Union[str, bytes]: + def get_file( + self, path: str, encoding: Optional[str] = "utf-8" + ) -> Union[str, bytes]: """Get a file from the wrapper. Args: @@ -60,59 +62,67 @@ async def get_file(self, options: GetFileOptions) -> Union[str, bytes]: Returns: The file contents as string or bytes according to encoding or an error. """ - data = await self.file_reader.read_file(options.path) - return data.decode(encoding=options.encoding) if options.encoding else data + data = self.file_reader.read_file(path) + return data.decode(encoding=encoding) if encoding else data def create_wasm_instance( - self, - store: Store, - state: State, - invoker: Invoker[UriPackageOrWrapper], - options: InvokeOptions[UriPackageOrWrapper], + self, store: Store, state: State, client: Optional[Invoker] ) -> Instance: """Create a new Wasm instance for the wrapper. Args: store: The Wasm store to use when creating the instance. state: The Wasm wrapper state to use when creating the instance. - invoker: The invoker to use when creating the instance. + client: The client to use when creating the instance. Returns: The Wasm instance of the wrapper Wasm module. """ try: - return create_instance(store, self.wasm_module, state, invoker) + return create_instance(store, self.wasm_module, state, client) except Exception as err: raise WrapAbortError( - options, "Unable to instantiate the wasm module" + state.invoke_options, "Unable to instantiate the wasm module" ) from err - async def invoke( + def invoke( self, - options: InvokeOptions[UriPackageOrWrapper], - invoker: Invoker[UriPackageOrWrapper], + uri: Uri, + method: str, + args: Optional[Dict[str, Any]] = None, + env: Optional[Dict[str, Any]] = None, + resolution_context: Optional[UriResolutionContext] = None, + client: Optional[Invoker] = None, ) -> InvocableResult: """Invoke the wrapper. Args: options: The options to use when invoking the wrapper. - invoker: The invoker to use when invoking the wrapper. + client: The client to use when invoking the wrapper. Returns: The result of the invocation or an error. """ - if not (options.uri and options.method): + if not (uri and method): raise WrapError( dedent( f""" Expected invocation uri and method to be defiened got: - uri: {options.uri} - method: {options.method} + uri: {uri} + method: {method} """ ) ) - state = State(invoke_options=options) + state = State( + invoke_options=InvokeOptions( + uri=uri, + method=method, + args=args, + env=env, + resolution_context=resolution_context, + ) + ) encoded_args = ( state.invoke_options.args @@ -126,7 +136,7 @@ async def invoke( env_length = len(encoded_env) store = Store() - instance = self.create_wasm_instance(store, state, invoker, options) + instance = self.create_wasm_instance(store, state, client) exports = WrapExports(instance, store) result = exports.__wrap_invoke__(method_length, args_length, env_length) @@ -135,6 +145,9 @@ async def invoke( # Note: currently we only return not None result from Wasm module return InvocableResult(result=state.invoke_result.result, encoded=True) raise WrapAbortError( - options, + state.invoke_options, "Expected a result from the Wasm module", ) + + +__all__ = ["WasmWrapper"] diff --git a/packages/polywrap-wasm/tests/test_wasm_wrapper.py b/packages/polywrap-wasm/tests/test_wasm_wrapper.py index fe202feb..0ec2b998 100644 --- a/packages/polywrap-wasm/tests/test_wasm_wrapper.py +++ b/packages/polywrap-wasm/tests/test_wasm_wrapper.py @@ -1,22 +1,27 @@ -from typing import Any, List, cast +from typing import Any, cast import pytest from pathlib import Path from polywrap_msgpack import msgpack_decode -from polywrap_core import Uri, InvokeOptions, Invoker, InvokerOptions, UriPackageOrWrapper -from polywrap_wasm import FileReader, WasmPackage, WasmWrapper, WRAP_MODULE_PATH +from polywrap_core import InvokerClient, Uri, Invoker, FileReader +from polywrap_wasm import WasmPackage, WasmWrapper +from polywrap_wasm.constants import WRAP_MODULE_PATH, WRAP_MANIFEST_PATH from polywrap_manifest import deserialize_wrap_manifest -from polywrap_wasm.constants import WRAP_MANIFEST_PATH + @pytest.fixture def mock_invoker(): - class MockInvoker(Invoker[UriPackageOrWrapper]): - async def invoke(self, options: InvokerOptions[UriPackageOrWrapper]) -> Any: + class MockInvoker(InvokerClient): + + def try_resolve_uri(self, *args: Any, **kwargs: Any) -> Any: raise NotImplementedError() - - def get_implementations(self, uri: Uri) -> List[Uri]: + + def invoke(self, *args: Any, **kwargs: Any) -> Any: + raise NotImplementedError() + + def get_implementations(self, *args: Any, **kwargs: Any) -> Any: raise NotImplementedError() return MockInvoker() @@ -39,7 +44,7 @@ def simple_wrap_manifest(): @pytest.fixture def dummy_file_reader(): class DummyFileReader(FileReader): - async def read_file(self, file_path: str) -> bytes: + def read_file(self, *args: Any, **kwargs: Any) -> bytes: raise NotImplementedError() yield DummyFileReader() @@ -48,7 +53,7 @@ async def read_file(self, file_path: str) -> bytes: @pytest.fixture def simple_file_reader(simple_wrap_module: bytes, simple_wrap_manifest: bytes): class DummyFileReader(FileReader): - async def read_file(self, file_path: str) -> bytes: + def read_file(self, file_path: str) -> bytes: if file_path == WRAP_MODULE_PATH: return simple_wrap_module if file_path == WRAP_MANIFEST_PATH: @@ -58,28 +63,41 @@ async def read_file(self, file_path: str) -> bytes: yield DummyFileReader() -@pytest.mark.asyncio -async def test_invoke_with_wrapper( - dummy_file_reader: FileReader, simple_wrap_module: bytes, simple_wrap_manifest: bytes, mock_invoker: Invoker[UriPackageOrWrapper] +def test_invoke_with_wrapper( + dummy_file_reader: FileReader, + simple_wrap_module: bytes, + simple_wrap_manifest: bytes, + mock_invoker: Invoker, ): - wrapper = WasmWrapper(dummy_file_reader, simple_wrap_module, deserialize_wrap_manifest(simple_wrap_manifest)) + wrapper = WasmWrapper( + dummy_file_reader, + simple_wrap_module, + deserialize_wrap_manifest(simple_wrap_manifest), + ) message = "hey" args = {"arg": message} - options: InvokeOptions[UriPackageOrWrapper] = InvokeOptions(uri=Uri.from_str("fs/./build"), method="simpleMethod", args=args) - result = await wrapper.invoke(options, mock_invoker) + result = wrapper.invoke( + uri=Uri.from_str("fs/./build"), + method="simpleMethod", + args=args, + client=mock_invoker, + ) assert result.encoded is True assert msgpack_decode(cast(bytes, result.result)) == message -@pytest.mark.asyncio -async def test_invoke_with_package(simple_file_reader: FileReader, mock_invoker: Invoker[UriPackageOrWrapper]): +def test_invoke_with_package(simple_file_reader: FileReader, mock_invoker: InvokerClient): package = WasmPackage(simple_file_reader) - wrapper = await package.create_wrapper() + wrapper = package.create_wrapper() message = "hey" args = {"arg": message} - options: InvokeOptions[UriPackageOrWrapper] = InvokeOptions(uri=Uri.from_str("fs/./build"), method="simpleMethod", args=args) - result = await wrapper.invoke(options, mock_invoker) + result = wrapper.invoke( + uri=Uri.from_str("fs/./build"), + method="simpleMethod", + args=args, + client=mock_invoker, + ) assert result.encoded is True assert msgpack_decode(cast(bytes, result.result)) == message diff --git a/python-monorepo.code-workspace b/python-monorepo.code-workspace index d6fea917..7c532afe 100644 --- a/python-monorepo.code-workspace +++ b/python-monorepo.code-workspace @@ -39,6 +39,10 @@ { "name": "polywrap-plugin", "path": "packages/polywrap-plugin" + }, + { + "name": "polywrap-test-cases", + "path": "packages/polywrap-test-cases" } ], "settings": {