Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# AGENTS

## General
- Use `uv` as the default package manager and runner.
- Keep code simple and self-documenting; do not add random comments.

## Typing
- Use strong, explicit typing everywhere.
- This library is mypy-heavy; ensure all code type-checks cleanly.

## Documentation pattern
- Follow the existing docstring style used in the codebase (reST/Sphinx style).
- Prefer structured sections like `Args:`, `Returns:`, `Raises:`, `Example:`, and `See Also:` when documenting.

## Testing
- Always run the full test suite at the end of a task (use `uv`).
6 changes: 2 additions & 4 deletions gloe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
from gloe.conditional import If, condition
from gloe.ensurer import ensure
from gloe.exceptions import UnsupportedTransformerArgException
from gloe.transformers import Transformer, MultiArgsTransformer
from gloe.transformers import Transformer
from gloe.base_transformer import BaseTransformer, PreviousTransformer
from gloe.base_transformer import TransformerException
from gloe.async_transformer import AsyncTransformer, MultiArgsAsyncTransformer
from gloe.async_transformer import AsyncTransformer

__version__ = "0.7.0"

Expand All @@ -33,5 +33,3 @@

setattr(Transformer, "__rshift__", _compose_nodes)
setattr(AsyncTransformer, "__rshift__", _compose_nodes)
setattr(MultiArgsTransformer, "__rshift__", _compose_nodes)
setattr(MultiArgsAsyncTransformer, "__rshift__", _compose_nodes)
194 changes: 86 additions & 108 deletions gloe/_composition_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
from inspect import Signature
from typing import TypeVar, Any, Optional, Union

from gloe.async_transformer import AsyncTransformer, MultiArgsAsyncTransformer
from gloe.async_transformer import AsyncTransformer
from gloe.base_transformer import BaseTransformer
from gloe.gateways._parallel import _Parallel, _ParallelAsync
from gloe.transformers import Transformer, MultiArgsTransformer
from gloe.transformers import Transformer
from gloe._typing_utils import _match_types, _specify_types
from gloe.exceptions import UnsupportedTransformerArgException

