metaflow-functions 0.2.1.dev1__tar.gz → 0.2.3__tar.gz

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.
Files changed (75) hide show
  1. metaflow_functions-0.2.3/MANIFEST.in +2 -0
  2. {metaflow_functions-0.2.1.dev1/metaflow_functions.egg-info → metaflow_functions-0.2.3}/PKG-INFO +1 -1
  3. metaflow_functions-0.2.3/VERSION +1 -0
  4. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/core/function_parameters.py +27 -1
  5. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/core/function_pipeline.py +63 -5
  6. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/factory.py +42 -1
  7. metaflow_functions-0.2.3/metaflow_extensions/nflx/toplevel/functions_version.py +1 -0
  8. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3/metaflow_functions.egg-info}/PKG-INFO +1 -1
  9. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_functions.egg-info/SOURCES.txt +2 -0
  10. metaflow_functions-0.2.1.dev1/metaflow_extensions/nflx/toplevel/functions_version.py +0 -1
  11. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/LICENSE +0 -0
  12. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/README.md +0 -0
  13. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/config/mfextinit_functions.py +0 -0
  14. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/avro_function/__init__.py +0 -0
  15. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/avro_function/serializers.py +0 -0
  16. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/__init__.py +0 -0
  17. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/__init__.py +0 -0
  18. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/abstract_backend.py +0 -0
  19. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/backend_type.py +0 -0
  20. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/factory.py +0 -0
  21. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/local/__init__.py +0 -0
  22. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/local/local_backend.py +0 -0
  23. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/memory/__init__.py +0 -0
  24. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/memory/memory_backend.py +0 -0
  25. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/memory/memory_cli.py +0 -0
  26. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/memory/runtime.py +0 -0
  27. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/memory/runtime_config.py +0 -0
  28. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/memory/supervisor/__init__.py +0 -0
  29. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/memory/supervisor/supervisor.py +0 -0
  30. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/memory/supervisor/utils.py +0 -0
  31. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/ray/__init__.py +0 -0
  32. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/backends/ray/ray_backend.py +0 -0
  33. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/common/__init__.py +0 -0
  34. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/common/runtime_utils.py +0 -0
  35. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/config.py +0 -0
  36. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/core/__init__.py +0 -0
  37. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/core/function.py +0 -0
  38. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/core/function_decorator.py +0 -0
  39. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/core/function_decorator_spec.py +0 -0
  40. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/core/function_payload.py +0 -0
  41. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/core/function_pipeline_spec.py +0 -0
  42. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/core/function_spec.py +0 -0
  43. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/debug.py +0 -0
  44. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/environment.py +0 -0
  45. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/exceptions.py +0 -0
  46. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/logger/__init__.py +0 -0
  47. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/logger/logger.py +0 -0
  48. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/memory/__init__.py +0 -0
  49. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/memory/concurrency.py +0 -0
  50. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/memory/librt.py +0 -0
  51. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/memory/memory.py +0 -0
  52. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/package.py +0 -0
  53. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/serializers/__init__.py +0 -0
  54. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/serializers/avro_mixin.py +0 -0
  55. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/serializers/base.py +0 -0
  56. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/serializers/binary_serializers.py +0 -0
  57. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/serializers/config.py +0 -0
  58. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/serializers/function_parameters_serializer.py +0 -0
  59. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/serializers/function_payload_serializer.py +0 -0
  60. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/serializers/hook_utils.py +0 -0
  61. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/serializers/import_interceptor.py +0 -0
  62. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/serializers/ray_sync.py +0 -0
  63. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/serializers/registry.py +0 -0
  64. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/typing.py +0 -0
  65. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/functions/utils.py +0 -0
  66. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/json_function/__init__.py +0 -0
  67. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/json_function/serializers.py +0 -0
  68. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/plugins/mfextinit_functions.py +0 -0
  69. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/toplevel/functions_toplevel.py +0 -0
  70. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_extensions/nflx/toplevel/mfextinit_functions.py +0 -0
  71. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_functions.egg-info/dependency_links.txt +0 -0
  72. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_functions.egg-info/requires.txt +0 -0
  73. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/metaflow_functions.egg-info/top_level.txt +0 -0
  74. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/setup.cfg +0 -0
  75. {metaflow_functions-0.2.1.dev1 → metaflow_functions-0.2.3}/setup.py +0 -0
