-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathadvanced_example.py
More file actions
202 lines (152 loc) · 6 KB
/
advanced_example.py
File metadata and controls
202 lines (152 loc) · 6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#!/usr/bin/env python
# -*- coding: utf-8 -*-
""" An example of advanced mutaprops functions:
* parameter grouping
* mutasources
* custom styling
* static files - images in the docstrings
* raw HTML
* asyncio integration
* multiple objects
* custom help
Note that this example uses files in the ``assets/`` directory.
Credits:
Hoovercraft logo created by Theresa Stoodley from the Noun Project.
Licensed under Creative Commons 3.0
"""
# TODO: class-level mutasources and mutaprops example
from mutaprops import *
from mutaprops.utils import rest_to_html
import asyncio
import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
logger = logging.getLogger(__name__)
@mutaprop_class("Hoovercraft UI")
class Hoovercraft:
MAX_EELS = 40
def __init__(self, number_of_eels=20, speed=0, direction='North'):
self._eel_count = number_of_eels
self._speed = speed
self._direction = direction
self._engine_running = False
self._steering_locked = True
self._eel_display = None
self._set_eel_display(self._eel_count)
# Following is the example of raw HTML support. It's basically an
# attribute containing HTML code.
# In case of change, the entier code is forwarded over websocket,
# so it's not very efficient solution. Some upgrades are planned.
@mutaproperty("Eel loading process",
MutaTypes.HTML,
hierarchy='Eel control') # Note the hierarchy argument, explained below
def eel_display(self):
return self._eel_display
@eel_display.setter
def eel_display(self, value):
self._eel_display = value
def _set_eel_display(self, value):
""" Wrapper for Raw HTML property setting."""
self.eel_display = """<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="{0}"
aria-valuemin="0" aria-valuemax="100"
style="min-width: 2em; width: {0}%;"> {0}% </div>
</div>
""".format((value/self.MAX_EELS)*100)
# Hierarchy allows grouping of parameters into an UI panels
# Panels can be minimized to save space (only in UI)
# Hierarchy can be flat (like in this example) or can have sub-sections
# like "Eel control/loading" etc. (then panel in panel would be created)
@mutaproperty("Number of eels", MutaTypes.INT,
min_val=0, max_val=MAX_EELS,
hierarchy='Eel control')
def eels(self):
return self._eel_count
@eels.setter
def eels(self, value):
self._eel_count = value
self._set_eel_display(self._eel_count)
if self._eel_count >= self.MAX_EELS:
logger.warning("The hoovercraft is full of eels!")
@mutaprop_action("Drop all eels!", hierarchy='Eel control')
def drop_all_eels(self):
self.eels = 0
logger.info("Eels are goooone!")
# Autodocumentation is generated from the function docstrings.
# On UI level, it makes the name of the mutapropert clickable,
# The documentation is then expanded upon clicking on the mutaprop name.
@mutaproperty("Engine state", MutaTypes.BOOL,
toggle={'on': 'Running', 'off': 'Stopped'},
hierarchy='Hoovercraft control')
def engine(self):
""" Hoovercraft engine is very very noisy.
Can be set to **running** or **stopped**.
.. image:: local/hoovercraft-scheme.png
Image by
`MesserWolland <https://commons.wikimedia.org/wiki/User:MesserWoland>`_
licensed under
`CC BY-SA 3.0 <http://creativecommons.org/licenses/by-sa/3.0/>`_.
"""
return self._engine_running
@engine.setter
def engine(self, value):
self._engine_running = value
self.steering_locked = not value
logger.info("Engine %s",
'started' if self._engine_running else 'stopped')
@mutasource
def steering_locked(self):
return self._steering_locked
@steering_locked.setter
def steering_locked(self, value):
self._steering_locked = value
@mutaproperty("Speed [km/h]", MutaTypes.INT, min_val=0, max_val=80,
read_only=steering_locked,
hierarchy='Hoovercraft control')
def speed(self):
return self._speed
@speed.setter
def speed(self, value):
self._speed = value
logger.info("Speed set to %d km/h", self._speed)
@mutaproperty("Direction of travel", MutaTypes.STRING,
select=['North', 'East', 'South', 'West'],
read_only=steering_locked,
hierarchy='Hoovercraft control')
def direction(self):
return self._direction
@direction.setter
def direction(self, value):
self._direction = value
logger.info("Going %s", self._direction)
custom_help = """
Hoovercraft manager
-------------------
This is an example help text, accessible through the help link in the
right top corner.
.. image:: http://i.imgur.com/WlOrqdR.jpg
It's ReST formatted, so it needs to be converted to HTML first.
use ``mutaprops.utils.rest_to_html`` for that.
"""
@asyncio.coroutine
def update_eels(obj):
while True:
obj.eels += 1
yield from asyncio.sleep(1)
if obj.eels > obj.MAX_EELS:
obj.drop_all_eels()
yield from asyncio.sleep(1)
if __name__ == '__main__':
test = Hoovercraft()
test.muta_init("Hoovercraft #1") # Initializes the mutaproperties.
test2 = Hoovercraft()
# Example of some asyncio stuff
loop = asyncio.get_event_loop()
loop.create_task(update_eels(test))
man = HttpMutaManager("Hoovercraft manager", proxy_log=logger,
loop=loop, # UI manager will run in app's loop.
local_dir="assets",
help_doc=rest_to_html(custom_help))
man.add_object(test)
man.add_object(test2, "Hoovercraft #2") # We can also muta-init object while adding, just by specifying the ID as the argument.
man.run(port=9000)