Expand All @@ -23,16 +23,15 @@ def is_transformer(node):
def _resolve_serial_connection_signatures(
transformer1: BaseTransformer, transformer2: BaseTransformer, generic_vars: dict
) -> Signature:
signature2 = transformer2.signature()
first_param = list(signature2.parameters.values())[0]
new_parameter = first_param.replace(
annotation=_specify_types(transformer1.input_type, generic_vars)
)
new_signature = signature2.replace(
parameters=[new_parameter],
signature1 = transformer1.signature()
parameters = [
parameter.replace(annotation=_specify_types(parameter.annotation, generic_vars))
for parameter in signature1.parameters.values()
]
return signature1.replace(
parameters=parameters,
return_annotation=_specify_types(transformer2.output_type, generic_vars),
)
return new_signature


def _compose_serial(transformer1, _transformer2):
Expand All @@ -50,8 +49,15 @@ def _compose_serial(transformer1, _transformer2):
generic_vars = {**input_generic_vars, **output_generic_vars}

def transformer1_signature(_) -> Signature:
parameters = [
parameter.replace(
annotation=_specify_types(parameter.annotation, generic_vars)
)
for parameter in signature1.parameters.values()
]
return signature1.replace(
return_annotation=_specify_types(signature1.return_annotation, generic_vars)
parameters=parameters,
return_annotation=_specify_types(signature1.return_annotation, generic_vars),
)

setattr(
Expand All @@ -76,55 +82,26 @@ def __len__(self):
new_transformer: Optional[BaseTransformer] = None
if is_transformer(transformer1) and is_transformer(transformer2):

if isinstance(transformer1, MultiArgsTransformer):

class NewMultiArgsTransformer(BaseNewTransformer, MultiArgsTransformer):
def __init__(self):
super().__init__()
self._flow = transformer1._flow + transformer2._flow

def transform(self, data):
return None

new_transformer = NewMultiArgsTransformer()

else:
class NewTransformer1(BaseNewTransformer, Transformer[_In, _NextOut]):
def __init__(self):
super().__init__()
self._flow = transformer1._flow + transformer2._flow

class NewTransformer1(BaseNewTransformer, Transformer[_In, _NextOut]):
def __init__(self):
super().__init__()
self._flow = transformer1._flow + transformer2._flow
def transform(self, *data):
return None

def transform(self, data):
return None

new_transformer = NewTransformer1()
new_transformer = NewTransformer1()
else:

if isinstance(transformer1, MultiArgsAsyncTransformer):

class NewMultiArgsAsyncTransformer(
BaseNewTransformer, MultiArgsAsyncTransformer
):
def __init__(self):
super().__init__()
self._flow = transformer1._flow + transformer2._flow
class NewTransformer2(BaseNewTransformer, AsyncTransformer[_In, _NextOut]):
def __init__(self):
super().__init__()
self._flow = transformer1._flow + transformer2._flow

async def transform_async(self, data):
return None

new_transformer = NewMultiArgsAsyncTransformer()
else:
async def transform_async(self, *data):
return None

class NewTransformer2(BaseNewTransformer, AsyncTransformer[_In, _NextOut]):
def __init__(self):
super().__init__()
self._flow = transformer1._flow + transformer2._flow

async def transform_async(self, data):
return None

new_transformer = NewTransformer2()
new_transformer = NewTransformer2()

new_transformer.__class__.__name__ = transformer2.__class__.__name__
new_transformer._label = transformer2.label
Expand All @@ -149,6 +126,41 @@ def _compose_diverging(
)

class BaseNewTransformer:
def signature(self) -> Signature:
incident_signature = incident_transformer.signature()
generic_vars: dict = {}
for receiving_transformer in receiving_transformers:
generic_vars.update(
_match_types(
receiving_transformer.input_type,
incident_transformer.output_type,
)
)
generic_vars.update(
_match_types(
incident_transformer.output_type,
receiving_transformer.input_type,
)
)

parameters = [
parameter.replace(
annotation=_specify_types(parameter.annotation, generic_vars)
)
for parameter in incident_signature.parameters.values()
]
return_types = [
_specify_types(
receiving_transformer.signature().return_annotation,
generic_vars,
)
for receiving_transformer in receiving_transformers
]
return incident_signature.replace(
parameters=parameters,
return_annotation=types.GenericAlias(tuple, tuple(return_types)),
)

def __len__(self):
lengths = [len(t) for t in receiving_transformers]
return sum(lengths) + len(incident_transformer)
Expand All @@ -157,67 +169,33 @@ def __len__(self):

if is_transformer(incident_transformer) and is_transformer(receiving_transformers):

if isinstance(incident_transformer, MultiArgsTransformer):

class NewMultiArgsTransformer(BaseNewTransformer, MultiArgsTransformer):
def __init__(self):
super().__init__()
self._flow = incident_transformer._flow + [
_Parallel(*receiving_transformers)
]

def transform(self, data):
return None

new_transformer = NewMultiArgsTransformer()
else:

class NewTransformer1(
BaseNewTransformer, Transformer[_In, tuple[Any, ...]]
):
def __init__(self):
super().__init__()
self._flow = incident_transformer._flow + [
_Parallel(*receiving_transformers)
]
class NewTransformer1(BaseNewTransformer, Transformer[_In, tuple[Any, ...]]):
def __init__(self):
super().__init__()
self._flow = incident_transformer._flow + [
_Parallel(*receiving_transformers)
]

def transform(self, data):
return None
def transform(self, *data):
return None

new_transformer = NewTransformer1()
new_transformer = NewTransformer1()

else:

if isinstance(incident_transformer, MultiArgsAsyncTransformer):

class NewMultiArgsAsyncTransformer(
BaseNewTransformer, MultiArgsAsyncTransformer
):
def __init__(self):
super().__init__()
self._flow = incident_transformer._flow + [
_ParallelAsync(*receiving_transformers)
]

async def transform_async(self, data):
return None

new_transformer = NewMultiArgsAsyncTransformer()
else:

class NewTransformer2(
BaseNewTransformer, AsyncTransformer[_In, tuple[Any, ...]]
):
def __init__(self):
super().__init__()
self._flow = incident_transformer._flow + [
_ParallelAsync(*receiving_transformers)
]
class NewTransformer2(
BaseNewTransformer, AsyncTransformer[_In, tuple[Any, ...]]
):
def __init__(self):
super().__init__()
self._flow = incident_transformer._flow + [
_ParallelAsync(*receiving_transformers)
]

async def transform_async(self, data):
return None
async def transform_async(self, *data):
return None

new_transformer = NewTransformer2()
new_transformer = NewTransformer2()

# new_transformer._previous = cast(Transformer, receiving_transformers)
new_transformer.__class__.__name__ = "Converge"
Expand Down
Loading