@@ -167,7 +167,7 @@ def __init__(
167
167
def __repr__ (self ):
168
168
return f"<{ type (self ).__name__ } runtime={ self ._runtime !r} code={ str_truncate (self .code , width = 200 )!r} >"
169
169
170
- def get_runtime (self , connection : Connection ) -> str :
170
+ def get_runtime (self , connection : Optional [ Connection ] = None ) -> str :
171
171
return self ._runtime or self ._guess_runtime (connection = connection )
172
172
173
173
@classmethod
@@ -221,7 +221,7 @@ def from_url(
221
221
code = code , runtime = runtime , version = version , context = context , _source = url
222
222
)
223
223
224
- def _guess_runtime (self , connection : Connection ) -> str :
224
+ def _guess_runtime (self , connection : Optional [ Connection ] = None ) -> str :
225
225
"""Guess UDF runtime from UDF source (path) or source code."""
226
226
# First, guess UDF language
227
227
language = None
@@ -240,22 +240,22 @@ def _guess_runtime(self, connection: Connection) -> str:
240
240
# TODO: detection heuristics for R and other languages?
241
241
if not language :
242
242
raise OpenEoClientException ("Failed to detect language of UDF code." )
243
- # Find runtime for language
244
- runtimes = { k . lower (): k for k in connection . list_udf_runtimes (). keys ()}
245
- if language . lower () in runtimes :
246
- return runtimes [ language . lower ()]
247
- else :
248
- raise OpenEoClientException (
249
- f"Failed to match UDF language { language !r } with a runtime ( { runtimes } )"
250
- )
243
+ runtime = language
244
+ if connection :
245
+ # Some additional best-effort validation/normalization of the runtime
246
+ # TODO: this just does some case-normalization, just drop that all together to eliminate
247
+ # the dependency on a connection object. See https://github.com/Open-EO/openeo-api/issues/510
248
+ runtimes = { k . lower (): k for k in connection . list_udf_runtimes (). keys ()}
249
+ runtime = runtimes . get ( runtime . lower (), runtime )
250
+ return runtime
251
251
252
252
def _guess_runtime_from_suffix (self , suffix : str ) -> Union [str ]:
253
253
return {
254
254
".py" : "Python" ,
255
255
".r" : "R" ,
256
256
}.get (suffix .lower ())
257
257
258
- def get_run_udf_callback (self , connection : Connection , data_parameter : str = "data" ) -> PGNode :
258
+ def get_run_udf_callback (self , connection : Optional [ Connection ] = None , data_parameter : str = "data" ) -> PGNode :
259
259
"""
260
260
For internal use: construct `run_udf` node to be used as callback in `apply`, `reduce_dimension`, ...
261
261
"""
@@ -272,18 +272,20 @@ def get_run_udf_callback(self, connection: Connection, data_parameter: str = "da
272
272
def build_child_callback (
273
273
process : Union [str , PGNode , typing .Callable , UDF ],
274
274
parent_parameters : List [str ],
275
- connection : Optional ["openeo. Connection" ] = None ,
275
+ connection : Optional [Connection ] = None ,
276
276
) -> dict :
277
277
"""
278
278
Build a "callback" process: a user defined process that is used by another process (such
279
279
as `apply`, `apply_dimension`, `reduce`, ....)
280
280
281
281
:param process: process id string, PGNode or callable that uses the ProcessBuilder mechanism to build a process
282
282
:param parent_parameters: list of parameter names defined for child process
283
+ :param connection: optional connection object to improve runtime validation for UDFs
283
284
:return:
284
285
"""
285
286
# TODO: move this to more generic process graph building utility module
286
287
# TODO: autodetect the parameters defined by parent process?
288
+ # TODO: eliminate need for connection object (also see `UDF._guess_runtime`)
287
289
if isinstance (process , PGNode ):
288
290
# Assume this is already a valid callback process
289
291
pg = process
0 commit comments