vuer 0.0.3__py3-none-any.whl → 0.0.5__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.

Potentially problematic release.


This version of vuer might be problematic. Click here for more details.

vuer/schemas.py CHANGED
@@ -3,6 +3,8 @@ from typing import Union
3
3
  import numpy as np
4
4
  import PIL.Image as pil_image
5
5
 
6
+ # from msgpack_numpy import pack, packb
7
+
6
8
  element_count = 0
7
9
 
8
10
 
@@ -31,7 +33,16 @@ class Element:
31
33
  :return: Dictionary representing the element.
32
34
  """
33
35
  # note: only return the non-private attributes, allow bypass.
34
- return {k: v for k, v in self.__dict__.items() if not k.startswith("_")}
36
+ output = {}
37
+ for k, v in self.__dict__.items():
38
+ if k.startswith('_'):
39
+ continue
40
+ if hasattr(v, "tolist"):
41
+ output[k] = v.tolist()
42
+ else:
43
+ output[k] = v
44
+
45
+ return output
35
46
 
36
47
 
37
48
  class BlockElement(Element):
@@ -40,7 +51,22 @@ class BlockElement(Element):
40
51
  super().__init__(**kwargs)
41
52
 
42
53
  def serialize(self):
43
- return {**super().serialize(), "children": [e.serialize() for e in self.children]}
54
+ # writ this as multiple lines
55
+ children = []
56
+ for e in self.children:
57
+ if isinstance(e, str):
58
+ children.append(e)
59
+ else:
60
+ children.append(e.serialize())
61
+ return {**super().serialize(), "children": children}
62
+
63
+
64
+ class AutoScroll(BlockElement):
65
+ tag = "AutoScroll"
66
+
67
+
68
+ class Markdown(BlockElement):
69
+ tag = "Markdown"
44
70
 
45
71
 
46
72
  class Page(BlockElement):
@@ -53,7 +79,7 @@ class Page(BlockElement):
53
79
 
54
80
 
55
81
  class div(BlockElement):
56
- tag = "div"
82
+ tag = "Div"
57
83
 
58
84
 
59
85
  class InputBox(Element):
@@ -122,6 +148,27 @@ class Text(Element):
122
148
  super().__init__(**kwargs)
123
149
 
124
150
 
151
+ class Bold(Text):
152
+ def __init__(self, text, style=None, **kwargs):
153
+ _style = {"fontWeight": "bold"}
154
+ _style.update(style or {})
155
+ super().__init__(text, style=_style, **kwargs)
156
+
157
+
158
+ class Italic(Text):
159
+ def __init__(self, text, style=None, **kwargs):
160
+ _style = {"fontStyle": "italic"}
161
+ _style.update(style or {})
162
+ super().__init__(text, style=_style, **kwargs)
163
+
164
+
165
+ class Link(Text):
166
+ tag = "a"
167
+
168
+ def __init__(self, text, src, **kwargs):
169
+ super().__init__(text, src=src, **kwargs)
170
+
171
+
125
172
  class Button(Element):
126
173
  """
127
174
  A Button element is an element that allows the user to click on it.
@@ -211,12 +258,12 @@ class Scene(BlockElement):
211
258
  tag = "Scene"
212
259
 
213
260
  def __init__(
214
- self,
215
- *children,
216
- rawChildren=None,
217
- htmlChildren=None,
218
- backgroundChildren=None,
219
- **kwargs,
261
+ self,
262
+ *children,
263
+ rawChildren=None,
264
+ htmlChildren=None,
265
+ backgroundChildren=None,
266
+ **kwargs,
220
267
  ):
221
268
  super().__init__(*children, **kwargs)
222
269
  self.rawChildren = rawChildren or []
@@ -224,13 +271,29 @@ class Scene(BlockElement):
224
271
  self.backgroundChildren = backgroundChildren or []
225
272
 
226
273
  def serialize(self):
