Skip to content

Commit

Permalink
finished Str, Bool, Int, ... functions
Browse files Browse the repository at this point in the history
  • Loading branch information
semiversus committed Sep 30, 2018
1 parent c6c799b commit cb9aea9
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 7 deletions.
4 changes: 4 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ Also fancy stuff like getting item by index or key is possible:
>>> d.emit({'c':123})
r: 123
Some python built in functions can't return Publishers (e.g. ``len()`` needs to
return an integer). For this cases special functions are defined in broqer: ``Str``,
``Int``, ``Float``, ``Len`` and ``In`` (for ``x in y``).

Asyncio Support
---------------

Expand Down
4 changes: 2 additions & 2 deletions broqer/op/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

# enable operator overloading
from .operator_overloading import apply_operator_overloading, Str, Bool, Int, \
Float, Repr, Len
Float, Repr, Len, In

apply_operator_overloading()

Expand All @@ -44,5 +44,5 @@
'False_', 'Trace', 'build_map', 'build_reduce', 'build_combine_latest',
'build_filter', 'build_accumulate', 'build_map_async',
'build_map_threaded', 'build_sink', 'Str', 'Bool', 'Int', 'Float', 'Repr',
'Len'
'Len', 'In'
]
34 changes: 31 additions & 3 deletions broqer/op/operator_overloading.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
""" This module enables the operator overloading of publishers """
import asyncio
import operator
import math
import operator
from functools import partial
from typing import Any

from broqer import Publisher
from broqer.op import CombineLatest
from broqer.op.operator import Operator


Expand Down Expand Up @@ -74,8 +76,6 @@ def apply_operator_overloading():
'__pow__', '__rshift__', '__sub__', '__xor__', '__concat__',
'__getitem__', '__floordiv__', '__truediv__'):
def _op(operand_left, operand_right, operation=method):
from broqer.op import CombineLatest

if isinstance(operand_right, Publisher):
return CombineLatest(operand_left, operand_right,
map_=getattr(operator, operation))
Expand Down Expand Up @@ -109,30 +109,58 @@ def _op_unary(operand, operation=_method):


class Str(_MapUnary):
""" Implementing the functionality of str() for publishers. """
def __init__(self, publisher: Publisher) -> None:
_MapUnary.__init__(self, publisher, str)


class Bool(_MapUnary):
""" Implementing the functionality of bool() for publishers. """
def __init__(self, publisher: Publisher) -> None:
_MapUnary.__init__(self, publisher, bool)


class Int(_MapUnary):
""" Implementing the functionality of int() for publishers. """
def __init__(self, publisher: Publisher) -> None:
_MapUnary.__init__(self, publisher, int)


class Float(_MapUnary):
""" Implementing the functionality of float() for publishers. """
def __init__(self, publisher: Publisher) -> None:
_MapUnary.__init__(self, publisher, float)


class Repr(_MapUnary):
""" Implementing the functionality of repr() for publishers. """
def __init__(self, publisher: Publisher) -> None:
_MapUnary.__init__(self, publisher, repr)


class Len(_MapUnary):
""" Implementing the functionality of len() for publishers. """
def __init__(self, publisher: Publisher) -> None:
_MapUnary.__init__(self, publisher, len)


def _in(item, container):
return item in container


class In(CombineLatest):
""" Implementing the functionality of ``in`` operator for publishers.
:param item: publisher or constant to check for availability in container.
:param container: container (publisher or constant)
"""
def __init__(self, item: Any, container: Any) -> None:
if isinstance(item, Publisher) and isinstance(container, Publisher):
CombineLatest.__init__(self, item, container, map_=_in)
elif isinstance(item, Publisher):
function = partial(_in, container=container)
CombineLatest.__init__(self, item, map_=function)
else:
assert isinstance(container, Publisher), \
'item or container has to be a publisher'
function = partial(_in, item)
CombineLatest.__init__(self, container, map_=function)
35 changes: 33 additions & 2 deletions test/test_core_publisher_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,14 @@ def test_getitem():
(operator.neg, -5, 5), (operator.neg, 'ab', TypeError), (operator.pos, -5, -5),
(operator.pos, Counter({'a':0, 'b':1}), Counter({'b':1})), (operator.abs, -5, 5),
(operator.invert, 5, -6), (round, 5.2, 5), (round, 5.8, 6), (math.trunc, -5.2, -5),
(math.floor, -5.2, -6), (math.ceil, -5.2, -5)
(math.floor, -5.2, -6), (math.ceil, -5.2, -5),
(op.Str, 123, '123'), (op.Str, (1, 2), '(1, 2)'), (op.Str, 1.23, '1.23'),
(op.Bool, 0, False), (op.Bool, 1, True), (op.Bool, 'False', True), (op.Bool, (1,2,3), True),
(op.Bool, {}, False), (op.Bool, None, False), (op.Bool, 513.17, True), (op.Bool, 0.0, False),
(op.Int, 1.99, 1), (op.Int, '123', 123), (op.Int, (1, 2, 3), TypeError), (op.Int, None, TypeError),
(op.Float, 1, 1.0), (op.Float, '12.34', 12.34), (op.Float, 'abc', ValueError),
(op.Repr, 123, '123'), (op.Repr, 'abc', "'abc'"), (op.Repr, int, "<class 'int'>"),
(op.Len, (), 0), (op.Len, [1,2,3], 3), (op.Len, 'abcde', 5), (op.Len, None, TypeError),
])
def test_unary_operators(operator, value, result):
v = StatefulPublisher(value)
Expand All @@ -266,4 +273,28 @@ def test_unary_operators(operator, value, result):
except Exception as e:
assert isinstance(e, result)
else:
assert cb.mock_called_once_with(result)
assert cb.mock_called_once_with(result)

def test_in_operator():
pi = Value(1)
ci = 1

pc = Value((1,2,3))
cc = (1, 2, 3)

dut1 = op.In(pi, pc)
dut2 = op.In(ci, pc)
dut3 = op.In(pi, cc)
with pytest.raises(AssertionError):
op.In(ci, cc)

assert dut1.get() == True
assert dut2.get() == True
assert dut3.get() == True

pi.emit('a')
pc.emit((2.3, 'b'))

assert dut1.get() == False
assert dut2.get() == False
assert dut3.get() == False

0 comments on commit cb9aea9

Please sign in to comment.