Skip to content

Commit

Permalink
Rename "Ports" to "Bindings" (#244)
Browse files Browse the repository at this point in the history
* Renome ports to bindings

* Remove Binding Suffix, Make Verb construction last-mile

* formatting

* update coverage

* formatting

* update version check script

* revert version-check.yml
  • Loading branch information
darthtrevino committed Jun 27, 2024
1 parent afb47b4 commit 7b820eb
Show file tree
Hide file tree
Showing 20 changed files with 499 additions and 384 deletions.
28 changes: 14 additions & 14 deletions python/reactivedataflow/reactivedataflow/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# Copyright (c) 2024 Microsoft Corporation.
"""The reactivedataflow Library."""

from .bindings import (
ArrayInput,
Bindings,
Config,
Input,
NamedInputs,
Output,
)
from .decorators import (
apply_decorators,
connect_input,
Expand All @@ -22,14 +30,6 @@
VerbInput,
VerbOutput,
)
from .ports import (
ArrayInputPort,
ConfigPort,
InputPort,
NamedInputsPort,
OutputPort,
Ports,
)
from .registry import Registry

# Public API
Expand All @@ -43,20 +43,20 @@
# - reactivedataflow.conditions - this contains a listing of emit and fire condition functions for users of the library.
# - recativedataflow.model - this contains the Pydantic model for graph assembly.
__all__ = [
"ArrayInputPort",
"ConfigPort",
"ArrayInput",
"Bindings",
"Config",
"EmitMode",
"ExecutionGraph",
"ExecutionNode",
"GraphAssembler",
"Input",
"InputMode",
"InputNode",
"InputPort",
"NamedInputsPort",
"NamedInputs",
"Node",
"Output",
"OutputMode",
"OutputPort",
"Ports",
"Registry",
"VerbInput",
"VerbOutput",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from reactivedataflow.utils.equality import IsEqualCheck


class ArrayInputPort(BaseModel, extra="allow"):
class ArrayInput(BaseModel, extra="allow"):
"""Specification for an array-based input port."""

type: str | None = Field(default=None, description="The type of the port.")
Expand All @@ -23,7 +23,7 @@ class ArrayInputPort(BaseModel, extra="allow"):
)


class NamedInputsPort(BaseModel, extra="allow"):
class NamedInputs(BaseModel, extra="allow"):
"""Specification for injecting all named inputs as a single dictionary."""

type: dict[str, str] | None = Field(
Expand All @@ -38,7 +38,7 @@ class NamedInputsPort(BaseModel, extra="allow"):
)


class InputPort(BaseModel, extra="allow"):
class Input(BaseModel, extra="allow"):
"""Specification for a named input port."""

name: str = Field(..., description="The name of the port.")
Expand All @@ -52,7 +52,7 @@ class InputPort(BaseModel, extra="allow"):
)


class OutputPort(BaseModel, extra="allow"):
class Output(BaseModel, extra="allow"):
"""Specification for an output port."""

name: str = Field(..., description="The name of the port.")
Expand All @@ -65,7 +65,7 @@ class OutputPort(BaseModel, extra="allow"):
)


class ConfigPort(BaseModel, extra="allow"):
class Config(BaseModel, extra="allow"):
"""Specification for a configuration field of an verb function."""

name: str = Field(..., description="The name of the port.")
Expand All @@ -77,56 +77,58 @@ class ConfigPort(BaseModel, extra="allow"):
)


Port = InputPort | ArrayInputPort | NamedInputsPort | ConfigPort | OutputPort
Binding = Input | ArrayInput | NamedInputs | Config | Output


class Ports:
"""PortMapper class."""
class Bindings:
"""Node Binding Managemer class.
_ports: list[Port]
Node bindings are used to map processing-graph inputs, outputs, and configuration values into the appropriate
function parameters. This class is used to manage the bindings for a node.
"""

def __init__(self, ports: list[Port]):
self._ports = ports
_bindings: list[Binding]

def __init__(self, ports: list[Binding]):
self._bindings = ports
self._validate()

def _validate(self):
"""Validate the ports."""
input_names = [port.name for port in self.ports if isinstance(port, InputPort)]
input_names = [port.name for port in self.bindings if isinstance(port, Input)]
if len(input_names) != len(set(input_names)):
raise PortNamesMustBeUniqueError