227
- return {
228
- **super().serialize(),
229
- "children": [e.serialize() for e in self.children],
230
- "rawChildren": [e.serialize() for e in self.rawChildren],
231
- "htmlChildren": [e.serialize() for e in self.htmlChildren],
232
- "backgroundChildren": [e.serialize() for e in self.backgroundChildren],
233
- }
274
+ obj = super().serialize()
275
+ if self.rawChildren:
276
+ obj["rawChildren"] = [e.serialize() for e in self.rawChildren if e]
277
+ if self.htmlChildren:
278
+ obj["htmlChildren"] = [e.serialize() for e in self.htmlChildren if e]
279
+ if self.backgroundChildren:
280
+ obj["backgroundChildren"] = [e.serialize() for e in self.backgroundChildren if e]
281
+ return obj
282
+
283
+
284
+ class DefaultScene(Scene):
285
+ def __init__(
286
+ self,
287
+ *children,
288
+ rawChildren=None,
289
+ htmlChildren=None,
290
+ backgroundChildren=None,
291
+ **kwargs,
292
+ ):
293
+ super().__init__(
294
+ AmbientLight(intensity=0.5, key="default_ambient_light"),
295
+ DirectionalLight(intensity=1, key="default_directional_light"),
296
+ *children, **kwargs)
234
297
 
235
298
 
236
299
  class SceneElement(BlockElement):
@@ -250,6 +313,46 @@ class group(SceneElement):
250
313
  children = []
251
314
 
252
315
 
316
+ class mesh(SceneElement):
317
+ tag = "mesh"
318
+ children = []
319
+
320
+
321
+ class TriMesh(SceneElement):
322
+ tag = "TriMesh"
323
+ children = []
324
+ vertices = None
325
+ faces = None
326
+ colors = None
327
+
328
+ def __post_init__(self, **kwargs):
329
+ self.vertices = self.vertices.flatten()
330
+ if hasattr(self.faces, "flatten"):
331
+ self.faces = self.faces.flatten()
332
+ if hasattr(self.colors, "flatten"):
333
+ if self.colors.shape[-1] == 4:
334
+ self.colors = self.colors[:, :3]
335
+ if self.colors.dtype == np.uint8:
336
+ self.colors = self.colors.astype(np.float32) / 255.
337
+ self.colors = self.colors.flatten().astype(np.float32)
338
+
339
+
340
+ class PointCloud(SceneElement):
341
+ tag = "PointCloud"
342
+ children = []
343
+ vertices = None
344
+ colors = None
345
+
346
+ def __post_init__(self, **kwargs):
347
+ self.vertices = self.vertices.flatten()
348
+ if hasattr(self.colors, "flatten"):
349
+ if self.colors.shape[-1] == 4:
350
+ self.colors = self.colors[:, :3]
351
+ if self.colors.dtype == np.uint8:
352
+ self.colors = self.colors.astype(np.float32) / 255.
353
+ self.colors = self.colors.flatten()
354
+
355
+
253
356
  class Box(SceneElement):
254
357
  tag = "Box"
255
358
 
@@ -385,10 +488,6 @@ class Html(SceneElement):
385
488
  tag = "Html"
386
489
 
387
490
 
388
- class Ply(SceneElement):
389
- tag = "Ply"
390
-
391
-
392
491
  class Pivot(SceneElement):
393
492
  tag = "Pivot"
394
493
 
@@ -397,6 +496,14 @@ class Movable(SceneElement):
397
496
  tag = "Movable"
398
497
 
399
498
 
499
+ class Obj(SceneElement):
500
+ tag = "Obj"
501
+
502
+
503
+ class Ply(SceneElement):
504
+ tag = "Ply"
505
+
506
+
400
507
  class Glb(SceneElement):
401
508
  tag = "Glb"
402
509
 
@@ -405,10 +512,6 @@ class Urdf(SceneElement):
405
512
  tag = "Urdf"
406
513
 
407
514
 
408
- class PointCloud(SceneElement):
409
- tag = "PointCloud"
410
-
411
-
412
515
  class Gripper(SceneElement):
413
516
  tag = "Gripper"
414
517
 
