ob-metaflow 2.11.4.9__py2.py3-none-any.whl → 2.11.9.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ob-metaflow might be problematic. Click here for more details.
- metaflow/cli.py +15 -10
- metaflow/clone_util.py +71 -0
- metaflow/cmd/develop/stub_generator.py +2 -0
- metaflow/cmd/develop/stubs.py +17 -8
- metaflow/metaflow_config.py +3 -0
- metaflow/package.py +4 -3
- metaflow/parameters.py +2 -2
- metaflow/plugins/aws/batch/batch.py +12 -0
- metaflow/plugins/aws/batch/batch_cli.py +25 -0
- metaflow/plugins/aws/batch/batch_client.py +40 -0
- metaflow/plugins/aws/batch/batch_decorator.py +32 -1
- metaflow/plugins/aws/step_functions/step_functions.py +3 -0
- metaflow/plugins/datatools/s3/s3op.py +4 -3
- metaflow/plugins/env_escape/client.py +154 -27
- metaflow/plugins/env_escape/client_modules.py +15 -47
- metaflow/plugins/env_escape/configurations/emulate_test_lib/overrides.py +31 -42
- metaflow/plugins/env_escape/configurations/emulate_test_lib/server_mappings.py +8 -3
- metaflow/plugins/env_escape/configurations/test_lib_impl/test_lib.py +74 -22
- metaflow/plugins/env_escape/consts.py +1 -0
- metaflow/plugins/env_escape/exception_transferer.py +46 -112
- metaflow/plugins/env_escape/override_decorators.py +8 -8
- metaflow/plugins/env_escape/server.py +42 -5
- metaflow/plugins/env_escape/stub.py +168 -23
- metaflow/plugins/env_escape/utils.py +3 -3
- metaflow/plugins/gcp/gcp_secret_manager_secrets_provider.py +3 -2
- metaflow/plugins/pypi/conda_environment.py +9 -0
- metaflow/plugins/pypi/pip.py +17 -2
- metaflow/runtime.py +252 -61
- metaflow/sidecar/sidecar.py +11 -1
- metaflow/sidecar/sidecar_subprocess.py +34 -18
- metaflow/task.py +28 -54
- metaflow/version.py +1 -1
- {ob_metaflow-2.11.4.9.dist-info → ob_metaflow-2.11.9.1.dist-info}/METADATA +2 -2
- {ob_metaflow-2.11.4.9.dist-info → ob_metaflow-2.11.9.1.dist-info}/RECORD +38 -37
- {ob_metaflow-2.11.4.9.dist-info → ob_metaflow-2.11.9.1.dist-info}/WHEEL +1 -1
- {ob_metaflow-2.11.4.9.dist-info → ob_metaflow-2.11.9.1.dist-info}/LICENSE +0 -0
- {ob_metaflow-2.11.4.9.dist-info → ob_metaflow-2.11.9.1.dist-info}/entry_points.txt +0 -0
- {ob_metaflow-2.11.4.9.dist-info → ob_metaflow-2.11.9.1.dist-info}/top_level.txt +0 -0
|
@@ -34,8 +34,12 @@ from .communication.channel import Channel
|
|
|
34
34
|
from .communication.socket_bytestream import SocketByteStream
|
|
35
35
|
|
|
36
36
|
from .data_transferer import DataTransferer, ObjReference
|
|
37
|
-
from .exception_transferer import load_exception
|
|
38
|
-
from .override_decorators import
|
|
37
|
+
from .exception_transferer import ExceptionMetaClass, load_exception
|
|
38
|
+
from .override_decorators import (
|
|
39
|
+
LocalAttrOverride,
|
|
40
|
+
LocalExceptionDeserializer,
|
|
41
|
+
LocalOverride,
|
|
42
|
+
)
|
|
39
43
|
from .stub import create_class
|
|
40
44
|
from .utils import get_canonical_name
|
|
41
45
|
|
|
@@ -193,28 +197,41 @@ class Client(object):
|
|
|
193
197
|
self._proxied_classes = {
|
|
194
198
|
k: None
|
|
195
199
|
for k in itertools.chain(
|
|
196
|
-
response[FIELD_CONTENT]["classes"],
|
|
200
|
+
response[FIELD_CONTENT]["classes"],
|
|
201
|
+
response[FIELD_CONTENT]["proxied"],
|
|
202
|
+
(e[0] for e in response[FIELD_CONTENT]["exceptions"]),
|
|
197
203
|
)
|
|
198
204
|
}
|
|
199
205
|
|
|
206
|
+
self._exception_hierarchy = dict(response[FIELD_CONTENT]["exceptions"])
|
|
207
|
+
self._proxied_classnames = set(response[FIELD_CONTENT]["classes"]).union(
|
|
208
|
+
response[FIELD_CONTENT]["proxied"]
|
|
209
|
+
)
|
|
210
|
+
self._aliases = response[FIELD_CONTENT]["aliases"]
|
|
211
|
+
|
|
200
212
|
# Determine all overrides
|
|
201
213
|
self._overrides = {}
|
|
202
214
|
self._getattr_overrides = {}
|
|
203
215
|
self._setattr_overrides = {}
|
|
204
|
-
self.
|
|
216
|
+
self._exception_deserializers = {}
|
|
205
217
|
for override in override_values:
|
|
206
218
|
if isinstance(override, (LocalOverride, LocalAttrOverride)):
|
|
207
219
|
for obj_name, obj_funcs in override.obj_mapping.items():
|
|
208
|
-
|
|
220
|
+
canonical_name = get_canonical_name(obj_name, self._aliases)
|
|
221
|
+
if canonical_name not in self._proxied_classes:
|
|
209
222
|
raise ValueError(
|
|
210
223
|
"%s does not refer to a proxied or override type" % obj_name
|
|
211
224
|
)
|
|
212
225
|
if isinstance(override, LocalOverride):
|
|
213
|
-
override_dict = self._overrides.setdefault(
|
|
226
|
+
override_dict = self._overrides.setdefault(canonical_name, {})
|
|
214
227
|
elif override.is_setattr:
|
|
215
|
-
override_dict = self._setattr_overrides.setdefault(
|
|
228
|
+
override_dict = self._setattr_overrides.setdefault(
|
|
229
|
+
canonical_name, {}
|
|
230
|
+
)
|
|
216
231
|
else:
|
|
217
|
-
override_dict = self._getattr_overrides.setdefault(
|
|
232
|
+
override_dict = self._getattr_overrides.setdefault(
|
|
233
|
+
canonical_name, {}
|
|
234
|
+
)
|
|
218
235
|
if isinstance(obj_funcs, str):
|
|
219
236
|
obj_funcs = (obj_funcs,)
|
|
220
237
|
for name in obj_funcs:
|
|
@@ -223,11 +240,18 @@ class Client(object):
|
|
|
223
240
|
"%s was already overridden for %s" % (name, obj_name)
|
|
224
241
|
)
|
|
225
242
|
override_dict[name] = override.func
|
|
226
|
-
if isinstance(override,
|
|
227
|
-
|
|
228
|
-
if
|
|
229
|
-
raise ValueError(
|
|
230
|
-
|
|
243
|
+
if isinstance(override, LocalExceptionDeserializer):
|
|
244
|
+
canonical_name = get_canonical_name(override.class_path, self._aliases)
|
|
245
|
+
if canonical_name not in self._exception_hierarchy:
|
|
246
|
+
raise ValueError(
|
|
247
|
+
"%s does not refer to an exception type" % override.class_path
|
|
248
|
+
)
|
|
249
|
+
cur_des = self._exception_deserializers.get(canonical_name, None)
|
|
250
|
+
if cur_des is not None:
|
|
251
|
+
raise ValueError(
|
|
252
|
+
"Exception %s has multiple deserializers" % override.class_path
|
|
253
|
+
)
|
|
254
|
+
self._exception_deserializers[canonical_name] = override.deserializer
|
|
231
255
|
|
|
232
256
|
# Proxied standalone functions are functions that are proxied
|
|
233
257
|
# as part of other objects like defaultdict for which we create a
|
|
@@ -243,8 +267,6 @@ class Client(object):
|
|
|
243
267
|
"aliases": response[FIELD_CONTENT]["aliases"],
|
|
244
268
|
}
|
|
245
269
|
|
|
246
|
-
self._aliases = response[FIELD_CONTENT]["aliases"]
|
|
247
|
-
|
|
248
270
|
def __del__(self):
|
|
249
271
|
self.cleanup()
|
|
250
272
|
|
|
@@ -288,8 +310,9 @@ class Client(object):
|
|
|
288
310
|
def get_exports(self):
|
|
289
311
|
return self._export_info
|
|
290
312
|
|
|
291
|
-
def
|
|
292
|
-
|
|
313
|
+
def get_exception_deserializer(self, name):
|
|
314
|
+
cannonical_name = get_canonical_name(name, self._aliases)
|
|
315
|
+
return self._exception_deserializers.get(cannonical_name)
|
|
293
316
|
|
|
294
317
|
def stub_request(self, stub, request_type, *args, **kwargs):
|
|
295
318
|
# Encode the operation to send over the wire and wait for the response
|
|
@@ -313,7 +336,7 @@ class Client(object):
|
|
|
313
336
|
if response_type == MSG_REPLY:
|
|
314
337
|
return self.decode(response[FIELD_CONTENT])
|
|
315
338
|
elif response_type == MSG_EXCEPTION:
|
|
316
|
-
raise load_exception(self
|
|
339
|
+
raise load_exception(self, response[FIELD_CONTENT])
|
|
317
340
|
elif response_type == MSG_INTERNAL_ERROR:
|
|
318
341
|
raise RuntimeError(
|
|
319
342
|
"Error in the server runtime:\n\n===== SERVER TRACEBACK =====\n%s"
|
|
@@ -334,10 +357,27 @@ class Client(object):
|
|
|
334
357
|
# this connection will be converted to a local stub.
|
|
335
358
|
return self._datatransferer.load(json_obj)
|
|
336
359
|
|
|
337
|
-
def get_local_class(
|
|
360
|
+
def get_local_class(
|
|
361
|
+
self, name, obj_id=None, is_returned_exception=False, is_parent=False
|
|
362
|
+
):
|
|
338
363
|
# Gets (and creates if needed), the class mapping to the remote
|
|
339
364
|
# class of name 'name'.
|
|
365
|
+
|
|
366
|
+
# We actually deal with four types of classes:
|
|
367
|
+
# - proxied functions
|
|
368
|
+
# - classes that are proxied regular classes AND proxied exceptions
|
|
369
|
+
# - classes that are proxied regular classes AND NOT proxied exceptions
|
|
370
|
+
# - classes that are NOT proxied regular classes AND are proxied exceptions
|
|
340
371
|
name = get_canonical_name(name, self._aliases)
|
|
372
|
+
|
|
373
|
+
def name_to_parent_name(name):
|
|
374
|
+
return "parent:%s" % name
|
|
375
|
+
|
|
376
|
+
if is_parent:
|
|
377
|
+
lookup_name = name_to_parent_name(name)
|
|
378
|
+
else:
|
|
379
|
+
lookup_name = name
|
|
380
|
+
|
|
341
381
|
if name == "function":
|
|
342
382
|
# Special handling of pickled functions. We create a new class that
|
|
343
383
|
# simply has a __call__ method that will forward things back to
|
|
@@ -346,17 +386,87 @@ class Client(object):
|
|
|
346
386
|
raise RuntimeError("Local function unpickling without an object ID")
|
|
347
387
|
if obj_id not in self._proxied_standalone_functions:
|
|
348
388
|
self._proxied_standalone_functions[obj_id] = create_class(
|
|
349
|
-
self,
|
|
389
|
+
self,
|
|
390
|
+
"__main__.__function_%s" % obj_id,
|
|
391
|
+
{},
|
|
392
|
+
{},
|
|
393
|
+
{},
|
|
394
|
+
{"__call__": ""},
|
|
395
|
+
[],
|
|
350
396
|
)
|
|
351
397
|
return self._proxied_standalone_functions[obj_id]
|
|
398
|
+
local_class = self._proxied_classes.get(lookup_name, None)
|
|
399
|
+
if local_class is not None:
|
|
400
|
+
return local_class
|
|
401
|
+
|
|
402
|
+
is_proxied_exception = name in self._exception_hierarchy
|
|
403
|
+
is_proxied_non_exception = name in self._proxied_classnames
|
|
404
|
+
|
|
405
|
+
if not is_proxied_exception and not is_proxied_non_exception:
|
|
406
|
+
if is_returned_exception or is_parent:
|
|
407
|
+
# In this case, it may be a local exception that we need to
|
|
408
|
+
# recreate
|
|
409
|
+
try:
|
|
410
|
+
ex_module, ex_name = name.rsplit(".", 1)
|
|
411
|
+
__import__(ex_module, None, None, "*")
|
|
412
|
+
except Exception:
|
|
413
|
+
pass
|
|
414
|
+
if ex_module in sys.modules and issubclass(
|
|
415
|
+
getattr(sys.modules[ex_module], ex_name), BaseException
|
|
416
|
+
):
|
|
417
|
+
# This is a local exception that we can recreate
|
|
418
|
+
local_exception = getattr(sys.modules[ex_module], ex_name)
|
|
419
|
+
wrapped_exception = ExceptionMetaClass(
|
|
420
|
+
ex_name,
|
|
421
|
+
(local_exception,),
|
|
422
|
+
dict(getattr(local_exception, "__dict__", {})),
|
|
423
|
+
)
|
|
424
|
+
wrapped_exception.__module__ = ex_module
|
|
425
|
+
self._proxied_classes[lookup_name] = wrapped_exception
|
|
426
|
+
return wrapped_exception
|
|
352
427
|
|
|
353
|
-
if name not in self._proxied_classes:
|
|
354
428
|
raise ValueError("Class '%s' is not known" % name)
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
429
|
+
|
|
430
|
+
# At this stage:
|
|
431
|
+
# - we don't have a local_class for this
|
|
432
|
+
# - it is not an inbuilt exception so it is either a proxied exception, a
|
|
433
|
+
# proxied class or a proxied object that is both an exception and a class.
|
|
434
|
+
|
|
435
|
+
parents = []
|
|
436
|
+
if is_proxied_exception:
|
|
437
|
+
# If exception, we need to get the parents from the exception
|
|
438
|
+
ex_parents = self._exception_hierarchy[name]
|
|
439
|
+
for parent in ex_parents:
|
|
440
|
+
# We always consider it to be an exception so that we wrap even non
|
|
441
|
+
# proxied builtins exceptions
|
|
442
|
+
parents.append(self.get_local_class(parent, is_parent=True))
|
|
443
|
+
# For regular classes, we get what it exposes from the server
|
|
444
|
+
if is_proxied_non_exception:
|
|
359
445
|
remote_methods = self.stub_request(None, OP_GETMETHODS, name)
|
|
446
|
+
else:
|
|
447
|
+
remote_methods = {}
|
|
448
|
+
|
|
449
|
+
parent_local_class = None
|
|
450
|
+
local_class = None
|
|
451
|
+
if is_proxied_exception:
|
|
452
|
+
# If we are a proxied exception AND a proxied class, we create two classes:
|
|
453
|
+
# actually:
|
|
454
|
+
# - the class itself (which is a stub)
|
|
455
|
+
# - the class in the capacity of a parent class (to another exception
|
|
456
|
+
# presumably). The reason for this is that if we have an exception/proxied
|
|
457
|
+
# class A and another B and B inherits from A, the MRO order would be all
|
|
458
|
+
# wrong since both A and B would also inherit from `Stub`. Here what we
|
|
459
|
+
# do is:
|
|
460
|
+
# - A_parent inherits from the actual parents of A (let's assume a
|
|
461
|
+
# builtin exception)
|
|
462
|
+
# - A inherits from (Stub, A_parent)
|
|
463
|
+
# - B_parent inherits from A_parent and the builtin Exception
|
|
464
|
+
# - B inherits from (Stub, B_parent)
|
|
465
|
+
ex_module, ex_name = name.rsplit(".", 1)
|
|
466
|
+
parent_local_class = ExceptionMetaClass(ex_name, (*parents,), {})
|
|
467
|
+
parent_local_class.__module__ = ex_module
|
|
468
|
+
|
|
469
|
+
if is_proxied_non_exception:
|
|
360
470
|
local_class = create_class(
|
|
361
471
|
self,
|
|
362
472
|
name,
|
|
@@ -364,9 +474,26 @@ class Client(object):
|
|
|
364
474
|
self._getattr_overrides.get(name, {}),
|
|
365
475
|
self._setattr_overrides.get(name, {}),
|
|
366
476
|
remote_methods,
|
|
477
|
+
(parent_local_class,) if parent_local_class else None,
|
|
367
478
|
)
|
|
479
|
+
if parent_local_class:
|
|
480
|
+
self._proxied_classes[name_to_parent_name(name)] = parent_local_class
|
|
481
|
+
if local_class:
|
|
368
482
|
self._proxied_classes[name] = local_class
|
|
369
|
-
|
|
483
|
+
else:
|
|
484
|
+
# This is for the case of pure proxied exceptions -- we want the lookup of
|
|
485
|
+
# foo.MyException to be the same class as looking of foo.MyException as a parent
|
|
486
|
+
# of another exception so `isinstance` works properly
|
|
487
|
+
self._proxied_classes[name] = parent_local_class
|
|
488
|
+
|
|
489
|
+
if is_parent:
|
|
490
|
+
# This should never happen but making sure
|
|
491
|
+
if not parent_local_class:
|
|
492
|
+
raise RuntimeError(
|
|
493
|
+
"Exception parent class %s is not a proxied exception" % name
|
|
494
|
+
)
|
|
495
|
+
return parent_local_class
|
|
496
|
+
return self._proxied_classes[name]
|
|
370
497
|
|
|
371
498
|
def can_pickle(self, obj):
|
|
372
499
|
return getattr(obj, "___connection___", None) == self
|
|
@@ -395,7 +522,7 @@ class Client(object):
|
|
|
395
522
|
obj_id = obj.identifier
|
|
396
523
|
local_instance = self._proxied_objects.get(obj_id)
|
|
397
524
|
if not local_instance:
|
|
398
|
-
local_class = self.get_local_class(remote_class_name, obj_id)
|
|
525
|
+
local_class = self.get_local_class(remote_class_name, obj_id=obj_id)
|
|
399
526
|
local_instance = local_class(self, remote_class_name, obj_id)
|
|
400
527
|
return local_instance
|
|
401
528
|
|
|
@@ -7,7 +7,6 @@ import sys
|
|
|
7
7
|
|
|
8
8
|
from .consts import OP_CALLFUNC, OP_GETVAL, OP_SETVAL
|
|
9
9
|
from .client import Client
|
|
10
|
-
from .override_decorators import LocalException
|
|
11
10
|
from .utils import get_canonical_name
|
|
12
11
|
|
|
13
12
|
|
|
@@ -16,7 +15,7 @@ def _clean_client(client):
|
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
class _WrappedModule(object):
|
|
19
|
-
def __init__(self, loader, prefix, exports,
|
|
18
|
+
def __init__(self, loader, prefix, exports, client):
|
|
20
19
|
self._loader = loader
|
|
21
20
|
self._prefix = prefix
|
|
22
21
|
self._client = client
|
|
@@ -24,19 +23,20 @@ class _WrappedModule(object):
|
|
|
24
23
|
r"^%s\.([a-zA-Z_][a-zA-Z0-9_]*)$" % prefix.replace(".", r"\.") # noqa W605
|
|
25
24
|
)
|
|
26
25
|
self._exports = {}
|
|
27
|
-
self._aliases = exports
|
|
26
|
+
self._aliases = exports.get("aliases", [])
|
|
28
27
|
for k in ("classes", "functions", "values"):
|
|
29
28
|
result = []
|
|
30
|
-
for item in exports[
|
|
29
|
+
for item in exports.get(k, []):
|
|
31
30
|
m = is_match.match(item)
|
|
32
31
|
if m:
|
|
33
32
|
result.append(m.group(1))
|
|
34
33
|
self._exports[k] = result
|
|
35
|
-
|
|
36
|
-
for
|
|
37
|
-
m = is_match.match(
|
|
34
|
+
result = []
|
|
35
|
+
for item, _ in exports.get("exceptions", []):
|
|
36
|
+
m = is_match.match(item)
|
|
38
37
|
if m:
|
|
39
|
-
|
|
38
|
+
result.append(m.group(1))
|
|
39
|
+
self._exports["exceptions"] = result
|
|
40
40
|
|
|
41
41
|
def __getattr__(self, name):
|
|
42
42
|
if name == "__loader__":
|
|
@@ -50,8 +50,8 @@ class _WrappedModule(object):
|
|
|
50
50
|
name = get_canonical_name(self._prefix + "." + name, self._aliases)[
|
|
51
51
|
len(self._prefix) + 1 :
|
|
52
52
|
]
|
|
53
|
-
if name in self._exports["classes"]:
|
|
54
|
-
# We load classes lazily
|
|
53
|
+
if name in self._exports["classes"] or name in self._exports["exceptions"]:
|
|
54
|
+
# We load classes and exceptions lazily
|
|
55
55
|
return self._client.get_local_class("%s.%s" % (self._prefix, name))
|
|
56
56
|
elif name in self._exports["functions"]:
|
|
57
57
|
# TODO: Grab doc back from the remote side like in _make_method
|
|
@@ -67,8 +67,6 @@ class _WrappedModule(object):
|
|
|
67
67
|
return self._client.stub_request(
|
|
68
68
|
None, OP_GETVAL, "%s.%s" % (self._prefix, name)
|
|
69
69
|
)
|
|
70
|
-
elif name in self._exception_classes:
|
|
71
|
-
return self._exception_classes[name]
|
|
72
70
|
else:
|
|
73
71
|
# Try to see if this is a submodule that we can load
|
|
74
72
|
m = None
|
|
@@ -173,7 +171,6 @@ class ModuleImporter(object):
|
|
|
173
171
|
|
|
174
172
|
# Get information about overrides and what the server knows about
|
|
175
173
|
exports = self._client.get_exports()
|
|
176
|
-
ex_overrides = self._client.get_local_exception_overrides()
|
|
177
174
|
|
|
178
175
|
prefixes = set()
|
|
179
176
|
export_classes = exports.get("classes", [])
|
|
@@ -182,42 +179,13 @@ class ModuleImporter(object):
|
|
|
182
179
|
export_exceptions = exports.get("exceptions", [])
|
|
183
180
|
self._aliases = exports.get("aliases", {})
|
|
184
181
|
for name in itertools.chain(
|
|
185
|
-
export_classes,
|
|
182
|
+
export_classes,
|
|
183
|
+
export_functions,
|
|
184
|
+
export_values,
|
|
185
|
+
(e[0] for e in export_exceptions),
|
|
186
186
|
):
|
|
187
187
|
splits = name.rsplit(".", 1)
|
|
188
188
|
prefixes.add(splits[0])
|
|
189
|
-
|
|
190
|
-
# Now look at the exceptions coming from the server
|
|
191
|
-
formed_exception_classes = {}
|
|
192
|
-
for ex_name, ex_parents in export_exceptions:
|
|
193
|
-
# Exception is a tuple (name, (parents,))
|
|
194
|
-
# Exceptions are also given in order of instantiation (ie: the
|
|
195
|
-
# server already topologically sorted them)
|
|
196
|
-
ex_class_dict = ex_overrides.get(ex_name, None)
|
|
197
|
-
if ex_class_dict is None:
|
|
198
|
-
ex_class_dict = {}
|
|
199
|
-
else:
|
|
200
|
-
ex_class_dict = dict(ex_class_dict.__dict__)
|
|
201
|
-
parents = []
|
|
202
|
-
for fake_base in ex_parents:
|
|
203
|
-
if fake_base.startswith("builtins."):
|
|
204
|
-
# This is something we know of here
|
|
205
|
-
parents.append(eval(fake_base[9:]))
|
|
206
|
-
else:
|
|
207
|
-
# It's in formed_classes
|
|
208
|
-
parents.append(formed_exception_classes[fake_base])
|
|
209
|
-
splits = ex_name.rsplit(".", 1)
|
|
210
|
-
ex_class_dict["__user_defined__"] = set(ex_class_dict.keys())
|
|
211
|
-
new_class = type(splits[1], tuple(parents), ex_class_dict)
|
|
212
|
-
new_class.__module__ = splits[0]
|
|
213
|
-
new_class.__name__ = splits[1]
|
|
214
|
-
formed_exception_classes[ex_name] = new_class
|
|
215
|
-
|
|
216
|
-
# Now update prefixes as needed
|
|
217
|
-
for name in formed_exception_classes:
|
|
218
|
-
splits = name.rsplit(".", 1)
|
|
219
|
-
prefixes.add(splits[0])
|
|
220
|
-
|
|
221
189
|
# We will make sure that we create modules even for "empty" prefixes
|
|
222
190
|
# because packages are always loaded hierarchically so if we have
|
|
223
191
|
# something in `a.b.c` but nothing directly in `a`, we still need to
|
|
@@ -235,7 +203,7 @@ class ModuleImporter(object):
|
|
|
235
203
|
self._handled_modules = {}
|
|
236
204
|
for prefix in prefixes:
|
|
237
205
|
self._handled_modules[prefix] = _WrappedModule(
|
|
238
|
-
self, prefix, exports,
|
|
206
|
+
self, prefix, exports, self._client
|
|
239
207
|
)
|
|
240
208
|
canonical_fullname = get_canonical_name(fullname, self._aliases)
|
|
241
209
|
# Modules are created canonically but we need to return something for any
|
|
@@ -5,56 +5,44 @@ from metaflow.plugins.env_escape.override_decorators import (
|
|
|
5
5
|
remote_override,
|
|
6
6
|
remote_getattr_override,
|
|
7
7
|
remote_setattr_override,
|
|
8
|
-
|
|
8
|
+
local_exception_deserialize,
|
|
9
9
|
remote_exception_serialize,
|
|
10
10
|
)
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
@local_override({"test_lib.TestClass1": "print_value"})
|
|
14
14
|
def local_print_value(stub, func):
|
|
15
|
-
print("Encoding before sending to server")
|
|
16
15
|
v = func()
|
|
17
|
-
print("Adding 5")
|
|
18
16
|
return v + 5
|
|
19
17
|
|
|
20
18
|
|
|
21
19
|
@remote_override({"test_lib.TestClass1": "print_value"})
|
|
22
20
|
def remote_print_value(obj, func):
|
|
23
|
-
print("Decoding from client")
|
|
24
21
|
v = func()
|
|
25
|
-
|
|
26
|
-
return v
|
|
22
|
+
return v + 3
|
|
27
23
|
|
|
28
24
|
|
|
29
25
|
@local_getattr_override({"test_lib.TestClass1": "override_value"})
|
|
30
26
|
def local_get_value2(stub, name, func):
|
|
31
|
-
print("In local getattr override for %s" % name)
|
|
32
27
|
r = func()
|
|
33
|
-
|
|
34
|
-
return r
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
@local_setattr_override({"test_lib.TestClass1": "override_value"})
|
|
38
|
-
def local_set_value2(stub, name, func, v):
|
|
39
|
-
print("In local setattr override for %s" % name)
|
|
40
|
-
r = func(v)
|
|
41
|
-
print("In local setattr override, got %s" % r)
|
|
42
|
-
return r
|
|
28
|
+
return r + 5
|
|
43
29
|
|
|
44
30
|
|
|
45
31
|
@remote_getattr_override({"test_lib.TestClass1": "override_value"})
|
|
46
32
|
def remote_get_value2(obj, name):
|
|
47
|
-
print("In remote getattr override for %s" % name)
|
|
48
33
|
r = getattr(obj, name)
|
|
49
|
-
|
|
34
|
+
return r + 3
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@local_setattr_override({"test_lib.TestClass1": "override_value"})
|
|
38
|
+
def local_set_value2(stub, name, func, v):
|
|
39
|
+
r = func(v + 5)
|
|
50
40
|
return r
|
|
51
41
|
|
|
52
42
|
|
|
53
43
|
@remote_setattr_override({"test_lib.TestClass1": "override_value"})
|
|
54
44
|
def remote_set_value2(obj, name, v):
|
|
55
|
-
|
|
56
|
-
r = setattr(obj, name, v)
|
|
57
|
-
print("In remote setattr override, got %s" % r)
|
|
45
|
+
r = setattr(obj, name, v + 3)
|
|
58
46
|
return r
|
|
59
47
|
|
|
60
48
|
|
|
@@ -63,30 +51,31 @@ def unsupported_method(stub, func, *args, **kwargs):
|
|
|
63
51
|
return NotImplementedError("Just because")
|
|
64
52
|
|
|
65
53
|
|
|
66
|
-
@
|
|
67
|
-
def
|
|
68
|
-
|
|
69
|
-
v = func(val)
|
|
70
|
-
return v
|
|
54
|
+
@local_exception_deserialize("test_lib.SomeException")
|
|
55
|
+
def some_exception_deserialize(ex, json_obj):
|
|
56
|
+
ex.user_value = json_obj
|
|
71
57
|
|
|
72
58
|
|
|
73
|
-
@
|
|
74
|
-
def
|
|
75
|
-
|
|
76
|
-
v = func(val)
|
|
77
|
-
return v
|
|
59
|
+
@remote_exception_serialize("test_lib.SomeException")
|
|
60
|
+
def some_exception_serialize(ex):
|
|
61
|
+
return 42
|
|
78
62
|
|
|
79
63
|
|
|
80
|
-
@
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
parent_val = super(self.__realclass__, self).__str__()
|
|
84
|
-
return parent_val + " In SomeException str override: %s" % self.user_value
|
|
64
|
+
@local_exception_deserialize("test_lib.ExceptionAndClass")
|
|
65
|
+
def exception_and_class_deserialize(ex, json_obj):
|
|
66
|
+
ex.user_value = json_obj
|
|
85
67
|
|
|
86
|
-
def _deserialize_user(self, json_obj):
|
|
87
|
-
self.user_value = json_obj
|
|
88
68
|
|
|
69
|
+
@remote_exception_serialize("test_lib.ExceptionAndClass")
|
|
70
|
+
def exception_and_class_serialize(ex):
|
|
71
|
+
return 43
|
|
89
72
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
73
|
+
|
|
74
|
+
@local_exception_deserialize("test_lib.ExceptionAndClassChild")
|
|
75
|
+
def exception_and_class_child_deserialize(ex, json_obj):
|
|
76
|
+
ex.user_value = json_obj
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@remote_exception_serialize("test_lib.ExceptionAndClassChild")
|
|
80
|
+
def exception_and_class_child_serialize(ex):
|
|
81
|
+
return 44
|
|
@@ -10,17 +10,22 @@ sys.path.append(
|
|
|
10
10
|
import test_lib as lib
|
|
11
11
|
|
|
12
12
|
EXPORTED_CLASSES = {
|
|
13
|
-
"test_lib": {
|
|
13
|
+
("test_lib", "test_lib.alias"): {
|
|
14
14
|
"TestClass1": lib.TestClass1,
|
|
15
15
|
"TestClass2": lib.TestClass2,
|
|
16
|
-
"
|
|
16
|
+
"BaseClass": lib.BaseClass,
|
|
17
|
+
"ChildClass": lib.ChildClass,
|
|
18
|
+
"ExceptionAndClass": lib.ExceptionAndClass,
|
|
19
|
+
"ExceptionAndClassChild": lib.ExceptionAndClassChild,
|
|
17
20
|
}
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
EXPORTED_EXCEPTIONS = {
|
|
21
|
-
"test_lib": {
|
|
24
|
+
("test_lib", "test_lib.alias"): {
|
|
22
25
|
"SomeException": lib.SomeException,
|
|
23
26
|
"MyBaseException": lib.MyBaseException,
|
|
27
|
+
"ExceptionAndClass": lib.ExceptionAndClass,
|
|
28
|
+
"ExceptionAndClassChild": lib.ExceptionAndClassChild,
|
|
24
29
|
}
|
|
25
30
|
}
|
|
26
31
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import functools
|
|
2
|
+
from html.parser import HTMLParser
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
class MyBaseException(Exception):
|
|
@@ -9,8 +10,48 @@ class SomeException(MyBaseException):
|
|
|
9
10
|
pass
|
|
10
11
|
|
|
11
12
|
|
|
12
|
-
class
|
|
13
|
+
class ExceptionAndClass(MyBaseException):
|
|
14
|
+
def __init__(self, *args):
|
|
15
|
+
super().__init__(*args)
|
|
16
|
+
|
|
17
|
+
def method_on_exception(self):
|
|
18
|
+
return "method_on_exception"
|
|
19
|
+
|
|
20
|
+
def __str__(self):
|
|
21
|
+
return "ExceptionAndClass Str: %s" % super().__str__()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ExceptionAndClassChild(ExceptionAndClass):
|
|
25
|
+
def __init__(self, *args):
|
|
26
|
+
super().__init__(*args)
|
|
27
|
+
|
|
28
|
+
def method_on_child_exception(self):
|
|
29
|
+
return "method_on_child_exception"
|
|
30
|
+
|
|
31
|
+
def __str__(self):
|
|
32
|
+
return "ExceptionAndClassChild Str: %s" % super().__str__()
|
|
33
|
+
|
|
13
34
|
|
|
35
|
+
class BaseClass(HTMLParser):
|
|
36
|
+
def __init__(self, *args, **kwargs):
|
|
37
|
+
super().__init__(*args, **kwargs)
|
|
38
|
+
self._output = []
|
|
39
|
+
|
|
40
|
+
def handle_starttag(self, tag, attrs):
|
|
41
|
+
self._output.append(tag)
|
|
42
|
+
return super().handle_starttag(tag, attrs)
|
|
43
|
+
|
|
44
|
+
def get_output(self):
|
|
45
|
+
return self._output
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class ChildClass(BaseClass):
|
|
49
|
+
def handle_endtag(self, tag):
|
|
50
|
+
self._output.append(tag)
|
|
51
|
+
return super().handle_endtag(tag)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class TestClass1(object):
|
|
14
55
|
cls_object = 25
|
|
15
56
|
|
|
16
57
|
def __init__(self, value):
|
|
@@ -41,11 +82,11 @@ class TestClass1(object):
|
|
|
41
82
|
return TestClass2(self._value, stride, count)
|
|
42
83
|
|
|
43
84
|
@staticmethod
|
|
44
|
-
def
|
|
85
|
+
def static_method(val):
|
|
45
86
|
return val + 42
|
|
46
87
|
|
|
47
88
|
@classmethod
|
|
48
|
-
def
|
|
89
|
+
def class_method(cls):
|
|
49
90
|
return cls.cls_object
|
|
50
91
|
|
|
51
92
|
@property
|
|
@@ -56,13 +97,42 @@ class TestClass1(object):
|
|
|
56
97
|
def override_value(self, value):
|
|
57
98
|
self._value2 = value
|
|
58
99
|
|
|
100
|
+
def __hidden(self, name, value):
|
|
101
|
+
setattr(self, name, value)
|
|
102
|
+
|
|
103
|
+
def weird_indirection(self, name):
|
|
104
|
+
return functools.partial(self.__hidden, name)
|
|
105
|
+
|
|
106
|
+
def returnChild(self):
|
|
107
|
+
return ChildClass()
|
|
108
|
+
|
|
109
|
+
def raiseOrReturnValueError(self, doRaise=False):
|
|
110
|
+
if doRaise:
|
|
111
|
+
raise ValueError("I raised")
|
|
112
|
+
return ValueError("I returned")
|
|
113
|
+
|
|
114
|
+
def raiseOrReturnSomeException(self, doRaise=False):
|
|
115
|
+
if doRaise:
|
|
116
|
+
raise SomeException("I raised")
|
|
117
|
+
return SomeException("I returned")
|
|
118
|
+
|
|
119
|
+
def raiseOrReturnExceptionAndClass(self, doRaise=False):
|
|
120
|
+
if doRaise:
|
|
121
|
+
raise ExceptionAndClass("I raised")
|
|
122
|
+
return ExceptionAndClass("I returned")
|
|
123
|
+
|
|
124
|
+
def raiseOrReturnExceptionAndClassChild(self, doRaise=False):
|
|
125
|
+
if doRaise:
|
|
126
|
+
raise ExceptionAndClassChild("I raised")
|
|
127
|
+
return ExceptionAndClassChild("I returned")
|
|
128
|
+
|
|
59
129
|
|
|
60
130
|
class TestClass2(object):
|
|
61
131
|
def __init__(self, value, stride, count):
|
|
62
132
|
self._mylist = [value + stride * i for i in range(count)]
|
|
63
133
|
|
|
64
134
|
def something(self, val):
|
|
65
|
-
return "
|
|
135
|
+
return "Test2:Something:%s" % val
|
|
66
136
|
|
|
67
137
|
def __iter__(self):
|
|
68
138
|
self._pos = 0
|
|
@@ -75,24 +145,6 @@ class TestClass2(object):
|
|
|
75
145
|
raise StopIteration
|
|
76
146
|
|
|
77
147
|
|
|
78
|
-
class TestClass3(object):
|
|
79
|
-
def __init__(self):
|
|
80
|
-
print("I am Class3")
|
|
81
|
-
|
|
82
|
-
def thirdfunction(self, val):
|
|
83
|
-
print("Got value: %s" % val)
|
|
84
|
-
# raise AttributeError("Some weird error")
|
|
85
|
-
|
|
86
|
-
def raiseSomething(self):
|
|
87
|
-
raise SomeException("Something went wrong")
|
|
88
|
-
|
|
89
|
-
def __hidden(self, name, value):
|
|
90
|
-
setattr(self, name, value)
|
|
91
|
-
|
|
92
|
-
def weird_indirection(self, name):
|
|
93
|
-
return functools.partial(self.__hidden, name)
|
|
94
|
-
|
|
95
|
-
|
|
96
148
|
def test_func(*args, **kwargs):
|
|
97
149
|
return "In test func"
|
|
98
150
|
|