@@ -0,0 +1,2 @@
1
+ include VERSION
2
+ include README.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metaflow-functions
3
- Version: 0.2.1.dev1
3
+ Version: 0.2.3
4
4
  Summary: Metaflow Functions
5
5
  Author: Netflix Metaflow Developers
6
6
  Author-email: metaflow-dev@netflix.com
@@ -0,0 +1 @@
1
+ 0.2.3
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import types
4
4
  from collections.abc import Iterator, Mapping
5
- from typing import TYPE_CHECKING, Any, Dict, Optional, TypeVar, Generic
5
+ from typing import TYPE_CHECKING, Any, Dict, Optional, Type, TypeVar, Generic
6
6
 
7
7
  if TYPE_CHECKING:
8
8
  from metaflow import Task
@@ -92,6 +92,7 @@ class LazyArtifactMapping(Mapping[str, Any]):
92
92
 
93
93
 
94
94
  T_FP_co = TypeVar("T_FP_co", covariant=True)
95
+ T_FP = TypeVar("T_FP", bound="FunctionParameters")
95
96
 
96
97
 
97
98
  class FunctionParameters(Generic[T_FP_co]):
@@ -414,3 +415,28 @@ class FunctionParameters(Generic[T_FP_co]):
414
415
  def __len__(self) -> int:
415
416
  """Return number of artifacts."""
416
417
  return len(self._lazy_mapping)
418
+
419
+ def as_typed(self, typed_class: Type[T_FP]) -> T_FP:
420
+ """
421
+ Create a typed view of this FunctionParameters instance.
422
+
423
+ The new instance is pre-populated from this instance's already-fetched
424
+ cache, so previously prefetched artifacts are not re-fetched. Any
425
+ artifacts not yet in the cache are loaded lazily from the same
426
+ function spec.
427
+
428
+ Parameters
429
+ ----------
430
+ typed_class : Type[FunctionParameters]
431
+ A FunctionParameters subclass to instantiate.
432
+
433
+ Returns
434
+ -------
435
+ FunctionParameters
436
+ An instance of typed_class pre-populated from this instance's cache.
437
+ """
438
+ cached = dict(self._lazy_mapping._cache)
439
+ return typed_class(
440
+ function_spec=self._lazy_mapping._function_spec,
441
+ **cached,
442
+ )
@@ -33,6 +33,10 @@ from metaflow_extensions.nflx.plugins.functions.exceptions import (
33
33
  MetaflowFunctionTypeException,
34
34
  MetaflowFunctionUserException,
35
35
  )
36
+ from metaflow_extensions.nflx.plugins.functions.core.function_parameters import (
37
+ FunctionParameters,
38
+ )
39
+ from metaflow_extensions.nflx.plugins.functions.utils import load_type_from_string
36
40
 
37
41
  if TYPE_CHECKING:
38
42
  from metaflow_extensions.nflx.plugins.functions.memory.memory import (
@@ -68,6 +72,9 @@ class FunctionPipeline(MetaflowFunction):
68
72
 
69
73
  self.functions = functions
70
74
  self._name = name
75
+ self._scoped_params: Optional[List["FunctionParameters"]] = (
76
+ None # populated on first execute call
77
+ )
71
78
 
72
79
  # Pipeline creates its own backend instance
73
80
  from metaflow_extensions.nflx.plugins.functions.backends import get_backend
@@ -172,8 +179,14 @@ class FunctionPipeline(MetaflowFunction):
172
179
  self.functions[0].spec.task_code_path if self.functions else None
173
180
  ), # Use first function's task code path