vuer/serdes.py ADDED
@@ -0,0 +1,20 @@
1
+ from typing import Sequence
2
+
3
+
4
+ def serializer(data):
5
+ if hasattr(data, "serialize"):
6
+ return data.serialize()
7
+
8
+ if isinstance(data, str):
9
+ # return Text(data)
10
+ return data
11
+
12
+ # this could be dangerous.
13
+ if isinstance(data, Sequence):
14
+ return [serializer(d) for d in data]
15
+
16
+ # this could be dangerous
17
+ if isinstance(data, dict):
18
+ return {k: serializer(v) for k, v in data.items()}
19
+
20
+ NotImplementedError(f"Cannot serialize {data}")
vuer/server.py CHANGED
@@ -1,3 +1,4 @@
1
+ import asyncio
1
2
  import json
2
3
  from asyncio import sleep
3
4
  from collections import deque, defaultdict
@@ -5,6 +6,7 @@ from functools import partial
5
6
  from typing import cast
6
7
  from uuid import uuid4
7
8
 
9
+ from msgpack import packb
8
10
  from params_proto import Proto, PrefixProto
9
11
  from websockets import ConnectionClosedError
10
12
 
@@ -29,14 +31,16 @@ class Vuer(PrefixProto, Server):
29
31
  name = "vuer"
30
32
  uri = "ws://localhost:8012"
31
33
  # change to vuer.dash.ml
32
- domain = "https://dash.ml/demos/vqn-dash/three"
34
+ domain = "https://dash.ml/vuer"
33
35
  port = 8012
34
36
  free_port = True
35
37
  static_root = "."
36
38
  queue_len = None
37
- cors_origin = "https://dash.ml,*"
39
+ # cors = "https://dash.ml,http://localhost:8000,http://127.0.0.1:8000,*"
38
40
  queries = Proto({}, help="query parameters to pass")
39
41
 
42
+ WEBSOCKET_MAX_SIZE = 2 ** 28
43
+
40
44
  device = "cuda"
41
45
 
42
46
  # need to be awaited
@@ -109,6 +113,10 @@ class Vuer(PrefixProto, Server):
109
113
  def stream(self):
110
114
  yield from self.downlink_queue
111
115
 
116
+ def spawn_task(self, task):
117
+ loop = asyncio.get_running_loop()
118
+ return loop.create_task(task)
119
+
112
120
  def spawn(self, fn=None, start=False):
