Skip to content

Instantly share code, notes, and snippets.

@pdxjohnny

pdxjohnny/full.patch

Created Jun 25, 2020
Embed
What would you like to do?
saksham defaults edits (NO_DEFAULTS)
commit 722561381fb70aa895b786b39934ed2316420aab
Author: sakshamarora1 <sakshamarora1001@gmail.com>
Date: Tue Jun 23 20:48:06 2020 +0530
df: memory: Support default values for definitions
Signed-off-by: sakshamarora1 <sakshamarora1001@gmail.com>
diff --git a/dffml/df/base.py b/dffml/df/base.py
index d11c3f73..a7695722 100644
--- a/dffml/df/base.py
+++ b/dffml/df/base.py
@@ -17,7 +17,7 @@ from dataclasses import is_dataclass
from contextlib import asynccontextmanager
from .exceptions import NotOpImp
-from .types import Operation, Input, Parameter, Stage, Definition
+from .types import Operation, Input, Parameter, Stage, Definition, NO_DEFAULT
from .log import LOGGER
@@ -196,13 +196,14 @@ class OperationImplementation(BaseDataFlowObject):
return loading_classes
-def create_definition(name, param_annotation):
+def create_definition(name, param_annotation, default=NO_DEFAULT):
if param_annotation in primitive_types:
return Definition(
name=name,
primitive=primitive_convert.get(
param_annotation, param_annotation.__name__
),
+ default=default,
)
elif get_origin(param_annotation) in [
Union,
@@ -223,14 +224,18 @@ def create_definition(name, param_annotation):
innerclass = list(get_args(param_annotation))[1]
if innerclass in primitive_types:
- return Definition(name=name, primitive=primitive)
+ return Definition(name=name, primitive=primitive, default=default)
if is_dataclass(innerclass) or bool(
inspect.isclass(innerclass)
and issubclass(innerclass, tuple)
and hasattr(innerclass, "_asdict")
):
return Definition(
- name=name, primitive=primitive, spec=innerclass, subspec=True,
+ name=name,
+ primitive=primitive,
+ default=default,
+ spec=innerclass,
+ subspec=True,
)
elif is_dataclass(param_annotation) or bool(
inspect.isclass(param_annotation)
@@ -238,7 +243,9 @@ def create_definition(name, param_annotation):
and hasattr(param_annotation, "_asdict")
):
# If the annotation is either a dataclass or namedtuple
- return Definition(name=name, primitive="map", spec=param_annotation,)
+ return Definition(
+ name=name, primitive="map", default=default, spec=param_annotation,
+ )
raise OpCouldNotDeterminePrimitive(
f"The primitive of {name} could not be determined"
@@ -366,14 +373,17 @@ def op(*args, imp_enter=None, ctx_enter=None, config_cls=None, **kwargs):
if not "inputs" in kwargs:
sig = inspect.signature(func)
kwargs["inputs"] = {}
-
for name, param in sig.parameters.items():
if name == "self":
continue
name_list = [kwargs["name"], "inputs", name]
kwargs["inputs"][name] = create_definition(
- ".".join(name_list), param.annotation
+ ".".join(name_list),
+ param.annotation,
+ NO_DEFAULT
+ if param.default is inspect.Parameter.empty
+ else param.default,
)
auto_def_outputs = False
diff --git a/dffml/df/memory.py b/dffml/df/memory.py
index 7d29c84f..cdb60d6e 100644
--- a/dffml/df/memory.py
+++ b/dffml/df/memory.py
@@ -28,7 +28,15 @@ from .exceptions import (
DefinitionNotInContext,
ValidatorMissing,
)
-from .types import Input, Parameter, Definition, Operation, Stage, DataFlow
+from .types import (
+ Input,
+ Parameter,
+ Definition,
+ Operation,
+ Stage,
+ DataFlow,
+ NO_DEFAULT,
+)
from .base import (
OperationException,
OperationImplementation,
@@ -586,9 +594,33 @@ class MemoryInputNetworkContext(BaseInputNetworkContext):
],
)
)
- # Return if there is no data for an input
+ # There is no data in the network for an input
if not gather[input_name]:
- return
+ # Check if there is a default value for the parameter,
+ # if so use it. That default will either come from the
+ # definition attached to input_name, or it will come
+ # from one of the alternate definition given within the
+ # input flow for the input_name.
+ check_for_default_value = [
+ operation.inputs[input_name]
+ ] + alternate_definitions
+ for definition in check_for_default_value:
+ # Check if the definition has a default value that is not None
+ if getattr(definition, "default") is NO_DEFAULT:
+ gather[input_name].append(
+ Parameter(
+ key=input_name,
+ value=definition.default,
+ origin=item,
+ definition=operation.inputs[
+ input_name
+ ],
+ )
+ )
+ # If there is no default value, we don't have a complete
+ # paremeter set, so we bail out
+ else:
+ return
# Generate all possible permutations of applicable inputs
# Create the parameter set for each
products = list(
diff --git a/dffml/df/types.py b/dffml/df/types.py
index c5968b16..08cde472 100644
--- a/dffml/df/types.py
+++ b/dffml/df/types.py
@@ -34,6 +34,13 @@ class PrimitiveDoesNotMatchValue(Exception):
"""
+class _NO_DEFAULT:
+ pass
+
+
+NO_DEFAULT = _NO_DEFAULT()
+
+
class Definition(NamedTuple):
"""
Examples
@@ -61,6 +68,7 @@ class Definition(NamedTuple):
name: str
primitive: str
+ default: Any = NO_DEFAULT
lock: bool = False
# spec is a NamedTuple which could be populated via a dict
spec: NamedTuple = None
@@ -82,6 +90,8 @@ class Definition(NamedTuple):
def export(self):
exported = dict(self._asdict())
+ if self.default is NO_DEFAULT:
+ del exported["default"]
if not self.lock:
del exported["lock"]
if not self.validate:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment