Skip to content

Commit

Permalink
added html generator, and now don't need to specify addr
Browse files Browse the repository at this point in the history
  • Loading branch information
washad committed Jun 22, 2019
1 parent 1e7622d commit 8e203bb
Show file tree
Hide file tree
Showing 34 changed files with 690 additions and 24 deletions.
39 changes: 35 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class TestGroup1(IOGroup):
Bool2 = BooleanIO("Boolean 2", "Bool2", True)
Int1 = IntIO("Integer 1", "Int1")
Int2 = IntIO("Integer 2", "Int2", default=34)
Float1 = FloatIO("Float 1", "Float1", default=1.2)
MyFloat1 = FloatIO("Float 1", "Float1", default=1.2)
class TestGroup2(IOGroup):
Bool1 = BooleanIO("Boolean 1", "Bool1", False)
Expand All @@ -44,9 +44,40 @@ group1a = TestGroup1()
group1b = TestGroup1()
group2 = TestGroup2()
group1a.Float1 = 1234.5
print(group1b.Float1.value)
group1a.MyFloat1 = 1234.5 # Performs redis 'set', sending 1234.5 with key 'Float1'
print(group1b.Float1.value) # Performs redis 'get', calling 'value' converts to primitive type
print(group2.Float1.value)
~~~~