113
121
  """
114
122
  Spawn a function as a task. This is useful in the following scenario:
@@ -164,9 +172,11 @@ class Vuer(PrefixProto, Server):
164
172
  async def send(self, ws_id, event: ServerEvent):
165
173
  ws = self.ws[ws_id]
166
174
  assert isinstance(event, ServerEvent), "event must be a ServerEvent type object."
167
- res_str = event.serialize()
168
- res_json_str = json.dumps(res_str)
169
- return await ws.send_str(res_json_str)
175
+ res_obj = event.serialize()
176
+ res_bytes = packb(res_obj, use_bin_type=True)
177
+ return await ws.send_bytes(res_bytes)
178
+ # res_json_str = json.dumps(res_str)
179
+ # return await ws.send_str(res_json_str)
170
180
 
171
181
  async def close_ws(self, ws_id):
172
182
  self.uplink_queue.pop(ws_id)
@@ -265,6 +275,15 @@ class Vuer(PrefixProto, Server):
265
275
  print("websocket is now disconnected. Removing the socket.")
266
276
  self.ws.pop(ws_id, None)
267
277
 
278
+ def add_handler(self, event_type, fn):
279
+ handler_id = uuid4()
280
+ self.handlers[event_type][handler_id] = fn
281
+
282
+ def cleanup():
283
+ del self.handlers[event_type][handler_id]
284
+
285
+ return cleanup
286
+
268
287
  def run(self, kill=None, *args, **kwargs):
269
288
  print("Vuer running at: " + self.get_url())
270
289
 
@@ -281,8 +300,9 @@ class Vuer(PrefixProto, Server):
281
300
  # host = host[2:]
282
301
 
283
302
  self._socket("", self.downlink)
284
- # serve local files via /local endpoint
285
- self._static("/local", self.static_root)
303
+ # serve local files via /static endpoint
304
+ self._static("/static", self.static_root)
305
+ print("serving static files from", self.static_root, "at", "/static")
286
306
  self._route("/relay", self.relay, method="POST")
287
307
  # self._socket()
288
308
  super().run()
vuer/types.py CHANGED
@@ -5,8 +5,6 @@ from math import pi
5
5
  Vector3 = namedtuple("Vector3", ["x", "y", "z"])
6
6
 
7
7
 
8
- # Euler = namedtuple("Euler", ["x", "y", "z", "order"])
9
- # refactor with default values for "order"
10
8
  class Euler(NamedTuple):
11
9
  x: int
12
10
  y: int
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vuer
3
- Version: 0.0.3
3
+ Version: 0.0.5
4
4
  Home-page: https://github.com/geyang/vuer
5
5
  Author: Ge Yang<ge.ike.yang@gmail.com>
6
6
  Author-email: ge.ike.yang@gmail.com
@@ -13,10 +13,12 @@ License-File: LICENSE
13
13
  Requires-Dist: tqdm
14
14
  Requires-Dist: termcolor
15
15
  Requires-Dist: params-proto
16
+ Requires-Dist: killport
17
+ Requires-Dist: msgpack
16
18
  Provides-Extra: dev
17
- Requires-Dist: black (==22.3.0) ; extra == 'dev'
18
- Requires-Dist: pylint (==2.13.4) ; extra == 'dev'
19
- Requires-Dist: pytest (==7.1.2) ; extra == 'dev'
19
+ Requires-Dist: black ==22.3.0 ; extra == 'dev'
20
+ Requires-Dist: pylint ==2.13.4 ; extra == 'dev'
21
+ Requires-Dist: pytest ==7.1.2 ; extra == 'dev'
20
22
 
21
23
  # Vuer: A modern 3D Visualizer for Robotics and VR
22
24
 
@@ -0,0 +1,22 @@
1
+ vuer/__init__.py,sha256=x2ZqgbBIDHQr7UvdkKhVdtYToIZdhXw4XTRnfrQiBos,28
2
+ vuer/base.py,sha256=LHGqz_067HTWDuL2JLuC_W25rKikBdrT4unF5nUi3tY,3035
3
+ vuer/events.py,sha256=5gyYXz0XZVAMU2xyKYJmpkhIWoGGSgcrUFy8h37AoM8,3676
4
+ vuer/schemas.py,sha256=LWY79JiN3Iwf_O8xv94LBAA8drwGjMVCC9v1Cr9byhI,12245
5
+ vuer/serdes.py,sha256=dlnLcISXoXv7X6lk6DKYUksQSX3wjQ8YFa4FUZel6Ds,484
6
+ vuer/server.py,sha256=ynXs4euJrLvdjsopDhZcs0QdMwTNh3Farl5PbcvZKsM,9234
7
+ vuer/types.py,sha256=4jVXsuLjaQwmnCrK9j9G6vSVbmb8cq72WhptZg3qOuU,681
8
+ vuer/addons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ vuer/addons/nerf_vuer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ vuer/addons/nerf_vuer/control_components.py,sha256=K4PU0nD572L4J7lLFfShWficWZQnH4t-x6WWMrAVw8g,290
11
+ vuer/addons/nerf_vuer/mixins.py,sha256=fQuW3adf6X2xw_PSfS145TNfbQ9OoTKuv8mYEo6Pt6A,12966
12
+ vuer/addons/nerf_vuer/nerf_vuer.py,sha256=0iIbrQK939wwlkJOIfdOIswRKTXOKh-0TpNM5NU2ESw,5196
13
+ vuer/addons/nerf_vuer/render_components.py,sha256=KbClUsbKUWweUXZzh1SMlJS1wilj-VaQOQHVShircaw,3854
14
+ vuer/addons/nerf_vuer/render_nodes.py,sha256=5TKqIbMPiOtBxfF4FQI6uB0w_9FTfGiwS8xRbhPa0_g,14441
15
+ vuer/addons/nerfuer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ vuer/addons/nerfuer/render_nodes.py,sha256=ekrF93o3Q5cE2GKoYYvt7l7Nva_i8r6AFw29xHzx0wA,4478
17
+ vuer-0.0.5.dist-info/LICENSE,sha256=MGF-inVBUaGe2mEjqT0g6XsHIXwoNXgNHqD7Z1MzR0k,1063
18
+ vuer-0.0.5.dist-info/METADATA,sha256=UqgVZUQ4uVYVAnlB-AIr6nBHV9XUARkaZKEW1oOCVc4,805
19
+ vuer-0.0.5.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
20
+ vuer-0.0.5.dist-info/entry_points.txt,sha256=J_NM6fbpipmD9oP7cdxd1UyBR8mVEQVx0xjlE_56yss,41
21
+ vuer-0.0.5.dist-info/top_level.txt,sha256=ermmVkwvGFAK4gfSgDIwOmKpxwpqNt-oo7gVQQUSHok,5
22
+ vuer-0.0.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.38.4)
2
+ Generator: bdist_wheel (0.41.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,21 +0,0 @@
1
- vuer/__init__.py,sha256=x2ZqgbBIDHQr7UvdkKhVdtYToIZdhXw4XTRnfrQiBos,28
2
- vuer/base.py,sha256=dR_EjvWS2lIBK2DNSlKYHh5Xj8Sv1aRFB1a285PXRLc,2963
3
- vuer/events.py,sha256=pJIdD5F-SqXJ_maowRiDgssnbRgP23dEsOKfXSxVE2o,4126
4
- vuer/schemas.py,sha256=5ie8t-yogjOicgMDJwvNn4lKmIADAbjiVXt6LpiPglM,9510
5
- vuer/server.py,sha256=mSmQXezngT0gzN7_70nPGfrXMGlXuvilX6AqH5vhnIQ,8613
6
- vuer/types.py,sha256=kaGXK2rB_wVgVp3iBKXyAUE5lJT7XTWODLo5_z25SW4,780
7
- vuer/addons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- vuer/addons/nerf_vuer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- vuer/addons/nerf_vuer/control_components.py,sha256=K4PU0nD572L4J7lLFfShWficWZQnH4t-x6WWMrAVw8g,290
10
- vuer/addons/nerf_vuer/mixins.py,sha256=sugZrJ2W__cDEX8aeORK0Ylf3SrlerTHrB7ZY1m_KlY,11226
11
- vuer/addons/nerf_vuer/nerf_vuer.py,sha256=jsG2E_sooUcfPSMUB2-VUA7agA_6-iiWdCmAJpQ2ZCU,4512
12
- vuer/addons/nerf_vuer/render_components.py,sha256=F6xlqfZWGghXmedWb4XhR1M_DLG9hVrtNoGSnRV-gyg,3865
13
- vuer/addons/nerf_vuer/render_nodes.py,sha256=ekrF93o3Q5cE2GKoYYvt7l7Nva_i8r6AFw29xHzx0wA,4478
14
- vuer/addons/nerfuer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- vuer/addons/nerfuer/render_nodes.py,sha256=ekrF93o3Q5cE2GKoYYvt7l7Nva_i8r6AFw29xHzx0wA,4478
16
- vuer-0.0.3.dist-info/LICENSE,sha256=MGF-inVBUaGe2mEjqT0g6XsHIXwoNXgNHqD7Z1MzR0k,1063
17
- vuer-0.0.3.dist-info/METADATA,sha256=nV0OW1UiJSMNEhwSXydMMQiuDcFLCEyY8arX68Y-D-I,764
18
- vuer-0.0.3.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
19
- vuer-0.0.3.dist-info/entry_points.txt,sha256=J_NM6fbpipmD9oP7cdxd1UyBR8mVEQVx0xjlE_56yss,41
20
- vuer-0.0.3.dist-info/top_level.txt,sha256=ermmVkwvGFAK4gfSgDIwOmKpxwpqNt-oo7gVQQUSHok,5
21
- vuer-0.0.3.dist-info/RECORD,,
File without changes