ob-metaflow 2.11.13.1__py2.py3-none-any.whl → 2.19.7.1rc0__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.
- metaflow/R.py +10 -7
- metaflow/__init__.py +40 -25
- metaflow/_vendor/imghdr/__init__.py +186 -0
- metaflow/_vendor/importlib_metadata/__init__.py +1063 -0
- metaflow/_vendor/importlib_metadata/_adapters.py +68 -0
- metaflow/_vendor/importlib_metadata/_collections.py +30 -0
- metaflow/_vendor/importlib_metadata/_compat.py +71 -0
- metaflow/_vendor/importlib_metadata/_functools.py +104 -0
- metaflow/_vendor/importlib_metadata/_itertools.py +73 -0
- metaflow/_vendor/importlib_metadata/_meta.py +48 -0
- metaflow/_vendor/importlib_metadata/_text.py +99 -0
- metaflow/_vendor/importlib_metadata/py.typed +0 -0
- metaflow/_vendor/typeguard/__init__.py +48 -0
- metaflow/_vendor/typeguard/_checkers.py +1070 -0
- metaflow/_vendor/typeguard/_config.py +108 -0
- metaflow/_vendor/typeguard/_decorators.py +233 -0
- metaflow/_vendor/typeguard/_exceptions.py +42 -0
- metaflow/_vendor/typeguard/_functions.py +308 -0
- metaflow/_vendor/typeguard/_importhook.py +213 -0
- metaflow/_vendor/typeguard/_memo.py +48 -0
- metaflow/_vendor/typeguard/_pytest_plugin.py +127 -0
- metaflow/_vendor/typeguard/_suppression.py +86 -0
- metaflow/_vendor/typeguard/_transformer.py +1229 -0
- metaflow/_vendor/typeguard/_union_transformer.py +55 -0
- metaflow/_vendor/typeguard/_utils.py +173 -0
- metaflow/_vendor/typeguard/py.typed +0 -0
- metaflow/_vendor/typing_extensions.py +3641 -0
- metaflow/_vendor/v3_7/importlib_metadata/__init__.py +1063 -0
- metaflow/_vendor/v3_7/importlib_metadata/_adapters.py +68 -0
- metaflow/_vendor/v3_7/importlib_metadata/_collections.py +30 -0
- metaflow/_vendor/v3_7/importlib_metadata/_compat.py +71 -0
- metaflow/_vendor/v3_7/importlib_metadata/_functools.py +104 -0
- metaflow/_vendor/v3_7/importlib_metadata/_itertools.py +73 -0
- metaflow/_vendor/v3_7/importlib_metadata/_meta.py +48 -0
- metaflow/_vendor/v3_7/importlib_metadata/_text.py +99 -0
- metaflow/_vendor/v3_7/importlib_metadata/py.typed +0 -0
- metaflow/_vendor/v3_7/typeguard/__init__.py +48 -0
- metaflow/_vendor/v3_7/typeguard/_checkers.py +906 -0
- metaflow/_vendor/v3_7/typeguard/_config.py +108 -0
- metaflow/_vendor/v3_7/typeguard/_decorators.py +237 -0
- metaflow/_vendor/v3_7/typeguard/_exceptions.py +42 -0
- metaflow/_vendor/v3_7/typeguard/_functions.py +310 -0
- metaflow/_vendor/v3_7/typeguard/_importhook.py +213 -0
- metaflow/_vendor/v3_7/typeguard/_memo.py +48 -0
- metaflow/_vendor/v3_7/typeguard/_pytest_plugin.py +100 -0
- metaflow/_vendor/v3_7/typeguard/_suppression.py +88 -0
- metaflow/_vendor/v3_7/typeguard/_transformer.py +1207 -0
- metaflow/_vendor/v3_7/typeguard/_union_transformer.py +54 -0
- metaflow/_vendor/v3_7/typeguard/_utils.py +169 -0
- metaflow/_vendor/v3_7/typeguard/py.typed +0 -0
- metaflow/_vendor/v3_7/typing_extensions.py +3072 -0
- metaflow/_vendor/yaml/__init__.py +427 -0
- metaflow/_vendor/yaml/composer.py +139 -0
- metaflow/_vendor/yaml/constructor.py +748 -0
- metaflow/_vendor/yaml/cyaml.py +101 -0
- metaflow/_vendor/yaml/dumper.py +62 -0
- metaflow/_vendor/yaml/emitter.py +1137 -0
- metaflow/_vendor/yaml/error.py +75 -0
- metaflow/_vendor/yaml/events.py +86 -0
- metaflow/_vendor/yaml/loader.py +63 -0
- metaflow/_vendor/yaml/nodes.py +49 -0
- metaflow/_vendor/yaml/parser.py +589 -0
- metaflow/_vendor/yaml/reader.py +185 -0
- metaflow/_vendor/yaml/representer.py +389 -0
- metaflow/_vendor/yaml/resolver.py +227 -0
- metaflow/_vendor/yaml/scanner.py +1435 -0
- metaflow/_vendor/yaml/serializer.py +111 -0
- metaflow/_vendor/yaml/tokens.py +104 -0
- metaflow/cards.py +5 -0
- metaflow/cli.py +331 -785
- metaflow/cli_args.py +17 -0
- metaflow/cli_components/__init__.py +0 -0
- metaflow/cli_components/dump_cmd.py +96 -0
- metaflow/cli_components/init_cmd.py +52 -0
- metaflow/cli_components/run_cmds.py +546 -0
- metaflow/cli_components/step_cmd.py +334 -0
- metaflow/cli_components/utils.py +140 -0
- metaflow/client/__init__.py +1 -0
- metaflow/client/core.py +467 -73
- metaflow/client/filecache.py +75 -35
- metaflow/clone_util.py +7 -1
- metaflow/cmd/code/__init__.py +231 -0
- metaflow/cmd/develop/stub_generator.py +756 -288
- metaflow/cmd/develop/stubs.py +12 -28
- metaflow/cmd/main_cli.py +6 -4
- metaflow/cmd/make_wrapper.py +78 -0
- metaflow/datastore/__init__.py +1 -0
- metaflow/datastore/content_addressed_store.py +41 -10
- metaflow/datastore/datastore_set.py +11 -2
- metaflow/datastore/flow_datastore.py +156 -10
- metaflow/datastore/spin_datastore.py +91 -0
- metaflow/datastore/task_datastore.py +154 -39
- metaflow/debug.py +5 -0
- metaflow/decorators.py +404 -78
- metaflow/exception.py +8 -2
- metaflow/extension_support/__init__.py +527 -376
- metaflow/extension_support/_empty_file.py +2 -2
- metaflow/extension_support/plugins.py +49 -31
- metaflow/flowspec.py +482 -33
- metaflow/graph.py +210 -42
- metaflow/includefile.py +84 -40
- metaflow/lint.py +141 -22
- metaflow/meta_files.py +13 -0
- metaflow/{metadata → metadata_provider}/heartbeat.py +24 -8
- metaflow/{metadata → metadata_provider}/metadata.py +86 -1
- metaflow/metaflow_config.py +175 -28
- metaflow/metaflow_config_funcs.py +51 -3
- metaflow/metaflow_current.py +4 -10
- metaflow/metaflow_environment.py +139 -53
- metaflow/metaflow_git.py +115 -0
- metaflow/metaflow_profile.py +18 -0
- metaflow/metaflow_version.py +150 -66
- metaflow/mflog/__init__.py +4 -3
- metaflow/mflog/save_logs.py +2 -2
- metaflow/multicore_utils.py +31 -14
- metaflow/package/__init__.py +673 -0
- metaflow/packaging_sys/__init__.py +880 -0
- metaflow/packaging_sys/backend.py +128 -0
- metaflow/packaging_sys/distribution_support.py +153 -0
- metaflow/packaging_sys/tar_backend.py +99 -0
- metaflow/packaging_sys/utils.py +54 -0
- metaflow/packaging_sys/v1.py +527 -0
- metaflow/parameters.py +149 -28
- metaflow/plugins/__init__.py +74 -5
- metaflow/plugins/airflow/airflow.py +40 -25
- metaflow/plugins/airflow/airflow_cli.py +22 -5
- metaflow/plugins/airflow/airflow_decorator.py +1 -1
- metaflow/plugins/airflow/airflow_utils.py +5 -3
- metaflow/plugins/airflow/sensors/base_sensor.py +4 -4
- metaflow/plugins/airflow/sensors/external_task_sensor.py +2 -2
- metaflow/plugins/airflow/sensors/s3_sensor.py +2 -2
- metaflow/plugins/argo/argo_client.py +78 -33
- metaflow/plugins/argo/argo_events.py +6 -6
- metaflow/plugins/argo/argo_workflows.py +2410 -527
- metaflow/plugins/argo/argo_workflows_cli.py +571 -121
- metaflow/plugins/argo/argo_workflows_decorator.py +43 -12
- metaflow/plugins/argo/argo_workflows_deployer.py +106 -0
- metaflow/plugins/argo/argo_workflows_deployer_objects.py +453 -0
- metaflow/plugins/argo/capture_error.py +73 -0
- metaflow/plugins/argo/conditional_input_paths.py +35 -0
- metaflow/plugins/argo/exit_hooks.py +209 -0
- metaflow/plugins/argo/jobset_input_paths.py +15 -0
- metaflow/plugins/argo/param_val.py +19 -0
- metaflow/plugins/aws/aws_client.py +10 -3
- metaflow/plugins/aws/aws_utils.py +55 -2
- metaflow/plugins/aws/batch/batch.py +72 -5
- metaflow/plugins/aws/batch/batch_cli.py +33 -10
- metaflow/plugins/aws/batch/batch_client.py +4 -3
- metaflow/plugins/aws/batch/batch_decorator.py +102 -35
- metaflow/plugins/aws/secrets_manager/aws_secrets_manager_secrets_provider.py +13 -10
- metaflow/plugins/aws/step_functions/dynamo_db_client.py +0 -3
- metaflow/plugins/aws/step_functions/production_token.py +1 -1
- metaflow/plugins/aws/step_functions/step_functions.py +65 -8
- metaflow/plugins/aws/step_functions/step_functions_cli.py +101 -7
- metaflow/plugins/aws/step_functions/step_functions_decorator.py +1 -2
- metaflow/plugins/aws/step_functions/step_functions_deployer.py +97 -0
- metaflow/plugins/aws/step_functions/step_functions_deployer_objects.py +264 -0
- metaflow/plugins/azure/azure_exceptions.py +1 -1
- metaflow/plugins/azure/azure_secret_manager_secrets_provider.py +240 -0
- metaflow/plugins/azure/azure_tail.py +1 -1
- metaflow/plugins/azure/includefile_support.py +2 -0
- metaflow/plugins/cards/card_cli.py +66 -30
- metaflow/plugins/cards/card_creator.py +25 -1
- metaflow/plugins/cards/card_datastore.py +21 -49
- metaflow/plugins/cards/card_decorator.py +132 -8
- metaflow/plugins/cards/card_modules/basic.py +112 -17
- metaflow/plugins/cards/card_modules/bundle.css +1 -1
- metaflow/plugins/cards/card_modules/card.py +16 -1
- metaflow/plugins/cards/card_modules/chevron/renderer.py +1 -1
- metaflow/plugins/cards/card_modules/components.py +665 -28
- metaflow/plugins/cards/card_modules/convert_to_native_type.py +36 -7
- metaflow/plugins/cards/card_modules/json_viewer.py +232 -0
- metaflow/plugins/cards/card_modules/main.css +1 -0
- metaflow/plugins/cards/card_modules/main.js +68 -49
- metaflow/plugins/cards/card_modules/renderer_tools.py +1 -0
- metaflow/plugins/cards/card_modules/test_cards.py +26 -12
- metaflow/plugins/cards/card_server.py +39 -14
- metaflow/plugins/cards/component_serializer.py +2 -9
- metaflow/plugins/cards/metadata.py +22 -0
- metaflow/plugins/catch_decorator.py +9 -0
- metaflow/plugins/datastores/azure_storage.py +10 -1
- metaflow/plugins/datastores/gs_storage.py +6 -2
- metaflow/plugins/datastores/local_storage.py +12 -6
- metaflow/plugins/datastores/spin_storage.py +12 -0
- metaflow/plugins/datatools/local.py +2 -0
- metaflow/plugins/datatools/s3/s3.py +126 -75
- metaflow/plugins/datatools/s3/s3op.py +254 -121
- metaflow/plugins/env_escape/__init__.py +3 -3
- metaflow/plugins/env_escape/client_modules.py +102 -72
- metaflow/plugins/env_escape/server.py +7 -0
- metaflow/plugins/env_escape/stub.py +24 -5
- metaflow/plugins/events_decorator.py +343 -185
- metaflow/plugins/exit_hook/__init__.py +0 -0
- metaflow/plugins/exit_hook/exit_hook_decorator.py +46 -0
- metaflow/plugins/exit_hook/exit_hook_script.py +52 -0
- metaflow/plugins/gcp/__init__.py +1 -1
- metaflow/plugins/gcp/gcp_secret_manager_secrets_provider.py +11 -6
- metaflow/plugins/gcp/gs_tail.py +10 -6
- metaflow/plugins/gcp/includefile_support.py +3 -0
- metaflow/plugins/kubernetes/kube_utils.py +108 -0
- metaflow/plugins/kubernetes/kubernetes.py +411 -130
- metaflow/plugins/kubernetes/kubernetes_cli.py +168 -36
- metaflow/plugins/kubernetes/kubernetes_client.py +104 -2
- metaflow/plugins/kubernetes/kubernetes_decorator.py +246 -88
- metaflow/plugins/kubernetes/kubernetes_job.py +253 -581
- metaflow/plugins/kubernetes/kubernetes_jobsets.py +1071 -0
- metaflow/plugins/kubernetes/spot_metadata_cli.py +69 -0
- metaflow/plugins/kubernetes/spot_monitor_sidecar.py +109 -0
- metaflow/plugins/logs_cli.py +359 -0
- metaflow/plugins/{metadata → metadata_providers}/local.py +144 -84
- metaflow/plugins/{metadata → metadata_providers}/service.py +103 -26
- metaflow/plugins/metadata_providers/spin.py +16 -0
- metaflow/plugins/package_cli.py +36 -24
- metaflow/plugins/parallel_decorator.py +128 -11
- metaflow/plugins/parsers.py +16 -0
- metaflow/plugins/project_decorator.py +51 -5
- metaflow/plugins/pypi/bootstrap.py +357 -105
- metaflow/plugins/pypi/conda_decorator.py +82 -81
- metaflow/plugins/pypi/conda_environment.py +187 -52
- metaflow/plugins/pypi/micromamba.py +157 -47
- metaflow/plugins/pypi/parsers.py +268 -0
- metaflow/plugins/pypi/pip.py +88 -13
- metaflow/plugins/pypi/pypi_decorator.py +37 -1
- metaflow/plugins/pypi/utils.py +48 -2
- metaflow/plugins/resources_decorator.py +2 -2
- metaflow/plugins/secrets/__init__.py +3 -0
- metaflow/plugins/secrets/secrets_decorator.py +26 -181
- metaflow/plugins/secrets/secrets_func.py +49 -0
- metaflow/plugins/secrets/secrets_spec.py +101 -0
- metaflow/plugins/secrets/utils.py +74 -0
- metaflow/plugins/tag_cli.py +4 -7
- metaflow/plugins/test_unbounded_foreach_decorator.py +41 -6
- metaflow/plugins/timeout_decorator.py +3 -3
- metaflow/plugins/uv/__init__.py +0 -0
- metaflow/plugins/uv/bootstrap.py +128 -0
- metaflow/plugins/uv/uv_environment.py +72 -0
- metaflow/procpoll.py +1 -1
- metaflow/pylint_wrapper.py +5 -1
- metaflow/runner/__init__.py +0 -0
- metaflow/runner/click_api.py +717 -0
- metaflow/runner/deployer.py +470 -0
- metaflow/runner/deployer_impl.py +201 -0
- metaflow/runner/metaflow_runner.py +714 -0
- metaflow/runner/nbdeploy.py +132 -0
- metaflow/runner/nbrun.py +225 -0
- metaflow/runner/subprocess_manager.py +650 -0
- metaflow/runner/utils.py +335 -0
- metaflow/runtime.py +1078 -260
- metaflow/sidecar/sidecar_worker.py +1 -1
- metaflow/system/__init__.py +5 -0
- metaflow/system/system_logger.py +85 -0
- metaflow/system/system_monitor.py +108 -0
- metaflow/system/system_utils.py +19 -0
- metaflow/task.py +521 -225
- metaflow/tracing/__init__.py +7 -7
- metaflow/tracing/span_exporter.py +31 -38
- metaflow/tracing/tracing_modules.py +38 -43
- metaflow/tuple_util.py +27 -0
- metaflow/user_configs/__init__.py +0 -0
- metaflow/user_configs/config_options.py +563 -0
- metaflow/user_configs/config_parameters.py +598 -0
- metaflow/user_decorators/__init__.py +0 -0
- metaflow/user_decorators/common.py +144 -0
- metaflow/user_decorators/mutable_flow.py +512 -0
- metaflow/user_decorators/mutable_step.py +424 -0
- metaflow/user_decorators/user_flow_decorator.py +264 -0
- metaflow/user_decorators/user_step_decorator.py +749 -0
- metaflow/util.py +243 -27
- metaflow/vendor.py +23 -7
- metaflow/version.py +1 -1
- ob_metaflow-2.19.7.1rc0.data/data/share/metaflow/devtools/Makefile +355 -0
- ob_metaflow-2.19.7.1rc0.data/data/share/metaflow/devtools/Tiltfile +726 -0
- ob_metaflow-2.19.7.1rc0.data/data/share/metaflow/devtools/pick_services.sh +105 -0
- ob_metaflow-2.19.7.1rc0.dist-info/METADATA +87 -0
- ob_metaflow-2.19.7.1rc0.dist-info/RECORD +445 -0
- {ob_metaflow-2.11.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/WHEEL +1 -1
- {ob_metaflow-2.11.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/entry_points.txt +1 -0
- metaflow/_vendor/v3_5/__init__.py +0 -1
- metaflow/_vendor/v3_5/importlib_metadata/__init__.py +0 -644
- metaflow/_vendor/v3_5/importlib_metadata/_compat.py +0 -152
- metaflow/package.py +0 -188
- ob_metaflow-2.11.13.1.dist-info/METADATA +0 -85
- ob_metaflow-2.11.13.1.dist-info/RECORD +0 -308
- /metaflow/_vendor/{v3_5/zipp.py → zipp.py} +0 -0
- /metaflow/{metadata → metadata_provider}/__init__.py +0 -0
- /metaflow/{metadata → metadata_provider}/util.py +0 -0
- /metaflow/plugins/{metadata → metadata_providers}/__init__.py +0 -0
- {ob_metaflow-2.11.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info/licenses}/LICENSE +0 -0
- {ob_metaflow-2.11.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import atexit
|
|
2
2
|
import importlib
|
|
3
|
+
import importlib.util
|
|
3
4
|
import itertools
|
|
4
5
|
import pickle
|
|
5
6
|
import re
|
|
@@ -41,6 +42,8 @@ class _WrappedModule(object):
|
|
|
41
42
|
def __getattr__(self, name):
|
|
42
43
|
if name == "__loader__":
|
|
43
44
|
return self._loader
|
|
45
|
+
if name == "__spec__":
|
|
46
|
+
return importlib.util.spec_from_loader(self._prefix, self._loader)
|
|
44
47
|
if name in ("__name__", "__package__"):
|
|
45
48
|
return self._prefix
|
|
46
49
|
if name in ("__file__", "__path__"):
|
|
@@ -71,7 +74,8 @@ class _WrappedModule(object):
|
|
|
71
74
|
# Try to see if this is a submodule that we can load
|
|
72
75
|
m = None
|
|
73
76
|
try:
|
|
74
|
-
|
|
77
|
+
submodule_name = ".".join([self._prefix, name])
|
|
78
|
+
m = importlib.import_module(submodule_name)
|
|
75
79
|
except ImportError:
|
|
76
80
|
pass
|
|
77
81
|
if m is None:
|
|
@@ -117,7 +121,28 @@ class _WrappedModule(object):
|
|
|
117
121
|
|
|
118
122
|
|
|
119
123
|
class ModuleImporter(object):
|
|
120
|
-
|
|
124
|
+
"""
|
|
125
|
+
A custom import hook that proxies module imports to a different Python environment.
|
|
126
|
+
|
|
127
|
+
This class implements the MetaPathFinder and Loader protocols (PEP 451) to enable
|
|
128
|
+
"environment escape" - allowing the current Python process to import and use modules
|
|
129
|
+
from a different Python interpreter with potentially different versions or packages.
|
|
130
|
+
|
|
131
|
+
When a module is imported through this importer:
|
|
132
|
+
1. A client spawns a server process in the target Python environment
|
|
133
|
+
2. The module is loaded in the remote environment
|
|
134
|
+
3. A _WrappedModule proxy is returned that forwards all operations (function calls,
|
|
135
|
+
attribute access, etc.) to the remote environment via RPC
|
|
136
|
+
4. Data is serialized/deserialized using pickle for cross-environment communication
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
python_executable: Path to the Python interpreter for the remote environment
|
|
140
|
+
pythonpath: Python path to use in the remote environment
|
|
141
|
+
max_pickle_version: Maximum pickle protocol version supported by remote interpreter
|
|
142
|
+
config_dir: Directory containing configuration for the environment escape
|
|
143
|
+
module_prefixes: List of module name prefixes to handle
|
|
144
|
+
"""
|
|
145
|
+
|
|
121
146
|
def __init__(
|
|
122
147
|
self,
|
|
123
148
|
python_executable,
|
|
@@ -135,84 +160,89 @@ class ModuleImporter(object):
|
|
|
135
160
|
self._handled_modules = None
|
|
136
161
|
self._aliases = {}
|
|
137
162
|
|
|
138
|
-
def
|
|
163
|
+
def find_spec(self, fullname, path=None, target=None):
|
|
139
164
|
if self._handled_modules is not None:
|
|
140
165
|
if get_canonical_name(fullname, self._aliases) in self._handled_modules:
|
|
141
|
-
return self
|
|
166
|
+
return importlib.util.spec_from_loader(fullname, self)
|
|
142
167
|
return None
|
|
143
168
|
if any([fullname.startswith(prefix) for prefix in self._module_prefixes]):
|
|
144
169
|
# We potentially handle this
|
|
145
|
-
return self
|
|
170
|
+
return importlib.util.spec_from_loader(fullname, self)
|
|
146
171
|
return None
|
|
147
172
|
|
|
148
|
-
def
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
raise NotImplementedError(
|
|
154
|
-
"Environment escape imports are not supported in Python 2"
|
|
155
|
-
)
|
|
156
|
-
# We initialize a client and query the modules we handle
|
|
157
|
-
# The max_pickle_version is the pickle version that the server (so
|
|
158
|
-
# the underlying interpreter we call into) supports; we determine
|
|
159
|
-
# what version the current environment support and take the minimum
|
|
160
|
-
# of those two
|
|
161
|
-
max_pickle_version = min(self._max_pickle_version, pickle.HIGHEST_PROTOCOL)
|
|
162
|
-
|
|
163
|
-
self._client = Client(
|
|
164
|
-
self._module_prefixes,
|
|
165
|
-
self._python_executable,
|
|
166
|
-
self._pythonpath,
|
|
167
|
-
max_pickle_version,
|
|
168
|
-
self._config_dir,
|
|
169
|
-
)
|
|
170
|
-
atexit.register(_clean_client, self._client)
|
|
171
|
-
|
|
172
|
-
# Get information about overrides and what the server knows about
|
|
173
|
-
exports = self._client.get_exports()
|
|
174
|
-
|
|
175
|
-
prefixes = set()
|
|
176
|
-
export_classes = exports.get("classes", [])
|
|
177
|
-
export_functions = exports.get("functions", [])
|
|
178
|
-
export_values = exports.get("values", [])
|
|
179
|
-
export_exceptions = exports.get("exceptions", [])
|
|
180
|
-
self._aliases = exports.get("aliases", {})
|
|
181
|
-
for name in itertools.chain(
|
|
182
|
-
export_classes,
|
|
183
|
-
export_functions,
|
|
184
|
-
export_values,
|
|
185
|
-
(e[0] for e in export_exceptions),
|
|
186
|
-
):
|
|
187
|
-
splits = name.rsplit(".", 1)
|
|
188
|
-
prefixes.add(splits[0])
|
|
189
|
-
# We will make sure that we create modules even for "empty" prefixes
|
|
190
|
-
# because packages are always loaded hierarchically so if we have
|
|
191
|
-
# something in `a.b.c` but nothing directly in `a`, we still need to
|
|
192
|
-
# create a module named `a`. There is probably a better way of doing this
|
|
193
|
-
all_prefixes = list(prefixes)
|
|
194
|
-
for prefix in all_prefixes:
|
|
195
|
-
parts = prefix.split(".")
|
|
196
|
-
cur = parts[0]
|
|
197
|
-
for i in range(1, len(parts)):
|
|
198
|
-
prefixes.add(cur)
|
|
199
|
-
cur = ".".join([cur, parts[i]])
|
|
200
|
-
|
|
201
|
-
# We now know all the modules that we can handle. We update
|
|
202
|
-
# handled_module and return the module if we have it or raise ImportError
|
|
203
|
-
self._handled_modules = {}
|
|
204
|
-
for prefix in prefixes:
|
|
205
|
-
self._handled_modules[prefix] = _WrappedModule(
|
|
206
|
-
self, prefix, exports, self._client
|
|
207
|
-
)
|
|
173
|
+
def create_module(self, spec):
|
|
174
|
+
# Return the pre-created wrapped module for this spec
|
|
175
|
+
self._initialize_client()
|
|
176
|
+
|
|
177
|
+
fullname = spec.name
|
|
208
178
|
canonical_fullname = get_canonical_name(fullname, self._aliases)
|
|
209
|
-
# Modules are created canonically but we need to
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
179
|
+
# Modules are created canonically but we need to handle any of the aliases.
|
|
180
|
+
wrapped_module = self._handled_modules.get(canonical_fullname)
|
|
181
|
+
if wrapped_module is None:
|
|
182
|
+
raise ImportError(f"No module named '{fullname}'")
|
|
183
|
+
return wrapped_module
|
|
184
|
+
|
|
185
|
+
def exec_module(self, module):
|
|
186
|
+
# No initialization needed since the wrapped module returned by
|
|
187
|
+
# create_module() is fully initialized
|
|
188
|
+
pass
|
|
189
|
+
|
|
190
|
+
def _initialize_client(self):
|
|
191
|
+
if self._client is not None:
|
|
192
|
+
return
|
|
193
|
+
|
|
194
|
+
# We initialize a client and query the modules we handle
|
|
195
|
+
# The max_pickle_version is the pickle version that the server (so
|
|
196
|
+
# the underlying interpreter we call into) supports; we determine
|
|
197
|
+
# what version the current environment support and take the minimum
|
|
198
|
+
# of those two
|
|
199
|
+
max_pickle_version = min(self._max_pickle_version, pickle.HIGHEST_PROTOCOL)
|
|
200
|
+
|
|
201
|
+
self._client = Client(
|
|
202
|
+
self._module_prefixes,
|
|
203
|
+
self._python_executable,
|
|
204
|
+
self._pythonpath,
|
|
205
|
+
max_pickle_version,
|
|
206
|
+
self._config_dir,
|
|
207
|
+
)
|
|
208
|
+
atexit.register(_clean_client, self._client)
|
|
209
|
+
|
|
210
|
+
# Get information about overrides and what the server knows about
|
|
211
|
+
exports = self._client.get_exports()
|
|
212
|
+
|
|
213
|
+
prefixes = set()
|
|
214
|
+
export_classes = exports.get("classes", [])
|
|
215
|
+
export_functions = exports.get("functions", [])
|
|
216
|
+
export_values = exports.get("values", [])
|
|
217
|
+
export_exceptions = exports.get("exceptions", [])
|
|
218
|
+
self._aliases = exports.get("aliases", {})
|
|
219
|
+
for name in itertools.chain(
|
|
220
|
+
export_classes,
|
|
221
|
+
export_functions,
|
|
222
|
+
export_values,
|
|
223
|
+
(e[0] for e in export_exceptions),
|
|
224
|
+
):
|
|
225
|
+
splits = name.rsplit(".", 1)
|
|
226
|
+
prefixes.add(splits[0])
|
|
227
|
+
# We will make sure that we create modules even for "empty" prefixes
|
|
228
|
+
# because packages are always loaded hierarchically so if we have
|
|
229
|
+
# something in `a.b.c` but nothing directly in `a`, we still need to
|
|
230
|
+
# create a module named `a`. There is probably a better way of doing this
|
|
231
|
+
all_prefixes = list(prefixes)
|
|
232
|
+
for prefix in all_prefixes:
|
|
233
|
+
parts = prefix.split(".")
|
|
234
|
+
cur = parts[0]
|
|
235
|
+
for i in range(1, len(parts)):
|
|
236
|
+
prefixes.add(cur)
|
|
237
|
+
cur = ".".join([cur, parts[i]])
|
|
238
|
+
|
|
239
|
+
# We now know all the modules that we can handle. We update
|
|
240
|
+
# handled_module and return the module if we have it or raise ImportError
|
|
241
|
+
self._handled_modules = {}
|
|
242
|
+
for prefix in prefixes:
|
|
243
|
+
self._handled_modules[prefix] = _WrappedModule(
|
|
244
|
+
self, prefix, exports, self._client
|
|
245
|
+
)
|
|
216
246
|
|
|
217
247
|
|
|
218
248
|
def create_modules(python_executable, pythonpath, max_pickle_version, path, prefixes):
|
|
@@ -264,6 +264,7 @@ class Server(object):
|
|
|
264
264
|
def serve(self, path=None, port=None):
|
|
265
265
|
# Open up a connection
|
|
266
266
|
if path is not None:
|
|
267
|
+
# Keep the print line to facilitate debugging
|
|
267
268
|
# print("SERVER: Starting at %s" % path)
|
|
268
269
|
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
269
270
|
__try_op__("bind", sock.bind, BIND_RETRY, path)
|
|
@@ -503,6 +504,12 @@ class Server(object):
|
|
|
503
504
|
class_type = self._known_classes.get(class_name)
|
|
504
505
|
if class_type is None:
|
|
505
506
|
raise ValueError("Unknown class %s" % class_name)
|
|
507
|
+
# Check if __init__ is overridden
|
|
508
|
+
override_mapping = self._overrides.get(class_type)
|
|
509
|
+
if override_mapping:
|
|
510
|
+
override_func = override_mapping.get("__init__")
|
|
511
|
+
if override_func:
|
|
512
|
+
return override_func(None, class_type, *args, **kwargs)
|
|
506
513
|
return class_type(*args, **kwargs)
|
|
507
514
|
|
|
508
515
|
def _handle_subclasscheck(self, target, class_name, otherclass_name, reverse=False):
|
|
@@ -146,7 +146,7 @@ class Stub(with_metaclass(StubMetaClass, object)):
|
|
|
146
146
|
return object.__getattribute__(self, name)
|
|
147
147
|
|
|
148
148
|
def __getattr__(self, name):
|
|
149
|
-
if name in DELETED_ATTRS:
|
|
149
|
+
if name in DELETED_ATTRS or self.___is_returned_exception___:
|
|
150
150
|
raise AttributeError()
|
|
151
151
|
return fwd_request(self, OP_GETATTR, name)
|
|
152
152
|
|
|
@@ -166,6 +166,8 @@ class Stub(with_metaclass(StubMetaClass, object)):
|
|
|
166
166
|
):
|
|
167
167
|
object.__setattr__(self, name, value)
|
|
168
168
|
else:
|
|
169
|
+
if self.___is_returned_exception___:
|
|
170
|
+
raise AttributeError()
|
|
169
171
|
fwd_request(self, OP_SETATTR, name, value)
|
|
170
172
|
|
|
171
173
|
def __dir__(self):
|
|
@@ -274,9 +276,22 @@ class MetaWithConnection(StubMetaClass):
|
|
|
274
276
|
if len(args) > 0 and id(args[0]) == id(cls.___class_connection___):
|
|
275
277
|
return super(MetaWithConnection, cls).__call__(*args, **kwargs)
|
|
276
278
|
else:
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
279
|
+
if hasattr(cls, "__overriden_init__"):
|
|
280
|
+
return cls.__overriden_init__(
|
|
281
|
+
None,
|
|
282
|
+
functools.partial(
|
|
283
|
+
cls.___class_connection___.stub_request,
|
|
284
|
+
None,
|
|
285
|
+
OP_INIT,
|
|
286
|
+
cls.___class_remote_class_name___,
|
|
287
|
+
),
|
|
288
|
+
*args,
|
|
289
|
+
**kwargs
|
|
290
|
+
)
|
|
291
|
+
else:
|
|
292
|
+
return cls.___class_connection___.stub_request(
|
|
293
|
+
None, OP_INIT, cls.___class_remote_class_name___, *args, **kwargs
|
|
294
|
+
)
|
|
280
295
|
|
|
281
296
|
def __subclasscheck__(cls, subclass):
|
|
282
297
|
subclass_name = "%s.%s" % (subclass.__module__, subclass.__name__)
|
|
@@ -379,7 +394,10 @@ def create_class(
|
|
|
379
394
|
name = name[7:]
|
|
380
395
|
method_type = CLASS_METHOD
|
|
381
396
|
if name in overriden_methods:
|
|
382
|
-
if
|
|
397
|
+
if name == "__init__":
|
|
398
|
+
class_dict["__overriden_init__"] = overriden_methods["__init__"]
|
|
399
|
+
|
|
400
|
+
elif method_type == NORMAL_METHOD:
|
|
383
401
|
class_dict[name] = (
|
|
384
402
|
lambda override, orig_method: lambda obj, *args, **kwargs: override(
|
|
385
403
|
obj, functools.partial(orig_method, obj), *args, **kwargs
|
|
@@ -410,6 +428,7 @@ def create_class(
|
|
|
410
428
|
class_dict[name] = _make_method(
|
|
411
429
|
method_type, connection, class_name, name, doc
|
|
412
430
|
)
|
|
431
|
+
|
|
413
432
|
# Check for any getattr/setattr overrides
|
|
414
433
|
special_attributes = set(getattr_overrides.keys())
|
|
415
434
|
special_attributes.update(set(setattr_overrides.keys()))
|