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-core/polywrap_core/utils/get_env_from_resolution_path.py b/packages/polywrap-core/polywrap_core/utils/get_env_from_resolution_path.py new file mode 100644 index 00000000..33bc4ac2 --- /dev/null +++ b/packages/polywrap-core/polywrap_core/utils/get_env_from_resolution_path.py @@ -0,0 +1,22 @@ +"""This module contains the utility function for getting the env from the URI history.""" +from typing import Any, List, Union + +from ..types import Client, Uri + + +def get_env_from_resolution_path( + uri_history: List[Uri], client: Client +) -> Union[Any, None]: + """Get environment variable from URI resolution history. + + Args: + uri_history: List of URIs from the URI resolution history + client: Polywrap client instance to use for getting the env by URI + + Returns: + env if found, None otherwise + """ + for uri in uri_history: + if env := client.get_env_by_uri(uri): + return env + return None 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):