PyObjectInterface 0.0.2__py3-none-any.whl → 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- PyObjectInterface/WebController.py +27 -6
- PyObjectInterface/examples/example.py +8 -0
- PyObjectInterface/examples/robot.py +31 -0
- PyObjectInterface/web_controller.tpl.html +10 -7
- PyObjectInterface-0.1.0.dist-info/METADATA +79 -0
- PyObjectInterface-0.1.0.dist-info/RECORD +10 -0
- {PyObjectInterface-0.0.2.dist-info → PyObjectInterface-0.1.0.dist-info}/WHEEL +1 -1
- PyObjectInterface-0.0.2.dist-info/METADATA +0 -29
- PyObjectInterface-0.0.2.dist-info/RECORD +0 -8
- {PyObjectInterface-0.0.2.dist-info → PyObjectInterface-0.1.0.dist-info}/LICENSE +0 -0
- {PyObjectInterface-0.0.2.dist-info → PyObjectInterface-0.1.0.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from PyObjectInterface import PyObjectInterface
|
|
2
2
|
from os import path
|
|
3
|
+
import traceback
|
|
3
4
|
import flask
|
|
4
5
|
|
|
5
6
|
def generate_html(poi: PyObjectInterface, font_size=2.5):
|
|
@@ -17,6 +18,8 @@ def generate_html(poi: PyObjectInterface, font_size=2.5):
|
|
|
17
18
|
className = 'py_' + stack
|
|
18
19
|
elemID = className + '|' + arg_name
|
|
19
20
|
buttons += f"<span class='input_label'>{arg_name}</span>"
|
|
21
|
+
if len(default) > 0 and default[0] == "'":
|
|
22
|
+
default = '"' + default[1:-1] + '"'
|
|
20
23
|
buttons += f"<input id='{elemID}' class='{className}' value='{default}'>"
|
|
21
24
|
if func_desc.desc is not None:
|
|
22
25
|
desc = func_desc.desc.strip().replace('\n','<br>')
|
|
@@ -44,6 +47,15 @@ def generate_html(poi: PyObjectInterface, font_size=2.5):
|
|
|
44
47
|
</details>
|
|
45
48
|
""")
|
|
46
49
|
|
|
50
|
+
def smart_arg_parse(x):
|
|
51
|
+
if x == 'None':
|
|
52
|
+
return None
|
|
53
|
+
if x[0] == '"' or x[0] == "'":
|
|
54
|
+
return x[1:-1] #strip trailing and leading quotes
|
|
55
|
+
if '.' in x:
|
|
56
|
+
return float(x)
|
|
57
|
+
return int(x)
|
|
58
|
+
|
|
47
59
|
def create_WebController(obj, name, flask_app, recursion_depth = 5, create_private_interface=True):
|
|
48
60
|
with open(path.dirname(__file__) + '/web_controller.tpl.html') as f:
|
|
49
61
|
tpl = f.read()
|
|
@@ -57,12 +69,21 @@ def create_WebController(obj, name, flask_app, recursion_depth = 5, create_priva
|
|
|
57
69
|
|
|
58
70
|
@flask_app.route(baseurl + '/call_method/<stack>', endpoint=baseurl + '_call_method')
|
|
59
71
|
def call_method(stack):
|
|
60
|
-
kwargs = {argname:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
72
|
+
kwargs = {argname: smart_arg_parse(arg) for argname, arg in flask.request.args.items()}
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
retval = poi.call_method(stack, kwargs)
|
|
76
|
+
if retval is None:
|
|
77
|
+
return ''
|
|
78
|
+
else:
|
|
79
|
+
return str(retval)
|
|
80
|
+
except (Exception,):
|
|
81
|
+
traces = traceback.format_exc().split('\n')
|
|
82
|
+
for i in range(6):
|
|
83
|
+
traces.pop(1) #remove the webcontroller call from the trace
|
|
84
|
+
trace = '\n'.join(traces)
|
|
85
|
+
return "Internal Error:\n" + trace
|
|
86
|
+
|
|
66
87
|
|
|
67
88
|
@flask_app.route(baseurl + '/get_attributes', endpoint=baseurl + '_get_attributes')
|
|
68
89
|
def get_attributes():
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
class DriveMotor:
|
|
2
|
+
def __init__(self, pin):
|
|
3
|
+
self.pin = pin
|
|
4
|
+
self.speed = 0
|
|
5
|
+
|
|
6
|
+
def forward(self):
|
|
7
|
+
self.speed = 50
|
|
8
|
+
|
|
9
|
+
def stop(self):
|
|
10
|
+
self.speed = 0
|
|
11
|
+
|
|
12
|
+
class Robot:
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self.left_motor = DriveMotor(1)
|
|
15
|
+
self.right_motor = DriveMotor(2)
|
|
16
|
+
|
|
17
|
+
def forward(self):
|
|
18
|
+
self.left_motor.forward()
|
|
19
|
+
self.right_motor.forward()
|
|
20
|
+
|
|
21
|
+
def stop(self):
|
|
22
|
+
self.left_motor.stop()
|
|
23
|
+
self.right_motor.stop()
|
|
24
|
+
|
|
25
|
+
def left(self):
|
|
26
|
+
self.left_motor.stop()
|
|
27
|
+
self.right_motor.forward()
|
|
28
|
+
|
|
29
|
+
def right(self):
|
|
30
|
+
self.left_motor.forward()
|
|
31
|
+
self.right_motor.stop()
|
|
@@ -92,18 +92,21 @@
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
function call_method_handler(retval) {
|
|
95
|
-
|
|
95
|
+
if (retval != '') {
|
|
96
|
+
console.log(retval);
|
|
97
|
+
alert(retval);
|
|
98
|
+
}
|
|
96
99
|
}
|
|
97
100
|
|
|
98
101
|
function call_method(stack) {
|
|
99
|
-
var elems = document.getElementsByClassName("py_" + stack)
|
|
100
|
-
url = new URL(location.href + '/call_method/' + stack)
|
|
102
|
+
var elems = document.getElementsByClassName("py_" + stack);
|
|
103
|
+
url = new URL(location.href + '/call_method/' + stack);
|
|
101
104
|
|
|
102
105
|
for (var e of elems) {
|
|
103
106
|
url.searchParams.append(e.id.split('|')[1], e.value);
|
|
104
107
|
}
|
|
105
|
-
|
|
106
|
-
get_request_async(url, call_method_handler)
|
|
108
|
+
console.log("Calling " + url);
|
|
109
|
+
get_request_async(url, call_method_handler);
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
function update_vars(json) {
|
|
@@ -116,10 +119,10 @@
|
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
function update_vars_async() {
|
|
119
|
-
get_request_async(location.href + '/get_attributes', update_vars)
|
|
122
|
+
get_request_async(location.href + '/get_attributes', update_vars);
|
|
120
123
|
}
|
|
121
124
|
|
|
122
|
-
setInterval(update_vars_async, 500)
|
|
125
|
+
setInterval(update_vars_async, 500);
|
|
123
126
|
update_vars_async();
|
|
124
127
|
</script>
|
|
125
128
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: PyObjectInterface
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Create a web interface to interact with a class
|
|
5
|
+
Home-page: https://github.com/RobertJN64/PyObjectInterface
|
|
6
|
+
Author: Robert Nies
|
|
7
|
+
Author-email: robertjnies@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: typing-extensions
|
|
21
|
+
Requires-Dist: flask
|
|
22
|
+
|
|
23
|
+
# PyObjectInterface
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+

|
|
27
|
+

|
|
28
|
+
|
|
29
|
+
Quickly control any python object through an async web interface.
|
|
30
|
+
|
|
31
|
+
`pip install PyObjectInterface`
|
|
32
|
+
```python
|
|
33
|
+
from PyObjectInterface.WebController import create_WebController
|
|
34
|
+
import flask
|
|
35
|
+
|
|
36
|
+
app = flask.Flask('Demo')
|
|
37
|
+
any_python_object = ...
|
|
38
|
+
create_WebController(any_python_object, 'any_python_object', app)
|
|
39
|
+
app.run()
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Go to `http://127.0.0.1:5000/webcontroller`
|
|
43
|
+
|
|
44
|
+
## Example: Async Robot Control
|
|
45
|
+

|
|
46
|
+
|
|
47
|
+
The above interface was automatically created from:
|
|
48
|
+
```python
|
|
49
|
+
class DriveMotor:
|
|
50
|
+
def __init__(self, pin):
|
|
51
|
+
self.pin = pin
|
|
52
|
+
self.speed = 0
|
|
53
|
+
|
|
54
|
+
def forward(self): ...
|
|
55
|
+
def stop(self): ...
|
|
56
|
+
|
|
57
|
+
class Robot:
|
|
58
|
+
def __init__(self):
|
|
59
|
+
self.left_motor = DriveMotor(1)
|
|
60
|
+
self.right_motor = DriveMotor(2)
|
|
61
|
+
|
|
62
|
+
def forward(self): ...
|
|
63
|
+
def stop(self): ...
|
|
64
|
+
def left(self): ...
|
|
65
|
+
def right(self): ...
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Look at [PyObjectInterface/examples/example.py](PyObjectInterface/examples/example.py) for more information.
|
|
69
|
+
|
|
70
|
+
## Advanced Usage and Settings
|
|
71
|
+
|
|
72
|
+
You can use PyObjectInterface without the WebController.
|
|
73
|
+
|
|
74
|
+
### create_WebController
|
|
75
|
+
- `obj`: Any python object
|
|
76
|
+
- `name: str`: Friendly name for object, generally the name of the variable that refers to the object
|
|
77
|
+
- `flask_app`: return value of flask.Flask()
|
|
78
|
+
- `recursion_depth = 5`: maximum layers of subobjects to include
|
|
79
|
+
- `create_private_interface = True`: if `True` creates a `/webcontroller/private` page that includes private methods and attributes
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
PyObjectInterface/WebController.py,sha256=YMQSaugLIKEwDxHkPTGjD4zAuIjk4X0ANf_UxtbSAbU,3820
|
|
2
|
+
PyObjectInterface/__init__.py,sha256=4524Z5al5Bwx4EsmPW7UldGaexNUMGCv0cldb3uobuQ,3674
|
|
3
|
+
PyObjectInterface/web_controller.tpl.html,sha256=KiNOmUGwsyAmkV9yol2X15G6uoAPjf2JHa6tnoCe_kw,2432
|
|
4
|
+
PyObjectInterface/examples/example.py,sha256=QhAcJJnh6LU923TL7MHwYU5keur1hgfn7Elt5nh8c-E,196
|
|
5
|
+
PyObjectInterface/examples/robot.py,sha256=qvDhIwvCtseA0AlEdZbR7RJkpbOMMw0F1C3UWNMs--M,655
|
|
6
|
+
PyObjectInterface-0.1.0.dist-info/LICENSE,sha256=_UXYaTVmtWrJCpKEgCz66EUsoFfLfn0CY4mEmuI5_zA,1054
|
|
7
|
+
PyObjectInterface-0.1.0.dist-info/METADATA,sha256=qtK66t-YQGBfpofNpMDFhVWuMxhujmu64YFVYlRH7PY,2559
|
|
8
|
+
PyObjectInterface-0.1.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
9
|
+
PyObjectInterface-0.1.0.dist-info/top_level.txt,sha256=5kOSl8l5D5IGWoWz9nkn_lQispA3D8qyPM9SvIC4LSU,18
|
|
10
|
+
PyObjectInterface-0.1.0.dist-info/RECORD,,
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: PyObjectInterface
|
|
3
|
-
Version: 0.0.2
|
|
4
|
-
Summary: Create a web interface to interact with a class
|
|
5
|
-
Home-page: https://github.com/RobertJN64/PyObjectInterface
|
|
6
|
-
Author: Robert Nies
|
|
7
|
-
Author-email: robertjnies@gmail.com
|
|
8
|
-
License: MIT
|
|
9
|
-
Classifier: Programming Language :: Python
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
-
Requires-Python: >=3.8
|
|
18
|
-
Description-Content-Type: text/markdown
|
|
19
|
-
License-File: LICENSE
|
|
20
|
-
Requires-Dist: typing-extensions
|
|
21
|
-
Requires-Dist: flask
|
|
22
|
-
|
|
23
|
-
# PyObjectInterface
|
|
24
|
-
|
|
25
|
-

|
|
26
|
-

|
|
27
|
-

|
|
28
|
-
|
|
29
|
-
`#TODO - good desc`
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
PyObjectInterface/WebController.py,sha256=_7J3iHyEvG4sttKYkr1w9pGcLDk8PI15MM7IGCWXeDA,3154
|
|
2
|
-
PyObjectInterface/__init__.py,sha256=4524Z5al5Bwx4EsmPW7UldGaexNUMGCv0cldb3uobuQ,3674
|
|
3
|
-
PyObjectInterface/web_controller.tpl.html,sha256=hc77J32kMO3S9EQ3VofI9bCO_0m8yCavROxWc1MmHmw,2361
|
|
4
|
-
PyObjectInterface-0.0.2.dist-info/LICENSE,sha256=_UXYaTVmtWrJCpKEgCz66EUsoFfLfn0CY4mEmuI5_zA,1054
|
|
5
|
-
PyObjectInterface-0.0.2.dist-info/METADATA,sha256=lyl0iU6MlOqCHNjuAHgwv973_ucVFa3KvgeB98ERCA8,1097
|
|
6
|
-
PyObjectInterface-0.0.2.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
|
|
7
|
-
PyObjectInterface-0.0.2.dist-info/top_level.txt,sha256=5kOSl8l5D5IGWoWz9nkn_lQispA3D8qyPM9SvIC4LSU,18
|
|
8
|
-
PyObjectInterface-0.0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|