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.
@@ -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: int(arg) for argname, arg in flask.request.args.items()} #TODO - better kwarg handling
61
- retval = poi.call_method(stack, kwargs)
62
- if retval is None:
63
- return "OK"
64
- else:
65
- return retval
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,8 @@
1
+ from PyObjectInterface.WebController import create_WebController
2
+ from robot import Robot
3
+ import flask
4
+
5
+ app = flask.Flask('Demo')
6
+ robot = Robot()
7
+ create_WebController(robot, 'robot', app)
8
+ app.run()
@@ -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
- console.log(retval) //#TODO - handle this
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
+ ![Tests Badge](https://github.com/RobertJN64/PyObjectInterface/actions/workflows/tests.yml/badge.svg)
26
+ ![Python Version Badge](https://img.shields.io/pypi/pyversions/PyObjectInterface)
27
+ ![License Badge](https://img.shields.io/github/license/RobertJN64/PyObjectInterface)
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
+ ![async_robot_control.png](async_robot_control.png)
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,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.3)
2
+ Generator: bdist_wheel (0.42.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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
- ![Tests Badge](https://github.com/RobertJN64/PyObjectInterface/actions/workflows/tests.yml/badge.svg)
26
- ![Python Version Badge](https://img.shields.io/pypi/pyversions/PyObjectInterface)
27
- ![License Badge](https://img.shields.io/github/license/RobertJN64/PyObjectInterface)
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,,