174
181
  artifacts=(
175
- self.functions[0].spec.artifacts if self.functions else None
176
- ), # Use first function's artifacts metadata
182
+ {
183
+ k: v
184
+ for func in self.functions
185
+ if func.spec.artifacts
186
+ for k, v in func.spec.artifacts.items()
187
+ }
188
+ or None
189
+ ), # Union of all constituent functions' artifacts metadata
177
190
  user=_lazy_get_username(),
178
191
  timestamp_utc=int(time.time()),
179
192
  system_metadata={
@@ -239,6 +252,44 @@ class FunctionPipeline(MetaflowFunction):
239
252
  """
240
253
  return self.backend.apply(self, data, **kwargs)
241
254
 
255
+ def _make_func_params(
256
+ self, pipeline_params: "FunctionParameters", func: MetaflowFunction
257
+ ) -> "FunctionParameters":
258
+ """
259
+ Create a typed FunctionParameters instance for a constituent function.
260
+
261
+ Uses the function's parameter_schema to instantiate the correct typed class,
262
+ pre-populated from the pipeline-level cache (already prefetched). This means
263
+ isinstance checks work correctly and no re-fetching is needed.
264
+
265
+ Returns pipeline params as-is for Optional[FunctionParameters] and base
266
+ FunctionParameters functions, and a typed instance for typed subclasses.
267
+ """
268
+ param_schema = None
269
+ if (
270
+ func.spec
271
+ and func.spec.function
272
+ and hasattr(func.spec.function, "parameter_schema")
273
+ ):
274
+ param_schema = func.spec.function.parameter_schema
275
+
276
+ # Optional[FunctionParameters] — artifacts not required but pass through anyway;
277
+ # the function can check and use them if present
278
+ if param_schema is None:
279
+ return pipeline_params
280
+
281
+ # Base FunctionParameters — pass pipeline params as-is, all artifacts accessible
282
+ if not param_schema or "type" not in param_schema:
283
+ return pipeline_params
284
+
285
+ # Typed subclass — create a typed view so isinstance works and
286
+ # no re-fetching occurs for already-prefetched artifacts
287
+ typed_class = load_type_from_string(param_schema["type"])
288
+ if typed_class is None or not issubclass(typed_class, FunctionParameters):
289
+ return pipeline_params
290
+
291
+ return pipeline_params.as_typed(typed_class)
292
+
242
293
  def execute(self, data: Any, params: "FunctionParameters", **kwargs: Any) -> Any: # type: ignore
243
294
  """
244
295
  Execute the pipeline by chaining all functions in the same process.
@@ -257,10 +308,16 @@ class FunctionPipeline(MetaflowFunction):
257
308
  Any
258
309
  The result of the pipeline execution
259
310
  """
260
- # Chain all functions together in the same process
311
+ # Per-function params are computed once on the first call and reused —
312
+ # params is the same object for every request in a runtime lifetime.
313
+ if self._scoped_params is None:
314
+ self._scoped_params = [
315
+ self._make_func_params(params, func) for func in self.functions
316
+ ]
317
+
261
318
  result = data
262
- for func in self.functions:
263
- result = func.execute(result, params, **kwargs)
319
+ for func, func_params in zip(self.functions, self._scoped_params):
320
+ result = func.execute(result, func_params, **kwargs)
264
321
  return result
265
322
 
266
323
  def is_compatible_with(self, other: MetaflowFunction) -> bool:
@@ -522,6 +579,7 @@ class FunctionPipeline(MetaflowFunction):
522
579
  if spec.uuid is None:
523
580
  raise MetaflowFunctionException("Pipeline spec is missing a uuid.")
524
581
  pipeline._name = spec.name
582
+ pipeline._scoped_params = None # type: ignore[assignment] # populated on first execute call
525
583
 
526
584
  # Pipeline creates its own backend instance
527
585
  from metaflow_extensions.nflx.plugins.functions.backends import get_backend
@@ -324,10 +324,15 @@ def create_function_type(
324
324
  type_hints = get_type_hints(self.func)
325
325
  parameter_schema = None
326
326
 
327
+ from metaflow_extensions.nflx.plugins.functions.core.function_parameters import (
328
+ FunctionParameters,
329
+ )
330
+
327
331
  params_type = type_hints.get("params")
328
332
  if params_type and is_optional_function_parameters_type(params_type):
329
333
  # Extract the actual concrete type, unwrapping Optional if needed
330
334
  concrete_type = params_type
335
+ is_optional_wrapper = False
331
336
  if get_origin(params_type) is Union:
332
337
  # Handle Optional[T] which is Union[T, None]
333
338
  args = get_args(params_type)
@@ -335,8 +340,14 @@ def create_function_type(
335
340
  if arg is not type(None):
336
341
  concrete_type = arg
337
342
  break
343
+ is_optional_wrapper = True
338
344
 
339
- parameter_schema = {"type": get_type_string(concrete_type)}
345
+ # Optional[FunctionParameters] (base class) signals no artifacts needed.
346
+ # A typed subclass or bare FunctionParameters still carries artifacts.
347
+ if is_optional_wrapper and concrete_type is FunctionParameters:
348
+ parameter_schema = None
349
+ else:
350
+ parameter_schema = {"type": get_type_string(concrete_type)}
340
351
 
341
352
  return GeneratedDecoratorSpec(
342
353
  name=self.func.__name__,
@@ -401,6 +412,36 @@ def create_function_type(
401
412
  """Build function spec and populate serializer configs."""
402
413
  func_spec = super()._build_function_spec(**kwargs)
403
414
 
415
+ # Filter artifacts based on what the function's FunctionParameters declares:
416
+ # - parameter_schema is None (Optional[FunctionParameters]): no artifacts needed
417
+ # - parameter_schema has a typed subclass: only declared artifacts
418
+ # - parameter_schema has base FunctionParameters: keep all artifacts
419
+ if func_spec.function is not None:
420
+ if func_spec.function.parameter_schema is None:
421
+ # Optional[FunctionParameters] — function needs no task artifacts
422
+ func_spec.artifacts = {}
423
+ elif "type" in func_spec.function.parameter_schema:
424
+ from metaflow_extensions.nflx.plugins.functions.utils import (
425
+ load_type_from_string,
426
+ )
427
+ from metaflow_extensions.nflx.plugins.functions.core.function_parameters import (
428
+ FunctionParameters,
429
+ )
430
+
431
+ params_class = load_type_from_string(
432
+ func_spec.function.parameter_schema["type"]
433
+ )
434
+ if (
435
+ params_class is not None
436
+ and issubclass(params_class, FunctionParameters)
437
+ and params_class._expected_artifacts is not None
438
+ ):
439
+ func_spec.artifacts = {
440
+ k: v
441
+ for k, v in (func_spec.artifacts or {}).items()
442
+ if k in params_class._expected_artifacts
443
+ }
444
+
404
445
  # Add serializer configs for this function's types
405
446
  from metaflow_extensions.nflx.plugins.functions.serializers.registry import (
406
447
  get_global_registry,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metaflow-functions
3
- Version: 0.2.1.dev1
3
+ Version: 0.2.3
4
4
  Summary: Metaflow Functions
5
5
  Author: Netflix Metaflow Developers
6
6
  Author-email: metaflow-dev@netflix.com
@@ -1,5 +1,7 @@
1
1
  LICENSE
2
+ MANIFEST.in
2
3
  README.md
4
+ VERSION
3
5
  setup.py
4
6
  metaflow_extensions/nflx/config/mfextinit_functions.py
5
7
  metaflow_extensions/nflx/plugins/mfextinit_functions.py
@@ -1 +0,0 @@
1
- _ext_version = "0.2.1.dev1"