config_names = [
port.name for port in self.ports if isinstance(port, ConfigPort)
]
config_names = [port.name for port in self.bindings if isinstance(port, Config)]
if len(config_names) != len(set(config_names)):
raise PortNamesMustBeUniqueError

@property
def ports(self) -> list[Port]:
"""Return the ports."""
return self._ports
def bindings(self) -> list[Binding]:
"""Return the bindings."""
return self._bindings

@property
def config(self) -> list[ConfigPort]:
"""Return the configuration ports."""
return [port for port in self.ports if isinstance(port, ConfigPort)]
def config(self) -> list[Config]:
"""Return the configuration bindings."""
return [port for port in self.bindings if isinstance(port, Config)]

@property
def input(self) -> list[InputPort]:
"""Return the input ports."""
return [port for port in self.ports if isinstance(port, InputPort)]
def input(self) -> list[Input]:
"""Return the input bindings."""
return [port for port in self.bindings if isinstance(port, Input)]

@property
def outputs(self) -> list[OutputPort]:
"""Return the output ports."""
return [port for port in self._ports if isinstance(port, OutputPort)]
def outputs(self) -> list[Output]:
"""Return the output bindings."""
return [port for port in self._bindings if isinstance(port, Output)]

@property
def array_input(self) -> ArrayInputPort | None:
def array_input(self) -> ArrayInput | None:
"""Return the array input port."""
return next((p for p in self._ports if isinstance(p, ArrayInputPort)), None)
return next((p for p in self._bindings if isinstance(p, ArrayInput)), None)

@property
def named_inputs(self) -> NamedInputsPort | None:
def named_inputs(self) -> NamedInputs | None:
"""Return the named inputs port."""
return next((p for p in self._ports if isinstance(p, NamedInputsPort)), None)
return next((p for p in self._bindings if isinstance(p, NamedInputs)), None)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright (c) 2024 Microsoft Corporation.
"""reactivedataflow Decorators."""

from .apply_decorators import apply_decorators
from .apply_decorators import AnyFn, Decorator, apply_decorators
from .connect_input import connect_input
from .connect_output import connect_output
from .emit_conditions import emit_conditions
Expand All @@ -10,6 +10,8 @@
from .verb import verb

__all__ = [
"AnyFn",
"Decorator",
"apply_decorators",
"connect_input",
"connect_output",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@
from functools import reduce
from typing import Any

Decorator = Callable[[Callable[..., Any]], Callable[..., Any]]
AnyFn = Callable[..., Any]
Decorator = Callable[[AnyFn], AnyFn]


def apply_decorators(
fn: Callable[..., Any], decorators: list[Decorator]
) -> Callable[..., Any]:
def apply_decorators(fn: AnyFn, decorators: list[Decorator]) -> AnyFn:
"""
Apply a series of decorators to a function reference.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
from collections.abc import Callable
from typing import Any, ParamSpec, TypeVar, cast

from reactivedataflow.bindings import Bindings
from reactivedataflow.nodes import VerbInput
from reactivedataflow.ports import Ports

T = TypeVar("T")
P = ParamSpec("P")


def connect_input(
ports: Ports,
bindings: Bindings,
) -> Callable[[Callable[P, T]], Callable[[VerbInput], T]]:
"""Decorate an execution function with input conditions.
Expand All @@ -27,26 +27,27 @@ def wrapped_fn(inputs: VerbInput, *args: P.args, **kwargs: P.kwargs) -> T:
fn_kwargs = {**kwargs}

# Inject named-input Dictionary
named_inputs_port = ports.named_inputs
named_inputs_port = bindings.named_inputs
if (
named_inputs_port is not None
and named_inputs_port.parameter is not None
):
fn_kwargs[named_inputs_port.parameter] = inputs.named_inputs

# Inject array-ports
array_port = ports.array_input
# Inject array input
array_port = bindings.array_input
if array_port is not None and array_port.parameter is not None:
fn_kwargs[array_port.parameter] = inputs.array_inputs

# Inject named ports
# Inject named parameters
fn_kwargs.update({
p.parameter or p.name: inputs.named_inputs.get(p.name)
for p in ports.input
for p in bindings.input
})
# Inject config ports
# Inject configuration values
fn_kwargs.update({
p.parameter or p.name: inputs.config.get(p.name) for p in ports.config
p.parameter or p.name: inputs.config.get(p.name)
for p in bindings.config
})

return cast(Any, fn)(*args, **fn_kwargs)
Expand Down
Loading

0 comments on commit 7b820eb

Please sign in to comment.