33
44import json
55from textwrap import dedent
6- from typing import Any , Dict , List , Optional , Union , cast
6+ from typing import Any , Dict , List , Optional , Union
77
88from polywrap_core import (
99 Client ,
1010 ClientConfig ,
11- Env ,
12- GetFileOptions ,
13- GetManifestOptions ,
14- InvokerOptions ,
15- IUriResolutionContext ,
16- TryResolveUriOptions ,
1711 Uri ,
1812 UriPackage ,
1913 UriPackageOrWrapper ,
14+ UriResolutionStep ,
2015 UriResolver ,
2116 UriWrapper ,
2217 Wrapper ,
18+ build_clean_uri_history ,
19+ get_env_from_resolution_path ,
2320)
24- from polywrap_manifest import AnyWrapManifest
21+ from polywrap_core import get_implementations as core_get_implementations
22+ from polywrap_manifest import AnyWrapManifest , DeserializeManifestOptions
2523from polywrap_msgpack import msgpack_decode , msgpack_encode
26- from polywrap_uri_resolvers import UriResolutionContext , build_clean_uri_history
24+ from polywrap_uri_resolvers import UriResolutionContext
2725
2826
2927class PolywrapClient (Client ):
@@ -59,13 +57,13 @@ def get_uri_resolver(self) -> UriResolver:
5957 """
6058 return self ._config .resolver
6159
62- def get_envs (self ) -> Dict [Uri , Env ]:
60+ def get_envs (self ) -> Dict [Uri , Any ]:
6361 """Get the dictionary of environment variables.
6462
6563 Returns:
66- Dict[Uri, Env ]: The dictionary of environment variables.
64+ Dict[Uri, Any ]: The dictionary of environment variables.
6765 """
68- envs : Dict [Uri , Env ] = self ._config .envs
66+ envs : Dict [Uri , Any ] = self ._config .envs
6967 return envs
7068
7169 def get_interfaces (self ) -> Dict [Uri , List [Uri ]]:
@@ -77,146 +75,196 @@ def get_interfaces(self) -> Dict[Uri, List[Uri]]:
7775 interfaces : Dict [Uri , List [Uri ]] = self ._config .interfaces
7876 return interfaces
7977
80- def get_implementations (self , uri : Uri ) -> Union [List [Uri ], None ]:
81- """Get the implementations for the given interface URI.
78+ def get_implementations (
79+ self ,
80+ uri : Uri ,
81+ apply_resolution : bool = True ,
82+ resolution_context : Optional [UriResolutionContext ] = None ,
83+ ) -> Optional [List [Uri ]]:
84+ """Get implementations of an interface with its URI.
8285
8386 Args:
84- uri (Uri): The interface URI.
87+ uri (Uri): URI of the interface.
88+ apply_resolution (bool): If True, apply resolution to the URI and interfaces.
8589
8690 Returns:
87- Union [List[Uri], None ]: The list of implementation URIs .
91+ Optional [List[Uri]]: List of implementations or None if not found .
8892 """
8993 interfaces : Dict [Uri , List [Uri ]] = self .get_interfaces ()
90- return interfaces .get (uri )
94+ if not apply_resolution :
95+ return interfaces .get (uri )
96+
97+ return core_get_implementations (uri , interfaces , self , resolution_context )
9198
92- def get_env_by_uri (self , uri : Uri ) -> Union [Env , None ]:
99+ def get_env_by_uri (self , uri : Uri ) -> Union [Any , None ]:
93100 """Get the environment variables for the given URI.
94101
95102 Args:
96103 uri (Uri): The URI of the wrapper.
97104
98105 Returns:
99- Union[Env , None]: The environment variables.
106+ Union[Any , None]: The environment variables.
100107 """
101108 return self ._config .envs .get (uri )
102109
103- async def get_file (self , uri : Uri , options : GetFileOptions ) -> Union [bytes , str ]:
110+ def get_file (
111+ self , uri : Uri , path : str , encoding : Optional [str ] = "utf-8"
112+ ) -> Union [bytes , str ]:
104113 """Get the file from the given wrapper URI.
105114
106115 Args:
107116 uri (Uri): The wrapper URI.
108- options (GetFileOptions) : The options for getting the file.
117+ (GetFile : The for getting the file.
109118
110119 Returns:
111120 Union[bytes, str]: The file contents.
112121 """
113- loaded_wrapper = await self .load_wrapper (uri )
114- return await loaded_wrapper .get_file (options )
122+ loaded_wrapper = self .load_wrapper (uri )
123+ return loaded_wrapper .get_file (path , encoding )
115124
116- async def get_manifest (
117- self , uri : Uri , options : Optional [GetManifestOptions ] = None
125+ def get_manifest (
126+ self , uri : Uri , options : Optional [DeserializeManifestOptions ] = None
118127 ) -> AnyWrapManifest :
119128 """Get the manifest from the given wrapper URI.
120129
121130 Args:
122131 uri (Uri): The wrapper URI.
123- options (Optional[GetManifestOptions] ): The options for getting the manifest.
132+ (Optional[GetManifest ): The for getting the manifest.
124133
125134 Returns:
126135 AnyWrapManifest: The manifest.
127136 """
128- loaded_wrapper = await self .load_wrapper (uri )
137+ loaded_wrapper = self .load_wrapper (uri )
129138 return loaded_wrapper .get_manifest ()
130139
131- async def try_resolve_uri (
132- self , options : TryResolveUriOptions [ UriPackageOrWrapper ]
140+ def try_resolve_uri (
141+ self , uri : Uri , resolution_context : Optional [ UriResolutionContext ] = None
133142 ) -> UriPackageOrWrapper :
134143 """Try to resolve the given URI.
135144
136145 Args:
137- options (TryResolveUriOptions[UriPackageOrWrapper ]): The options for resolving the URI.
146+ (TryResolveUriUriPackageOrWrapper ]): The for resolving the URI.
138147
139148 Returns:
140149 UriPackageOrWrapper: The resolved URI, package or wrapper.
141150 """
142- uri = options .uri
143151 uri_resolver = self ._config .resolver
144- resolution_context = options . resolution_context or UriResolutionContext ()
152+ resolution_context = resolution_context or UriResolutionContext ()
145153
146- return await uri_resolver .try_resolve_uri (uri , self , resolution_context )
154+ return uri_resolver .try_resolve_uri (uri , self , resolution_context )
147155
148- async def load_wrapper (
156+ def load_wrapper (
149157 self ,
150158 uri : Uri ,
151- resolution_context : Optional [IUriResolutionContext [ UriPackageOrWrapper ] ] = None ,
152- ) -> Wrapper [ UriPackageOrWrapper ] :
159+ resolution_context : Optional [UriResolutionContext ] = None ,
160+ ) -> Wrapper :
153161 """Load the wrapper for the given URI.
154162
155163 Args:
156164 uri (Uri): The wrapper URI.
157- resolution_context (Optional[IUriResolutionContext[UriPackageOrWrapper] ]):\
165+ resolution_context (Optional[UriResolutionContext ]):\
158166 The resolution context.
159167
160168 Returns:
161- Wrapper[UriPackageOrWrapper] : initialized wrapper instance.
169+ Wrapper: initialized wrapper instance.
162170 """
163171 resolution_context = resolution_context or UriResolutionContext ()
164172
165- uri_package_or_wrapper = await self .try_resolve_uri (
166- TryResolveUriOptions ( uri = uri , resolution_context = resolution_context )
173+ uri_package_or_wrapper = self .try_resolve_uri (
174+ uri = uri , resolution_context = resolution_context
167175 )
168176
169- if isinstance (uri_package_or_wrapper , UriPackage ):
170- return await cast (
171- UriPackage [UriPackageOrWrapper ], uri_package_or_wrapper
172- ).package .create_wrapper ()
173-
174- if isinstance (uri_package_or_wrapper , UriWrapper ):
175- return cast (UriWrapper [UriPackageOrWrapper ], uri_package_or_wrapper ).wrapper
176-
177- raise RuntimeError (
178- dedent (
179- f"""
180- Error resolving URI "{ uri .uri } "
181- URI not found
182- Resolution Stack: {
183- json .dumps (
184- build_clean_uri_history (
185- resolution_context .get_history ()
186- ), indent = 2
177+ match uri_package_or_wrapper :
178+ case UriPackage (uri = uri , package = package ):
179+ return package .create_wrapper ()
180+ case UriWrapper (uri = uri , wrapper = wrapper ):
181+ return wrapper
182+ case _:
183+ raise RuntimeError (
184+ dedent (
185+ f"""
186+ Error resolving URI "{ uri .uri } "
187+ URI not found
188+ Resolution Stack: {
189+ json .dumps (
190+ build_clean_uri_history (
191+ resolution_context .get_history ()
192+ ), indent = 2
193+ )
194+ }
195+ """
187196 )
188- }
189- """
190- )
191- )
197+ )
192198
193- async def invoke (self , options : InvokerOptions [UriPackageOrWrapper ]) -> Any :
199+ def invoke (
200+ self ,
201+ uri : Uri ,
202+ method : str ,
203+ args : Optional [Any ] = None ,
204+ env : Optional [Any ] = None ,
205+ resolution_context : Optional [UriResolutionContext ] = None ,
206+ encode_result : Optional [bool ] = False ,
207+ ) -> Any :
194208 """Invoke the given wrapper URI.
195209
196210 Args:
197- options (InvokerOptions[UriPackageOrWrapper ]): The options for invoking the wrapper.
211+ (InvokerUriPackageOrWrapper ]): The for invoking the wrapper.
198212
199213 Returns:
200214 Any: The result of the invocation.
201215 """
202- resolution_context = options .resolution_context or UriResolutionContext ()
203- wrapper = await self .load_wrapper (
204- options .uri , resolution_context = resolution_context
216+ resolution_context = resolution_context or UriResolutionContext ()
217+ load_wrapper_context = resolution_context .create_sub_history_context ()
218+ wrapper = self .load_wrapper (uri , resolution_context = load_wrapper_context )
219+ wrapper_resolution_path = load_wrapper_context .get_resolution_path ()
220+ wrapper_resolved_uri = wrapper_resolution_path [- 1 ]
221+
222+ resolution_context .track_step (
223+ UriResolutionStep (
224+ source_uri = uri ,
225+ result = UriWrapper (uri = uri , wrapper = wrapper ),
226+ description = "Client.load_wrapper" ,
227+ sub_history = load_wrapper_context .get_history (),
228+ )
205229 )
206- options .env = options .env or self .get_env_by_uri (options .uri )
207230
208- invocable_result = await wrapper .invoke (options , invoker = self )
231+ env = env or get_env_from_resolution_path (
232+ load_wrapper_context .get_resolution_path (), self
233+ )
234+
235+ wrapper_invoke_context = resolution_context .create_sub_history_context ()
209236
210- if options .encode_result and not invocable_result .encoded :
237+ invocable_result = wrapper .invoke (
238+ uri = wrapper_resolved_uri ,
239+ method = method ,
240+ args = args ,
241+ env = env ,
242+ resolution_context = wrapper_invoke_context ,
243+ client = self ,
244+ )
245+
246+ resolution_context .track_step (
247+ UriResolutionStep (
248+ source_uri = wrapper_resolved_uri ,
249+ result = wrapper_resolved_uri ,
250+ description = "Wrapper.invoke" ,
251+ sub_history = wrapper_invoke_context .get_history (),
252+ )
253+ )
254+
255+ if encode_result and not invocable_result .encoded :
211256 encoded = msgpack_encode (invocable_result .result )
212257 return encoded
213258
214259 if (
215- not options . encode_result
260+ not encode_result
216261 and invocable_result .encoded
217262 and isinstance (invocable_result .result , (bytes , bytearray ))
218263 ):
219264 decoded : Any = msgpack_decode (invocable_result .result )
220265 return decoded
221266
222267 return invocable_result .result
268+
269+
270+ __all__ = ["PolywrapClient" ]
0 commit comments