metaflow 2.12.0__py2.py3-none-any.whl → 2.12.2__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/cli.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import inspect
2
+ import os
2
3
  import sys
3
4
  import traceback
4
5
  from datetime import datetime
@@ -9,11 +10,11 @@ from metaflow._vendor import click
9
10
 
10
11
  from . import decorators, lint, metaflow_version, namespace, parameters, plugins
11
12
  from .cli_args import cli_args
12
- from .client.core import get_metadata
13
13
  from .datastore import FlowDataStore, TaskDataStore, TaskDataStoreSet
14
14
  from .exception import CommandException, MetaflowException
15
15
  from .graph import FlowGraph
16
16
  from .metaflow_config import (
17
+ DECOSPECS,
17
18
  DEFAULT_DATASTORE,
18
19
  DEFAULT_ENVIRONMENT,
19
20
  DEFAULT_EVENT_LOGGER,
@@ -118,6 +119,26 @@ def logger(body="", system_msg=False, head="", bad=False, timestamp=True, nl=Tru
118
119
  click.secho(body, bold=system_msg, fg=LOGGER_BAD_COLOR if bad else None, nl=nl)
119
120
 
120
121
 
122
+ def config_merge_cb(ctx, param, value):
123
+ # Callback to:
124
+ # - read the Click auto_envvar variable from both the
125
+ # environment AND the configuration
126
+ # - merge that value with the value passed in the command line (value)
127
+ # - return the value as a tuple
128
+ # Note that this function gets called even if there is no option passed on the
129
+ # command line.
130
+ # NOTE: Assumes that ctx.auto_envvar_prefix is set to METAFLOW (same as in
131
+ # from_conf)
132
+
133
+ # Special case where DECOSPECS and value are the same. This happens
134
+ # when there is no --with option at the TL and DECOSPECS is read from
135
+ # the env var. In this case, click also passes it as value
136
+ splits = DECOSPECS.split()
137
+ if len(splits) == len(value) and all([a == b for (a, b) in zip(splits, value)]):
138
+ return value
139
+ return tuple(list(value) + DECOSPECS.split())
140
+
141
+
121
142
  @click.group()
122
143
  def cli(ctx):
123
144
  pass
@@ -618,7 +639,7 @@ def resume(
618
639
  resume_identifier=None,
619
640
  runner_attribute_file=None,
620
641
  ):
621
- before_run(obj, tags, decospecs + obj.environment.decospecs())
642
+ before_run(obj, tags, decospecs)
622
643
 
623
644
  if origin_run_id is None:
624
645
  origin_run_id = get_latest_run_id(obj.echo, obj.flow.name)
@@ -678,7 +699,12 @@ def resume(
678
699
  runtime.persist_constants()
679
700
  write_file(
680
701
  runner_attribute_file,
681
- "%s:%s" % (get_metadata(), "/".join((obj.flow.name, runtime.run_id))),
702
+ "%s@%s:%s"
703
+ % (
704
+ obj.metadata.__class__.TYPE,
705
+ obj.metadata.__class__.INFO,
706
+ "/".join((obj.flow.name, runtime.run_id)),
707
+ ),
682
708
  )
683
709
  if clone_only:
684
710
  runtime.clone_original_run()
@@ -716,7 +742,7 @@ def run(
716
742
  ):
717
743
  if user_namespace is not None:
718
744
  namespace(user_namespace or None)
719
- before_run(obj, tags, decospecs + obj.environment.decospecs())
745
+ before_run(obj, tags, decospecs)
720
746
 
721
747
  runtime = NativeRuntime(
722
748
  obj.flow,
@@ -741,7 +767,12 @@ def run(
741
767
  runtime.persist_constants()
742
768
  write_file(
743
769
  runner_attribute_file,
744
- "%s:%s" % (get_metadata(), "/".join((obj.flow.name, runtime.run_id))),
770
+ "%s@%s:%s"
771
+ % (
772
+ obj.metadata.__class__.TYPE,
773
+ obj.metadata.__class__.INFO,
774
+ "/".join((obj.flow.name, runtime.run_id)),
775
+ ),
745
776
  )
746
777
  runtime.execute()
747
778
 
@@ -764,9 +795,20 @@ def before_run(obj, tags, decospecs):
764
795
  # A downside is that we need to have the following decorators handling
765
796
  # in two places in this module and make sure _init_step_decorators
766
797
  # doesn't get called twice.
767
- if decospecs:
768
- decorators._attach_decorators(obj.flow, decospecs)
798
+
799
+ # We want the order to be the following:
800
+ # - run level decospecs
801
+ # - top level decospecs
802
+ # - environment decospecs
803
+ all_decospecs = (
804
+ list(decospecs or [])
805
+ + obj.tl_decospecs
806
+ + list(obj.environment.decospecs() or [])
807
+ )
808
+ if all_decospecs:
809
+ decorators._attach_decorators(obj.flow, all_decospecs)
769
810
  obj.graph = FlowGraph(obj.flow.__class__)
811
+
770
812
  obj.check(obj.graph, obj.flow, obj.environment, pylint=obj.pylint)
771
813
  # obj.environment.init_environment(obj.logger)
772
814
 
@@ -837,6 +879,7 @@ def version(obj):
837
879
  multiple=True,
838
880
  help="Add a decorator to all steps. You can specify this option "
839
881
  "multiple times to attach multiple decorators in steps.",
882
+ callback=config_merge_cb,
840
883
  )
841
884
  @click.option(
842
885
  "--pylint/--no-pylint",
@@ -955,8 +998,11 @@ def start(
955
998
  deco_options,
956
999
  )
957
1000
 
958
- if decospecs:
959
- decorators._attach_decorators(ctx.obj.flow, decospecs)
1001
+ # In the case of run/resume, we will want to apply the TL decospecs
1002
+ # *after* the run decospecs so that they don't take precedence. In other
1003
+ # words, for the same decorator, we want `myflow.py run --with foo` to
1004
+ # take precedence over any other `foo` decospec
1005
+ ctx.obj.tl_decospecs = list(decospecs or [])
960
1006
 
961
1007
  # initialize current and parameter context for deploy-time parameters
962
1008
  current._set_env(flow=ctx.obj.flow, is_running=False)
@@ -967,7 +1013,14 @@ def start(
967
1013
  if ctx.invoked_subcommand not in ("run", "resume"):
968
1014
  # run/resume are special cases because they can add more decorators with --with,
969
1015
  # so they have to take care of themselves.
970
- decorators._attach_decorators(ctx.obj.flow, ctx.obj.environment.decospecs())
1016
+ all_decospecs = ctx.obj.tl_decospecs + list(
1017
+ ctx.obj.environment.decospecs() or []
1018
+ )
1019
+ if all_decospecs:
1020
+ decorators._attach_decorators(ctx.obj.flow, all_decospecs)
1021
+ # Regenerate graph if we attached more decorators
1022
+ ctx.obj.graph = FlowGraph(ctx.obj.flow.__class__)
1023
+
971
1024
  decorators._init_step_decorators(
972
1025
  ctx.obj.flow,
973
1026
  ctx.obj.graph,
@@ -975,6 +1028,7 @@ def start(
975
1028
  ctx.obj.flow_datastore,
976
1029
  ctx.obj.logger,
977
1030
  )
1031
+
978
1032
  # TODO (savin): Enable lazy instantiation of package
979
1033
  ctx.obj.package = None
980
1034
  if ctx.invoked_subcommand is None:
metaflow/decorators.py CHANGED
@@ -158,13 +158,14 @@ class Decorator(object):
158
158
  attr_list.append("%s=%s" % (k, str(v)))
159
159
  else:
160
160
  attr_list.append("%s=%s" % (k, json.dumps(v).replace('"', '\\"')))
161
+
161
162
  attrstr = ",".join(attr_list)
162
163
  return "%s:%s" % (self.name, attrstr)
163
164
  else:
164
165
  return self.name
165
166
 
166
167
  def __str__(self):
167
- mode = "decorated" if self.statically_defined else "cli"
168
+ mode = "static" if self.statically_defined else "dynamic"
168
169
  attrs = " ".join("%s=%s" % x for x in self.attributes.items())
169
170
  if attrs:
170
171
  attrs = " " + attrs
@@ -450,6 +451,18 @@ def _base_step_decorator(decotype, *args, **kwargs):
450
451
  return wrap
451
452
 
452
453
 
454
+ _all_step_decos = None
455
+
456
+
457
+ def _get_all_step_decos():
458
+ global _all_step_decos
459
+ if _all_step_decos is None:
460
+ from .plugins import STEP_DECORATORS
461
+
462
+ _all_step_decos = {decotype.name: decotype for decotype in STEP_DECORATORS}
463
+ return _all_step_decos
464
+
465
+
453
466
  def _attach_decorators(flow, decospecs):
454
467
  """
455
468
  Attach decorators to all steps during runtime. This has the same
@@ -462,6 +475,7 @@ def _attach_decorators(flow, decospecs):
462
475
  #
463
476
  # Note that each step gets its own instance of the decorator class,
464
477
  # so decorator can maintain step-specific state.
478
+
465
479
  for step in flow:
466
480
  _attach_decorators_to_step(step, decospecs)
467
481
 
@@ -472,9 +486,8 @@ def _attach_decorators_to_step(step, decospecs):
472
486
  effect as if you defined the decorators statically in the source for
473
487
  the step.
474
488
  """
475
- from .plugins import STEP_DECORATORS
476
489
 
477
- decos = {decotype.name: decotype for decotype in STEP_DECORATORS}
490
+ decos = _get_all_step_decos()
478
491
 
479
492
  for decospec in decospecs:
480
493
  splits = decospec.split(":", 1)
@@ -249,6 +249,14 @@ CONTACT_INFO = from_conf(
249
249
  },
250
250
  )
251
251
 
252
+
253
+ ###
254
+ # Decorators
255
+ ###
256
+ # Format is a space separated string of decospecs (what is passed
257
+ # using --with)
258
+ DECOSPECS = from_conf("DECOSPECS", "")
259
+
252
260
  ###
253
261
  # AWS Batch configuration
254
262
  ###
@@ -496,6 +504,8 @@ def get_pinned_conda_libs(python_version, datastore_type):
496
504
  try:
497
505
  from metaflow.extension_support import get_modules
498
506
 
507
+ _TOGGLE_DECOSPECS = []
508
+
499
509
  ext_modules = get_modules("config")
500
510
  for m in ext_modules:
501
511
  # We load into globals whatever we have in extension_module
@@ -519,8 +529,18 @@ try:
519
529
  return d1
520
530
 
521
531
  globals()[n] = _new_get_pinned_conda_libs
532
+ elif n == "TOGGLE_DECOSPECS":
533
+ if any([x.startswith("-") for x in o]):
534
+ raise ValueError("Removing decospecs is not currently supported")
535
+ if any(" " in x for x in o):
536
+ raise ValueError("Decospecs cannot contain spaces")
537
+ _TOGGLE_DECOSPECS.extend(o)
522
538
  elif not n.startswith("__") and not isinstance(o, types.ModuleType):
523
539
  globals()[n] = o
540
+ # If DECOSPECS is set, use that, else extrapolate from extensions
541
+ if not DECOSPECS:
542
+ DECOSPECS = " ".join(_TOGGLE_DECOSPECS)
543
+
524
544
  finally:
525
545
  # Erase all temporary names to avoid leaking things
526
546
  for _n in [
@@ -537,6 +557,7 @@ finally:
537
557
  "v",
538
558
  "f1",
539
559
  "f2",
560
+ "_TOGGLE_DECOSPECS",
540
561
  ]:
541
562
  try:
542
563
  del globals()[_n]
@@ -184,6 +184,12 @@ class ArgoWorkflows(object):
184
184
  # allowed by Metaflow - guaranteeing uniqueness.
185
185
  return name.replace("_", "-")
186
186
 
187
+ @staticmethod
188
+ def _sensor_name(name):
189
+ # Unfortunately, Argo Events Sensor names don't allow for
190
+ # dots (sensors run into an error) which rules out self.name :(
191
+ return name.replace(".", "-")
192
+
187
193
  @staticmethod
188
194
  def list_templates(flow_name, all=False):
189
195
  client = ArgoClient(namespace=KUBERNETES_NAMESPACE)
@@ -216,7 +222,7 @@ class ArgoWorkflows(object):
216
222
 
217
223
  # The workflow might have sensors attached to it, which consume actual resources.
218
224
  # Try to delete these as well.
219
- sensor_deleted = client.delete_sensor(name)
225
+ sensor_deleted = client.delete_sensor(ArgoWorkflows._sensor_name(name))
220
226
 
221
227
  # After cleaning up related resources, delete the workflow in question.
222
228
  # Failure in deleting is treated as critical and will be made visible to the user
@@ -333,10 +339,9 @@ class ArgoWorkflows(object):
333
339
  argo_client.schedule_workflow_template(
334
340
  self.name, self._schedule, self._timezone
335
341
  )
336
- # Register sensor. Unfortunately, Argo Events Sensor names don't allow for
337
- # dots (sensors run into an error) which rules out self.name :(
342
+ # Register sensor.
338
343
  # Metaflow will overwrite any existing sensor.
339
- sensor_name = self.name.replace(".", "-")
344
+ sensor_name = ArgoWorkflows._sensor_name(self.name)
340
345
  if self._sensor:
341
346
  argo_client.register_sensor(sensor_name, self._sensor.to_json())
342
347
  else:
@@ -2039,7 +2044,7 @@ class ArgoWorkflows(object):
2039
2044
  .metadata(
2040
2045
  # Sensor metadata.
2041
2046
  ObjectMeta()
2042
- .name(self.name.replace(".", "-"))
2047
+ .name(ArgoWorkflows._sensor_name(self.name))
2043
2048
  .namespace(KUBERNETES_NAMESPACE)
2044
2049
  .label("app.kubernetes.io/name", "metaflow-sensor")
2045
2050
  .label("app.kubernetes.io/part-of", "metaflow")
metaflow/version.py CHANGED
@@ -1 +1 @@
1
- metaflow_version = "2.12.0"
1
+ metaflow_version = "2.12.2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: metaflow
3
- Version: 2.12.0
3
+ Version: 2.12.2
4
4
  Summary: Metaflow: More Data Science, Less Engineering
5
5
  Author: Metaflow Developers
6
6
  Author-email: help@metaflow.org
@@ -26,7 +26,7 @@ License-File: LICENSE
26
26
  Requires-Dist: requests
27
27
  Requires-Dist: boto3
28
28
  Provides-Extra: stubs
29
- Requires-Dist: metaflow-stubs ==2.12.0 ; extra == 'stubs'
29
+ Requires-Dist: metaflow-stubs ==2.12.2 ; extra == 'stubs'
30
30
 
31
31
  ![Metaflow_Logo_Horizontal_FullColor_Ribbon_Dark_RGB](https://user-images.githubusercontent.com/763451/89453116-96a57e00-d713-11ea-9fa6-82b29d4d6eff.png)
32
32
 
@@ -1,12 +1,12 @@
1
1
  metaflow/R.py,sha256=bNcXXpGOe5wquzTRGyU0KS9gJMz7HceKjXxammYPUE0,3841
2
2
  metaflow/__init__.py,sha256=3GEqivYycw6mvjn-ndEFGuCdYnGztciQgEWX87vjf6M,5885
3
3
  metaflow/cards.py,sha256=tP1_RrtmqdFh741pqE4t98S7SA0MtGRlGvRICRZF1Mg,426
4
- metaflow/cli.py,sha256=3OhQDuXbgJjg-KrsAcXCObWOcXpd9Qedbv_RDLO682g,31935
4
+ metaflow/cli.py,sha256=4NTGG4_UCd53HhscDVMQGl4VcV8O6C33iFKfTc-n2tg,33736
5
5
  metaflow/cli_args.py,sha256=lcgBGNTvfaiPxiUnejAe60Upt9swG6lRy1_3OqbU6MY,2616
6
6
  metaflow/clone_util.py,sha256=XfUX0vssu_hPlyZfhFl1AOnKkLqvt33Qp8xNrmdocGg,2057
7
7
  metaflow/cmd_with_io.py,sha256=kl53HkAIyv0ecpItv08wZYczv7u3msD1VCcciqigqf0,588
8
8
  metaflow/debug.py,sha256=HEmt_16tJtqHXQXsqD9pqOFe3CWR5GZ7VwpaYQgnRdU,1466
9
- metaflow/decorators.py,sha256=n91bvWA4JJWHwZnI02-rFGBZsWWMtaABYlWYcOvHuRw,21391
9
+ metaflow/decorators.py,sha256=vmM1uavxAaLhS8fC54h2y4UL_NJr2jQ5pHxaxJLCWuc,21587
10
10
  metaflow/event_logger.py,sha256=joTVRqZPL87nvah4ZOwtqWX8NeraM_CXKXXGVpKGD8o,780
11
11
  metaflow/events.py,sha256=ahjzkSbSnRCK9RZ-9vTfUviz_6gMvSO9DGkJ86X80-k,5300
12
12
  metaflow/exception.py,sha256=KC1LHJQzzYkWib0DeQ4l_A2r8VaudywsSqIQuq1RDZU,4954
@@ -15,7 +15,7 @@ metaflow/graph.py,sha256=ZPxyG8uwVMk5YYgX4pQEQaPZtZM5Wy-G4NtJK73IEuA,11818
15
15
  metaflow/includefile.py,sha256=yHczcZ_U0SrasxSNhZb3DIBzx8UZnrJCl3FzvpEQLOA,19753
16
16
  metaflow/integrations.py,sha256=LlsaoePRg03DjENnmLxZDYto3NwWc9z_PtU6nJxLldg,1480
17
17
  metaflow/lint.py,sha256=_kYAbAtsP7IG1Rd0FqNbo8I8Zs66_0WXbaZJFARO3dE,10394
18
- metaflow/metaflow_config.py,sha256=WdLyxSwQy1XZUoJWrCMujz6OuzRqFSZZ31OP9b9mihc,21618
18
+ metaflow/metaflow_config.py,sha256=hso-EOFxKJxGUiotTdG2logrZHPpKDaY7hm7p4q8hJc,22305
19
19
  metaflow/metaflow_config_funcs.py,sha256=pCaiQ2ez9wXixJI3ehmf3QiW9lUqFrZnBZx1my_0wIg,4874
20
20
  metaflow/metaflow_current.py,sha256=sCENPBiji3LcPbwgOG0ukGd_yEc5tST8EowES8DzRtA,7430
21
21
  metaflow/metaflow_environment.py,sha256=HJfhI3GrU-YbY7Etu9M-1q7EbwtEGFzCBhrUs45OLXY,7403
@@ -35,7 +35,7 @@ metaflow/tuple_util.py,sha256=_G5YIEhuugwJ_f6rrZoelMFak3DqAR2tt_5CapS1XTY,830
35
35
  metaflow/unbounded_foreach.py,sha256=p184WMbrMJ3xKYHwewj27ZhRUsSj_kw1jlye5gA9xJk,387
36
36
  metaflow/util.py,sha256=m5womQ7y-jXehuMyHPfByDbZ4HwTJxzs869cPOlMR8s,13057
37
37
  metaflow/vendor.py,sha256=FchtA9tH22JM-eEtJ2c9FpUdMn8sSb1VHuQS56EcdZk,5139
38
- metaflow/version.py,sha256=pqIxgkkbL8fwxLZUUfdCZLx-eMGZTjLRM1r2oZdtsRY,28
38
+ metaflow/version.py,sha256=sdavZlXn6yAn7ZbaZSr5MI3visWVVwTt1jCnVgTOkcM,28
39
39
  metaflow/_vendor/__init__.py,sha256=y_CiwUD3l4eAKvTVDZeqgVujMy31cAM1qjAB-HfI-9s,353
40
40
  metaflow/_vendor/typing_extensions.py,sha256=0nUs5p1A_UrZigrAVBoOEM6TxU37zzPDUtiij1ZwpNc,110417
41
41
  metaflow/_vendor/zipp.py,sha256=ajztOH-9I7KA_4wqDYygtHa6xUBVZgFpmZ8FE74HHHI,8425
@@ -174,7 +174,7 @@ metaflow/plugins/airflow/sensors/s3_sensor.py,sha256=JUKoGNoTCtrO9MNEneEC7ldRNwg
174
174
  metaflow/plugins/argo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
175
175
  metaflow/plugins/argo/argo_client.py,sha256=MKKhMCbWOPzf6z5zQQiyDRHHkAXcO7ipboDZDqAAvOk,15849
176
176
  metaflow/plugins/argo/argo_events.py,sha256=_C1KWztVqgi3zuH57pInaE9OzABc2NnncC-zdwOMZ-w,5909
177
- metaflow/plugins/argo/argo_workflows.py,sha256=6px2phfm19G9pz4zcaC4xYsdoxNC8SxdzZr1uyoMaV4,130187
177
+ metaflow/plugins/argo/argo_workflows.py,sha256=cyoWiEMgV2jZpE2cvMDJPOqEfRuhYoG4m1rqgqm0Gzc,130326
178
178
  metaflow/plugins/argo/argo_workflows_cli.py,sha256=sZTpgfmc50eT3e0qIxpVqUgWhTcYlO1HM4gU6Oaya8g,33259
179
179
  metaflow/plugins/argo/argo_workflows_decorator.py,sha256=K5t4uIk2IXPdK7v7DEjj3buSB8ikLjLycKjbZUYeiaw,6781
180
180
  metaflow/plugins/argo/generate_input_paths.py,sha256=loYsI6RFX9LlFsHb7Fe-mzlTTtRdySoOu7sYDy-uXK0,881
@@ -332,9 +332,9 @@ metaflow/tutorials/07-worldview/README.md,sha256=5vQTrFqulJ7rWN6r20dhot9lI2sVj9W
332
332
  metaflow/tutorials/07-worldview/worldview.ipynb,sha256=ztPZPI9BXxvW1QdS2Tfe7LBuVzvFvv0AToDnsDJhLdE,2237
333
333
  metaflow/tutorials/08-autopilot/README.md,sha256=GnePFp_q76jPs991lMUqfIIh5zSorIeWznyiUxzeUVE,1039
334
334
  metaflow/tutorials/08-autopilot/autopilot.ipynb,sha256=DQoJlILV7Mq9vfPBGW-QV_kNhWPjS5n6SJLqePjFYLY,3191
335
- metaflow-2.12.0.dist-info/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
336
- metaflow-2.12.0.dist-info/METADATA,sha256=5c5f8MYqP0w7J8tjxmXywb8k_NRusFNfCCdPRVp3yxw,5906
337
- metaflow-2.12.0.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
338
- metaflow-2.12.0.dist-info/entry_points.txt,sha256=IKwTN1T3I5eJL3uo_vnkyxVffcgnRdFbKwlghZfn27k,57
339
- metaflow-2.12.0.dist-info/top_level.txt,sha256=v1pDHoWaSaKeuc5fKTRSfsXCKSdW1zvNVmvA-i0if3o,9
340
- metaflow-2.12.0.dist-info/RECORD,,
335
+ metaflow-2.12.2.dist-info/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
336
+ metaflow-2.12.2.dist-info/METADATA,sha256=uPb9tJHUxC2bXau5g1PPXM92VbR1OwRuiMAW68JEsX8,5906
337
+ metaflow-2.12.2.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
338
+ metaflow-2.12.2.dist-info/entry_points.txt,sha256=IKwTN1T3I5eJL3uo_vnkyxVffcgnRdFbKwlghZfn27k,57
339
+ metaflow-2.12.2.dist-info/top_level.txt,sha256=v1pDHoWaSaKeuc5fKTRSfsXCKSdW1zvNVmvA-i0if3o,9
340
+ metaflow-2.12.2.dist-info/RECORD,,