ob-metaflow 2.9.10.1__py2.py3-none-any.whl → 2.10.2.6__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.

Files changed (57) hide show
  1. metaflow/_vendor/packaging/__init__.py +15 -0
  2. metaflow/_vendor/packaging/_elffile.py +108 -0
  3. metaflow/_vendor/packaging/_manylinux.py +238 -0
  4. metaflow/_vendor/packaging/_musllinux.py +80 -0
  5. metaflow/_vendor/packaging/_parser.py +328 -0
  6. metaflow/_vendor/packaging/_structures.py +61 -0
  7. metaflow/_vendor/packaging/_tokenizer.py +188 -0
  8. metaflow/_vendor/packaging/markers.py +245 -0
  9. metaflow/_vendor/packaging/requirements.py +95 -0
  10. metaflow/_vendor/packaging/specifiers.py +1005 -0
  11. metaflow/_vendor/packaging/tags.py +546 -0
  12. metaflow/_vendor/packaging/utils.py +141 -0
  13. metaflow/_vendor/packaging/version.py +563 -0
  14. metaflow/_vendor/v3_7/__init__.py +1 -0
  15. metaflow/_vendor/v3_7/zipp.py +329 -0
  16. metaflow/metaflow_config.py +2 -1
  17. metaflow/metaflow_environment.py +3 -1
  18. metaflow/mflog/mflog.py +7 -1
  19. metaflow/multicore_utils.py +12 -2
  20. metaflow/plugins/__init__.py +8 -3
  21. metaflow/plugins/airflow/airflow.py +13 -0
  22. metaflow/plugins/argo/argo_client.py +16 -0
  23. metaflow/plugins/argo/argo_events.py +7 -1
  24. metaflow/plugins/argo/argo_workflows.py +62 -0
  25. metaflow/plugins/argo/argo_workflows_cli.py +15 -0
  26. metaflow/plugins/aws/batch/batch.py +10 -0
  27. metaflow/plugins/aws/batch/batch_cli.py +1 -2
  28. metaflow/plugins/aws/batch/batch_decorator.py +2 -9
  29. metaflow/plugins/datatools/s3/s3.py +4 -0
  30. metaflow/plugins/env_escape/client.py +24 -3
  31. metaflow/plugins/env_escape/stub.py +2 -8
  32. metaflow/plugins/kubernetes/kubernetes.py +13 -0
  33. metaflow/plugins/kubernetes/kubernetes_cli.py +1 -2
  34. metaflow/plugins/kubernetes/kubernetes_decorator.py +9 -2
  35. metaflow/plugins/pypi/__init__.py +29 -0
  36. metaflow/plugins/pypi/bootstrap.py +131 -0
  37. metaflow/plugins/pypi/conda_decorator.py +335 -0
  38. metaflow/plugins/pypi/conda_environment.py +414 -0
  39. metaflow/plugins/pypi/micromamba.py +294 -0
  40. metaflow/plugins/pypi/pip.py +205 -0
  41. metaflow/plugins/pypi/pypi_decorator.py +130 -0
  42. metaflow/plugins/pypi/pypi_environment.py +7 -0
  43. metaflow/plugins/pypi/utils.py +75 -0
  44. metaflow/task.py +0 -3
  45. metaflow/vendor.py +1 -0
  46. {ob_metaflow-2.9.10.1.dist-info → ob_metaflow-2.10.2.6.dist-info}/METADATA +1 -1
  47. {ob_metaflow-2.9.10.1.dist-info → ob_metaflow-2.10.2.6.dist-info}/RECORD +51 -33
  48. {ob_metaflow-2.9.10.1.dist-info → ob_metaflow-2.10.2.6.dist-info}/WHEEL +1 -1
  49. metaflow/plugins/conda/__init__.py +0 -90
  50. metaflow/plugins/conda/batch_bootstrap.py +0 -104
  51. metaflow/plugins/conda/conda.py +0 -247
  52. metaflow/plugins/conda/conda_environment.py +0 -136
  53. metaflow/plugins/conda/conda_flow_decorator.py +0 -35
  54. metaflow/plugins/conda/conda_step_decorator.py +0 -416
  55. {ob_metaflow-2.9.10.1.dist-info → ob_metaflow-2.10.2.6.dist-info}/LICENSE +0 -0
  56. {ob_metaflow-2.9.10.1.dist-info → ob_metaflow-2.10.2.6.dist-info}/entry_points.txt +0 -0
  57. {ob_metaflow-2.9.10.1.dist-info → ob_metaflow-2.10.2.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,335 @@
1
+ import importlib
2
+ import json
3
+ import os
4
+ import platform
5
+ import sys
6
+ import tempfile
7
+
8
+ from metaflow.decorators import FlowDecorator, StepDecorator
9
+ from metaflow.extension_support import EXT_PKG
10
+ from metaflow.metaflow_environment import InvalidEnvironmentException
11
+ from metaflow.util import get_metaflow_root
12
+
13
+ from ... import INFO_FILE
14
+
15
+
16
+ class CondaStepDecorator(StepDecorator):
17
+ """
18
+ Specifies the Conda environment for the step.
19
+
20
+ Information in this decorator will augment any
21
+ attributes set in the `@conda_base` flow-level decorator. Hence,
22
+ you can use `@conda_base` to set packages required by all
23
+ steps and use `@conda` to specify step-specific overrides.
24
+
25
+ Parameters
26
+ ----------
27
+ packages : Dict[str, str], default: {}
28
+ Packages to use for this step. The key is the name of the package
29
+ and the value is the version to use.
30
+ libraries : Dict[str, str], default: {}
31
+ Supported for backward compatibility. When used with packages, packages will take precedence.
32
+ python : str, optional
33
+ Version of Python to use, e.g. '3.7.4'. A default value of None implies
34
+ that the version used will correspond to the version of the Python interpreter used to start the run.
35
+ disabled : bool, default: False
36
+ If set to True, disables @conda.
37
+ """
38
+
39
+ name = "conda"
40
+ defaults = {
41
+ "packages": {},
42
+ "libraries": {}, # Deprecated! Use packages going forward
43
+ "python": None,
44
+ "disabled": None,
45
+ }
46
+ # To define conda channels for the whole solve, users can specify
47
+ # CONDA_CHANNELS in their environment. For pinning specific packages to specific
48
+ # conda channels, users can specify channel::package as the package name.
49
+
50
+ def __init__(self, attributes=None, statically_defined=False):
51
+ super(CondaStepDecorator, self).__init__(attributes, statically_defined)
52
+
53
+ # Support legacy 'libraries=' attribute for the decorator.
54
+ self.attributes["packages"] = {
55
+ **self.attributes["libraries"],
56
+ **self.attributes["packages"],
57
+ }
58
+ del self.attributes["libraries"]
59
+
60
+ def step_init(self, flow, graph, step, decos, environment, flow_datastore, logger):
61
+ # The init_environment hook for Environment creates the relevant virtual
62
+ # environments. The step_init hook sets up the relevant state for that hook to
63
+ # do it's magic.
64
+
65
+ self.flow = flow
66
+ self.step = step
67
+ self.environment = environment
68
+ self.datastore = flow_datastore
69
+
70
+ # Support flow-level decorator.
71
+ if "conda_base" in self.flow._flow_decorators:
72
+ super_attributes = self.flow._flow_decorators["conda_base"][0].attributes
73
+ self.attributes["packages"] = {
74
+ **super_attributes["packages"],
75
+ **self.attributes["packages"],
76
+ }
77
+ self.attributes["python"] = (
78
+ self.attributes["python"] or super_attributes["python"]
79
+ )
80
+ self.attributes["disabled"] = (
81
+ self.attributes["disabled"]
82
+ if self.attributes["disabled"] is not None
83
+ else super_attributes["disabled"]
84
+ )
85
+
86
+ # Set default for `disabled` argument.
87
+ if not self.attributes["disabled"]:
88
+ self.attributes["disabled"] = False
89
+ # Set Python interpreter to user's Python if necessary.
90
+ if not self.attributes["python"]:
91
+ self.attributes["python"] = platform.python_version() # CPython!
92
+
93
+ # @conda uses a conda environment to create a virtual environment.
94
+ # The conda environment can be created through micromamba.
95
+ _supported_virtual_envs = ["conda"]
96
+
97
+ # To placate people who don't want to see a shred of conda in UX, we symlink
98
+ # --environment=pypi to --environment=conda
99
+ _supported_virtual_envs.extend(["pypi"])
100
+
101
+ # The --environment= requirement ensures that valid virtual environments are
102
+ # created for every step to execute it, greatly simplifying the @conda
103
+ # implementation.
104
+ if environment.TYPE not in _supported_virtual_envs:
105
+ raise InvalidEnvironmentException(
106
+ "@%s decorator requires %s"
107
+ % (
108
+ self.name,
109
+ " or ".join(
110
+ ["--environment=%s" % env for env in _supported_virtual_envs]
111
+ ),
112
+ )
113
+ )
114
+
115
+ # At this point, the list of 32 bit instance types is shrinking quite rapidly.
116
+ # We can worry about supporting them when there is a need.
117
+
118
+ # TODO: This code snippet can be done away with by altering the constructor of
119
+ # MetaflowEnvironment. A good first-task exercise.
120
+ # Avoid circular import
121
+ from metaflow.plugins.datastores.local_storage import LocalStorage
122
+
123
+ environment.set_local_root(LocalStorage.get_datastore_root_from_config(logger))
124
+
125
+ self.disabled = not self.environment.get_environment(
126
+ next(step for step in self.flow if step.name == self.step)
127
+ )
128
+
129
+ def runtime_init(self, flow, graph, package, run_id):
130
+ if self.disabled:
131
+ return
132
+ # Create a symlink to metaflow installed outside the virtual environment.
133
+ self.metaflow_dir = tempfile.TemporaryDirectory(dir="/tmp")
134
+ os.symlink(
135
+ os.path.join(get_metaflow_root(), "metaflow"),
136
+ os.path.join(self.metaflow_dir.name, "metaflow"),
137
+ )
138
+
139
+ info = os.path.join(get_metaflow_root(), os.path.basename(INFO_FILE))
140
+ # Symlink the INFO file as well to properly propagate down the Metaflow version
141
+ if os.path.isfile(info):
142
+ os.symlink(
143
+ info, os.path.join(self.metaflow_dir.name, os.path.basename(INFO_FILE))
144
+ )
145
+ else:
146
+ # If there is no info file, we will actually create one in this new
147
+ # place because we won't be able to properly resolve the EXT_PKG extensions
148
+ # the same way as outside conda (looking at distributions, etc.). In a
149
+ # Conda environment, as shown below (where we set self.addl_paths), all
150
+ # EXT_PKG extensions are PYTHONPATH extensions. Instead of re-resolving,
151
+ # we use the resolved information that is written out to the INFO file.
152
+ with open(
153
+ os.path.join(self.metaflow_dir.name, os.path.basename(INFO_FILE)),
154
+ mode="wt",
155
+ encoding="utf-8",
156
+ ) as f:
157
+ f.write(
158
+ json.dumps(
159
+ self.environment.get_environment_info(include_ext_info=True)
160
+ )
161
+ )
162
+
163
+ # Support metaflow extensions.
164
+ self.addl_paths = None
165
+ try:
166
+ m = importlib.import_module(EXT_PKG)
167
+ except ImportError:
168
+ # No additional check needed because if we are here, we already checked
169
+ # for other issues when loading at the toplevel.
170
+ pass
171
+ else:
172
+ custom_paths = list(set(m.__path__))
173
+ # For some reason, at times, unique paths appear multiple times. We
174
+ # simplify to avoid un-necessary links.
175
+
176
+ if len(custom_paths) == 1:
177
+ # Regular package; we take a quick shortcut here.
178
+ os.symlink(
179
+ custom_paths[0],
180
+ os.path.join(self.metaflow_dir.name, EXT_PKG),
181
+ )
182
+ else:
183
+ # This is a namespace package, we therefore create a bunch of
184
+ # directories so that we can symlink in those separately, and we will
185
+ # add those paths to the PYTHONPATH for the interpreter. Note that we
186
+ # don't symlink to the parent of the package because that could end up
187
+ # including more stuff we don't want
188
+ self.addl_paths = []
189
+ for p in custom_paths:
190
+ temp_dir = tempfile.mkdtemp(dir=self.metaflow_dir.name)
191
+ os.symlink(p, os.path.join(temp_dir, EXT_PKG))
192
+ self.addl_paths.append(temp_dir)
193
+
194
+ # # Also install any environment escape overrides directly here to enable
195
+ # # the escape to work even in non metaflow-created subprocesses
196
+ # from ..env_escape import generate_trampolines
197
+ # generate_trampolines(self.metaflow_dir.name)
198
+
199
+ def runtime_task_created(
200
+ self, task_datastore, task_id, split_index, input_paths, is_cloned, ubf_context
201
+ ):
202
+ if self.disabled:
203
+ return
204
+ self.interpreter = (
205
+ self.environment.interpreter(self.step)
206
+ if not any(
207
+ decorator.name in ["batch", "kubernetes"]
208
+ for decorator in next(
209
+ step for step in self.flow if step.name == self.step
210
+ ).decorators
211
+ )
212
+ else None
213
+ )
214
+
215
+ def task_pre_step(
216
+ self,
217
+ step_name,
218
+ task_datastore,
219
+ meta,
220
+ run_id,
221
+ task_id,
222
+ flow,
223
+ graph,
224
+ retry_count,
225
+ max_retries,
226
+ ubf_context,
227
+ inputs,
228
+ ):
229
+ if self.disabled:
230
+ return
231
+ # Add Python interpreter's parent to the path to ensure that any non-pythonic
232
+ # dependencies in the virtual environment are visible to the user code.
233
+ # sys.executable points to the Python interpreter in the virtual environment
234
+ # since we are already inside the task context.
235
+ os.environ["PATH"] = os.pathsep.join(
236
+ filter(
237
+ None,
238
+ (
239
+ os.path.dirname(os.path.realpath(sys.executable)),
240
+ os.environ.get("PATH"),
241
+ ),
242
+ )
243
+ )
244
+ # TODO: Register metadata
245
+
246
+ def runtime_step_cli(
247
+ self, cli_args, retry_count, max_user_code_retries, ubf_context
248
+ ):
249
+ if self.disabled:
250
+ return
251
+ # Ensure local installation of Metaflow is visible to user code
252
+ python_path = self.metaflow_dir.name
253
+ if self.addl_paths is not None:
254
+ addl_paths = os.pathsep.join(self.addl_paths)
255
+ python_path = os.pathsep.join([addl_paths, python_path])
256
+ cli_args.env["PYTHONPATH"] = python_path
257
+ if self.interpreter:
258
+ # https://github.com/conda/conda/issues/7707
259
+ # Also ref - https://github.com/Netflix/metaflow/pull/178
260
+ cli_args.env["PYTHONNOUSERSITE"] = "1"
261
+ # The executable is already in place for the user code to execute against
262
+ cli_args.entrypoint[0] = self.interpreter
263
+
264
+ def runtime_finished(self, exception):
265
+ if self.disabled:
266
+ return
267
+ self.metaflow_dir.cleanup()
268
+
269
+
270
+ class CondaFlowDecorator(FlowDecorator):
271
+ """
272
+ Specifies the Conda environment for all steps of the flow.
273
+
274
+ Use `@conda_base` to set common libraries required by all
275
+ steps and use `@conda` to specify step-specific additions.
276
+
277
+ Parameters
278
+ ----------
279
+ packages : Dict[str, str], default: {}
280
+ Packages to use for this flow. The key is the name of the package
281
+ and the value is the version to use.
282
+ libraries : Dict[str, str], default: {}
283
+ Supported for backward compatibility. When used with packages, packages will take precedence.
284
+ python : str, optional
285
+ Version of Python to use, e.g. '3.7.4'. A default value of None implies
286
+ that the version used will correspond to the version of the Python interpreter used to start the run.
287
+ disabled : bool, default: False
288
+ If set to True, disables Conda.
289
+ """
290
+
291
+ # TODO: Migrate conda_base keyword to conda for simplicity.
292
+ name = "conda_base"
293
+ defaults = {
294
+ "packages": {},
295
+ "libraries": {}, # Deprecated! Use packages going forward.
296
+ "python": None,
297
+ "disabled": None,
298
+ }
299
+
300
+ def __init__(self, attributes=None, statically_defined=False):
301
+ super(CondaFlowDecorator, self).__init__(attributes, statically_defined)
302
+
303
+ # Support legacy 'libraries=' attribute for the decorator.
304
+ self.attributes["packages"] = {
305
+ **self.attributes["libraries"],
306
+ **self.attributes["packages"],
307
+ }
308
+ del self.attributes["libraries"]
309
+ if self.attributes["python"]:
310
+ self.attributes["python"] = str(self.attributes["python"])
311
+
312
+ def flow_init(
313
+ self, flow, graph, environment, flow_datastore, metadata, logger, echo, options
314
+ ):
315
+ # @conda uses a conda environment to create a virtual environment.
316
+ # The conda environment can be created through micromamba.
317
+ _supported_virtual_envs = ["conda"]
318
+
319
+ # To placate people who don't want to see a shred of conda in UX, we symlink
320
+ # --environment=pypi to --environment=conda
321
+ _supported_virtual_envs.extend(["pypi"])
322
+
323
+ # The --environment= requirement ensures that valid virtual environments are
324
+ # created for every step to execute it, greatly simplifying the @conda
325
+ # implementation.
326
+ if environment.TYPE not in _supported_virtual_envs:
327
+ raise InvalidEnvironmentException(
328
+ "@%s decorator requires %s"
329
+ % (
330
+ self.name,
331
+ " or ".join(
332
+ ["--environment=%s" % env for env in _supported_virtual_envs]
333
+ ),
334
+ )
335
+ )