That is really all there is to it. For more specific cases, see the unit tests.
### HTML:
For convenience, methods are provided to automatically generate html. The
[dominate](https://github.com/Knio/dominate/blob/master/tests/test_html.py) library is used behind the scenes,
giving you first class access to manipulate the html response; Below is an example of usage,
consult the test cases for further examples.

~~~~
class TestGroup(IOGroup):
Bool1 = BooleanIO("Boolean 1", "Bool1", units="On/Off")
Float1 = FloatIO("Float 1", "Float1", default=1.23, units="furlongs")
h = HMTLIOGroup(test_group, "my_id", "my_namespace").html().render()
print(h) #-> Gives;
'''
<div class="my_namespace_io_container" id="my_id_io_container">
<div class="my_namespace_io" id="my_id_Bool1_io">
<div class="my_namespace_io_name">Boolean 1</div>
<div class="my_namespace_io_value" id="my_id_Bool1_io_value" onchange="OnIOValueChange(event)">False</div>
<div class="my_namespace_io_units">On/Off</div>
</div>
<div class="my_namespace_io" id="my_id_Float1_io">
<div class="my_namespace_io_name">Float 1</div>
<div class="my_namespace_io_value" id="my_id_Float1_io_value" onchange="OnIOValueChange(event)">1.23</div>
<div class="my_namespace_io_units">furlongs</div>
</div>
</div>
'''
~~~~
8 changes: 8 additions & 0 deletions build/lib/pyrediseasyio/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from pyrediseasyio.io.io_group import IOGroup
from pyrediseasyio.html.html_io_group import HMTLIOGroup
from pyrediseasyio.html.html_io import HTMLIO
from pyrediseasyio.io.base import SingleIO
from pyrediseasyio.io.boolean_io import BooleanIO
from pyrediseasyio.io.string_io import StringIO
from pyrediseasyio.io.float_io import FloatIO
from pyrediseasyio.io.integer_io import IntIO
Empty file.
52 changes: 52 additions & 0 deletions build/lib/pyrediseasyio/html/html_io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from pyrediseasyio.io.base import SingleIO
from dominate.tags import div, tr, td



class HTMLIO:

def __init__(self, io: SingleIO, html_id_header: str, namespace: str = 'pyredeio'):
self.io = io
self.namespace = namespace
self.html_id_header = html_id_header

@staticmethod
def html_id_for(header: str, attr: SingleIO):
return f'{header}_{attr.addr}_io'

@property
def html_id(self):
return self.html_id_for(self.html_id_header, self.io)

@property
def html_class(self):
return f'{self.namespace}_io'

def html(self, show_units: bool = True):
io = self.io
name, addr, val, units = io.name, io.addr, io.value, io.units
with div(cls=self.html_class, id=self.html_id) as container:
div(name, cls=f'{self.html_class}_name')
div(val, cls=f'{self.html_class}_value', id=f'{self.html_id}_value', onchange='OnIOValueChange(event)')
if show_units:
units = '' if units is None else units
div(units, cls=f'{self.html_class}_units')
return container

def html_row(self, show_units: bool = True):
io = self.io
name, addr, val, units = io.name, io.addr, io.value, io.units
with tr(cls=self.html_class, id=self.html_id) as container:
td(name, cls=f'{self.html_class}_name')
td(val, cls=f'{self.html_class}_value', id=f'{self.html_id}_value', onchange='OnIOValueChange(event)')
if show_units:
units = '' if units is None else units
td(units, cls=f'{self.html_class}_units')
return container







61 changes: 61 additions & 0 deletions build/lib/pyrediseasyio/html/html_io_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from pyrediseasyio.io.io_group import IOGroup
from pyrediseasyio.html.html_io import HTMLIO
from typing import List, Callable
from dominate.tags import div, table
import json


class HMTLIOGroup:

def __init__(self, io_group: IOGroup,
html_id_header: str,
namespace: str = 'pyredeio'):

self.html_id_header = html_id_header
self._io_group = io_group
self.namespace = namespace

@property
def html_id(self):
return f'{self.html_id_header}_io_container'

def html(self, by_names: List = None, by_type: List = None,
by_lambda_each: Callable = None, by_lambda_results: Callable = None,
html_classes: List = None):

attrs = self._io_group.get_attributes(by_names, by_type, by_lambda_each, by_lambda_results)
cls = f'{self.namespace}_io_container'
classes = html_classes.append(cls) if html_classes else [cls]
classes = ' '.join(classes)

with div(cls=classes, id=self.html_id) as container:
for attr in attrs:
HTMLIO(attr, self.html_id_header, self.namespace).html()
return container

def html_table(self, by_names: List = None, by_type: List = None,
by_lambda_each: Callable = None, by_lambda_results: Callable = None,
html_classes: List = None, show_units: bool=True):

attrs = self._io_group.get_attributes(by_names, by_type, by_lambda_each, by_lambda_results)
cls = f'{self.namespace}_io_container'
classes = html_classes.append(cls) if html_classes else [cls]
classes = ' '.join(classes)

with table(cls=classes, id=self.html_id) as container:
for attr in attrs:
HTMLIO(attr, self.html_id_header, self.namespace).html_row(show_units)
return container

def dumps(self, by_names: List = None, by_type: List = None,
by_lambda_each: Callable = None, by_lambda_results: Callable = None):

attrs = self._io_group.get_attributes(by_names, by_type, by_lambda_each, by_lambda_results)

def f(a):
return dict(id=HTMLIO.html_id_for(self.html_id_header, a), name=a.name, value=a.value, units=a.units)
results = [f(a) for a in attrs]

return json.dumps(results)


Empty file.
155 changes: 155 additions & 0 deletions build/lib/pyrediseasyio/io/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
from pyrediseasyio.abstract_reader_writer import AbstractReaderWriter
from dominate.tags import div, span, tr, td
import threading
import json

lock = threading.Lock()


class SingleIO:
def __init__(self, name: str, addr: str, default: object, units: str = None, reader: AbstractReaderWriter = None):
self.name = name
self.addr = addr
self._reader_writer = reader
self.default = default
self.units = units

def __and__(self, other):
if hasattr(other, 'value'):
return self.value and other.value
return self.value and other

def __add__(self, other):
if hasattr(other, 'value'):
other = other.value
return self.value + other

def __sub__(self, other):
if hasattr(other, 'value'):
other = other.value
return self.value - other

def __mul__(self, other):
if hasattr(other, 'value'):
other = other.value
return self.value * other

def __eq__(self, other):
if hasattr(other, 'value'):
other = other.value
return self.value == other

def __floordiv__(self, other):
if hasattr(other, 'value'):
other = other.value
return self.value // other

def __iadd__(self, other):
if hasattr(other, 'value'):
other = other.value
val = self.value
val += other
self.write(val)

def __idiv__(self, other):
if hasattr(other, 'value'):
other = other.value
val = self.value
val /= other
self.write(val)

def __ifloordiv__(self, other):
if hasattr(other, 'value'):
other = other.value
val = self.value
val //= other
self.write(val)

def __imul__(self, other):
if hasattr(other, 'value'):
other = other.value
val = self.value
val *= other
self.write(val)

def __invert__(self):
return ~self.value

def __ipow__(self, other):
if hasattr(other, 'value'):
other = other.value
val = self.value
val **= other
self.write(val)

def __isub__(self, other):
if hasattr(other, 'value'):
other = other.value
val = self.value
val -= other
self.write(val)

def __ne__(self, other):
if hasattr(other, 'value'):
other = other.value
return self.value != other

def __or__(self, other):
if hasattr(other, 'value'):
other = other.value
return self.value or other

def __pos__(self):
return self.value

def __pow__(self, power, modulo=None):
if hasattr(power, 'value'):
power = power.value
return self.value ** power

def __neg__(self):
return -self.value

def __set__(self, obj, value):
self.write(value)

def __str__(self):
return f'[{type(self).__name__}] {self.name} = {self.value} {self.units}'

def __truediv__(self, other):
if hasattr(other, 'value'):
other = other.value
return self.value / other

@property
def value(self):
return self.read()

@staticmethod
def _convert_type(value):
return value

def publish(self, value, channel: str = None, and_write: bool = False):
value = self._convert_type(value)
data = json.dumps({self.addr: value})
self._reader_writer.publish(data, channel)
if and_write:
self.write(value)

def read(self):
if self._reader_writer is None:
return None
with lock:
val = self._reader_writer.read(self.addr)
if val is None:
val = self.default
val = self._convert_type(val)
return val

def write(self, value):
if self._reader_writer is None:
return
with lock:
value = self._convert_type(value)
self._reader_writer.write(self.addr, value)

24 changes: 24 additions & 0 deletions build/lib/pyrediseasyio/io/boolean_io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from pyrediseasyio import SingleIO
from pyrediseasyio.abstract_reader_writer import AbstractReaderWriter
from str2bool import str2bool


class BooleanIO(SingleIO):
def __init__(self, name: str, addr: str, default: bool = False, units: str = None,
reader: AbstractReaderWriter = None):
super().__init__(name, addr, default, units, reader)

@staticmethod
def _convert_type(value):
if value is None:
return False
if isinstance(value, str):
return str2bool(value)
return bool(value)

def __bool__(self):
return self.value

@property
def value(self) -> bool:
return super().value
13 changes: 13 additions & 0 deletions build/lib/pyrediseasyio/io/float_io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from pyrediseasyio import SingleIO
from pyrediseasyio.abstract_reader_writer import AbstractReaderWriter


class FloatIO(SingleIO):
def __init__(self, name: str, addr: str, default: float = 0, units: str = None, reader: AbstractReaderWriter = None):
super().__init__(name, addr, default, units, reader)

@staticmethod
def _convert_type(value):
return float(value)


14 changes: 14 additions & 0 deletions build/lib/pyrediseasyio/io/integer_io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from pyrediseasyio import SingleIO
from pyrediseasyio.abstract_reader_writer import AbstractReaderWriter


class IntIO(SingleIO):
def __init__(self, name: str, addr: str, default: int = 0, units: str = None, reader: AbstractReaderWriter = None):
super().__init__(name, addr, default, units, reader)

@staticmethod
def _convert_type(value):
return int(value)



Loading

0 comments on commit 8e203bb

Please sign in to comment.