outleap 0.6.2__tar.gz → 0.7.1__tar.gz
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.
- {outleap-0.6.2 → outleap-0.7.1}/PKG-INFO +3 -2
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/api_wrappers.py +199 -61
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/client.py +3 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/version.py +2 -2
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap.egg-info/PKG-INFO +3 -2
- {outleap-0.6.2 → outleap-0.7.1}/.coveragerc +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/.github/workflows/cis.yml +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/.github/workflows/pypi_publish.yml +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/.gitignore +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/COPYING +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/MANIFEST.in +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/README.md +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/codecov.yml +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/examples/README.md +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/examples/complex_leap_script.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/examples/simple_leap_script.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/pyproject.toml +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/setup.cfg +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/setup.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/__init__.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/bridge.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/protocol.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/qt_helpers.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/scripts/__init__.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/scripts/agent.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/scripts/inspector.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/scripts/repl.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/scripts/ui/inspector.ui +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/ui_elems.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap/utils.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap.egg-info/SOURCES.txt +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap.egg-info/dependency_links.txt +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap.egg-info/entry_points.txt +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap.egg-info/requires.txt +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/src/outleap.egg-info/top_level.txt +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/static/inspector_screenshot.png +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/tests/__init__.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/tests/test_client.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/tests/test_protocol.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/tests/test_stdio.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/tests/test_ui_elems.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/tests/test_wrappers.py +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/tests/ui_paths.txt +0 -0
- {outleap-0.6.2 → outleap-0.7.1}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: outleap
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Tools for using asyncio to control a Second Life viewer over the LEAP protocol
|
|
5
5
|
Author-email: Salad Dais <83434023+SaladDais@users.noreply.github.com>
|
|
6
6
|
License: MIT License
|
|
@@ -26,6 +26,7 @@ Provides-Extra: tools
|
|
|
26
26
|
Requires-Dist: ptpython<4,>=3; extra == "tools"
|
|
27
27
|
Requires-Dist: qasync; extra == "tools"
|
|
28
28
|
Requires-Dist: pyside6-essentials; extra == "tools"
|
|
29
|
+
Dynamic: license-file
|
|
29
30
|
|
|
30
31
|
# outleap
|
|
31
32
|
|
|
@@ -97,11 +97,11 @@ class LLWindowAPI(LEAPAPIWrapper):
|
|
|
97
97
|
path: UI_PATH_TYPE,
|
|
98
98
|
) -> Dict:
|
|
99
99
|
if keycode is not None:
|
|
100
|
-
payload = {"keycode": keycode}
|
|
100
|
+
payload: Dict = {"keycode": keycode}
|
|
101
101
|
elif keysym is not None:
|
|
102
|
-
payload = {"keysym": keysym}
|
|
102
|
+
payload: Dict = {"keysym": keysym}
|
|
103
103
|
elif char is not None:
|
|
104
|
-
payload = {"char": char}
|
|
104
|
+
payload: Dict = {"char": char}
|
|
105
105
|
else:
|
|
106
106
|
raise ValueError("Didn't have one of keycode, keysym or char")
|
|
107
107
|
|
|
@@ -163,9 +163,7 @@ class LLWindowAPI(LEAPAPIWrapper):
|
|
|
163
163
|
|
|
164
164
|
async def get_paths(self, under: Optional[UI_PATH_TYPE] = None) -> List[UIPath]:
|
|
165
165
|
"""Get all UI paths under the root, or under a path if specified"""
|
|
166
|
-
|
|
167
|
-
under = ""
|
|
168
|
-
resp = await self._client.command(self._pump_name, "getPaths", {"under": str(under)})
|
|
166
|
+
resp = await self._client.command(self._pump_name, "getPaths", {"under": str(under or "")})
|
|
169
167
|
if error := resp.get("error"):
|
|
170
168
|
raise ValueError(error)
|
|
171
169
|
return [UIPath(path) for path in resp.get("paths", [])]
|
|
@@ -185,9 +183,9 @@ class LLWindowAPI(LEAPAPIWrapper):
|
|
|
185
183
|
button: str = None,
|
|
186
184
|
) -> Dict:
|
|
187
185
|
if path is not None:
|
|
188
|
-
payload = {"path": str(path)}
|
|
186
|
+
payload: Dict = {"path": str(path)}
|
|
189
187
|
elif x is not None and y is not None:
|
|
190
|
-
payload = {"x": x, "y": y}
|
|
188
|
+
payload: Dict = {"x": x, "y": y}
|
|
191
189
|
else:
|
|
192
190
|
raise ValueError("Didn't have one of x + y or path")
|
|
193
191
|
|
|
@@ -381,7 +379,7 @@ class LLAgentAPI(LEAPAPIWrapper):
|
|
|
381
379
|
lookat_type: int = 8,
|
|
382
380
|
):
|
|
383
381
|
"""Look at either a specific `obj_uuid` or the closest object to `position`"""
|
|
384
|
-
payload = {"type": lookat_type}
|
|
382
|
+
payload: Dict = {"type": lookat_type}
|
|
385
383
|
if obj_uuid:
|
|
386
384
|
payload["obj_uuid"] = obj_uuid
|
|
387
385
|
elif position:
|
|
@@ -391,9 +389,124 @@ class LLAgentAPI(LEAPAPIWrapper):
|
|
|
391
389
|
self._client.void_command(self._pump_name, "lookAt", payload)
|
|
392
390
|
|
|
393
391
|
def get_auto_pilot(self) -> Awaitable[Dict]:
|
|
394
|
-
"""Get information about current state of the autopilot system"""
|
|
392
|
+
"""Get information about the current state of the autopilot system"""
|
|
395
393
|
return self._client.command(self._pump_name, "getAutoPilot", {})
|
|
396
394
|
|
|
395
|
+
def get_agent_screen_pos(self, avatar_id: Optional[uuid.UUID] = None) -> Awaitable[Dict]:
|
|
396
|
+
"""Get where the specified agent is on the screen, uses current agent's ID if none provided"""
|
|
397
|
+
payload = {}
|
|
398
|
+
if avatar_id:
|
|
399
|
+
payload["avatar_id"] = avatar_id
|
|
400
|
+
return self._client.command(self._pump_name, "getAgentScreenPos", payload)
|
|
401
|
+
|
|
402
|
+
def get_nearby_avatars(self, dist: Optional[float] = None) -> Awaitable[List[Dict]]:
|
|
403
|
+
payload = {}
|
|
404
|
+
if dist is not None:
|
|
405
|
+
payload["dist"] = dist
|
|
406
|
+
fut = self._client.command(self._pump_name, "getNearbyAvatarsList", payload)
|
|
407
|
+
return _data_unwrapper(fut, "result")
|
|
408
|
+
|
|
409
|
+
def get_nearby_objects(self, dist: Optional[float] = None) -> Awaitable[List[Dict]]:
|
|
410
|
+
payload = {}
|
|
411
|
+
if dist is not None:
|
|
412
|
+
payload["dist"] = dist
|
|
413
|
+
fut = self._client.command(self._pump_name, "getNearbyObjectsList", payload)
|
|
414
|
+
return _data_unwrapper(fut, "result")
|
|
415
|
+
|
|
416
|
+
def get_position(self) -> Awaitable[Dict]:
|
|
417
|
+
"""Get details about the agent's position"""
|
|
418
|
+
return self._client.command(self._pump_name, "getPosition", {})
|
|
419
|
+
|
|
420
|
+
def request_sit(
|
|
421
|
+
self,
|
|
422
|
+
obj_uuid: Optional[uuid.UUID] = None,
|
|
423
|
+
position: Optional[Sequence[float]] = None,
|
|
424
|
+
) -> Awaitable:
|
|
425
|
+
"""Request to sit on obj_id, or object closest to position. Sits on ground if no args provided"""
|
|
426
|
+
if position and obj_uuid is not None:
|
|
427
|
+
raise ValueError("obj_uuid and position are mutually exclusive")
|
|
428
|
+
|
|
429
|
+
params = {}
|
|
430
|
+
if obj_uuid:
|
|
431
|
+
params["obj_uuid"] = obj_uuid
|
|
432
|
+
if position:
|
|
433
|
+
params["position"] = list(position)
|
|
434
|
+
return self._client.command(self._pump_name, "requestSit", params)
|
|
435
|
+
|
|
436
|
+
def request_stand(self) -> None:
|
|
437
|
+
self._client.void_command(self._pump_name, "requestStand", {})
|
|
438
|
+
|
|
439
|
+
def request_teleport(
|
|
440
|
+
self,
|
|
441
|
+
region_name: Optional[str] = None,
|
|
442
|
+
x: Optional[int] = None,
|
|
443
|
+
y: Optional[int] = None,
|
|
444
|
+
z: Optional[int] = None,
|
|
445
|
+
skip_confirmation: bool = True,
|
|
446
|
+
) -> None:
|
|
447
|
+
"""Request a teleport from the system, (x,y,z) are global if region_name unspecified"""
|
|
448
|
+
have_coords = all(_ is not None for _ in (x, y, z))
|
|
449
|
+
if not region_name and not have_coords:
|
|
450
|
+
raise ValueError("region_name or (x,y,z) is required")
|
|
451
|
+
|
|
452
|
+
params: Dict = {"skip_confirmation": skip_confirmation}
|
|
453
|
+
if region_name:
|
|
454
|
+
params["regionname"] = region_name
|
|
455
|
+
if have_coords:
|
|
456
|
+
params["x"] = x
|
|
457
|
+
params["y"] = y
|
|
458
|
+
params["z"] = z
|
|
459
|
+
|
|
460
|
+
self._client.void_command(self._pump_name, "requestTeleport", params)
|
|
461
|
+
|
|
462
|
+
def get_id(self) -> Awaitable[uuid.UUID]:
|
|
463
|
+
"""Get the current agent's ID"""
|
|
464
|
+
return _data_unwrapper(self._client.command(self._pump_name, "getId", {}), "id")
|
|
465
|
+
|
|
466
|
+
def get_groups(self) -> Awaitable[List[Dict]]:
|
|
467
|
+
return _data_unwrapper(self._client.command(self._pump_name, "getGroups", {}), "groups")
|
|
468
|
+
|
|
469
|
+
def play_animation(self, item_id: uuid.UUID, inworld: bool = True) -> Awaitable:
|
|
470
|
+
"""Play an animation by item id"""
|
|
471
|
+
return self._client.command(
|
|
472
|
+
self._pump_name, "playAnimation", {"item_id": item_id, "inworld": inworld}
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
def stop_animation(self, item_id: uuid.UUID) -> Awaitable:
|
|
476
|
+
"""Stop an animation by item id"""
|
|
477
|
+
return self._client.command(self._pump_name, "stopAnimation", {"item_id": item_id})
|
|
478
|
+
|
|
479
|
+
def get_animation_info(self, item_id: uuid.UUID) -> Awaitable[Dict]:
|
|
480
|
+
"""Get information about an animation by item id"""
|
|
481
|
+
return _data_unwrapper(
|
|
482
|
+
self._client.command(self._pump_name, "getAnimationInfo", {"item_id": item_id}), "anim_info"
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
def set_camera_params(self, params: Dict) -> None:
|
|
486
|
+
"""Set camera parameters using LSL-like semantics"""
|
|
487
|
+
self._client.void_command(self._pump_name, "setCameraParams", params)
|
|
488
|
+
|
|
489
|
+
def set_follow_cam_active(self, active: bool) -> None:
|
|
490
|
+
self._client.void_command(self._pump_name, "setFollowCamActive", {"active": active})
|
|
491
|
+
|
|
492
|
+
def remove_camera_params(self) -> None:
|
|
493
|
+
self._client.void_command(self._pump_name, "removeCameraParams", {})
|
|
494
|
+
|
|
495
|
+
def request_touch(
|
|
496
|
+
self,
|
|
497
|
+
obj_uuid: Optional[uuid.UUID] = None,
|
|
498
|
+
position: Optional[Sequence[float]] = None,
|
|
499
|
+
face: int = 0,
|
|
500
|
+
) -> None:
|
|
501
|
+
if not obj_uuid and not position:
|
|
502
|
+
raise ValueError("Must specify either obj_uuid or position")
|
|
503
|
+
params: Dict = {"face": face}
|
|
504
|
+
if obj_uuid:
|
|
505
|
+
params["obj_uuid"] = obj_uuid
|
|
506
|
+
if position:
|
|
507
|
+
params["position"] = list(position)
|
|
508
|
+
self._client.void_command(self._pump_name, "requestTouch", params)
|
|
509
|
+
|
|
397
510
|
|
|
398
511
|
class LLFloaterRegAPI(LEAPAPIWrapper):
|
|
399
512
|
PUMP_NAME = "LLFloaterReg"
|
|
@@ -466,7 +579,7 @@ class LLFloaterRegAPI(LEAPAPIWrapper):
|
|
|
466
579
|
)
|
|
467
580
|
|
|
468
581
|
|
|
469
|
-
class
|
|
582
|
+
class LLURLDispatcherAPI(LEAPAPIWrapper):
|
|
470
583
|
PUMP_NAME = "LLUrlDispatcher"
|
|
471
584
|
|
|
472
585
|
def dispatch(self, url: str, trusted: bool = True):
|
|
@@ -482,7 +595,7 @@ class LLURLDispatcher(LEAPAPIWrapper):
|
|
|
482
595
|
self._client.void_command(self._pump_name, "dispatchFromTextEditor", {"url": url})
|
|
483
596
|
|
|
484
597
|
|
|
485
|
-
class
|
|
598
|
+
class LLFloaterAboutAPI(LEAPAPIWrapper):
|
|
486
599
|
PUMP_NAME = "LLFloaterAbout"
|
|
487
600
|
|
|
488
601
|
def get_info(self) -> Awaitable[dict]:
|
|
@@ -490,7 +603,7 @@ class LLFloaterAbout(LEAPAPIWrapper):
|
|
|
490
603
|
return self._client.command(self._pump_name, "getInfo")
|
|
491
604
|
|
|
492
605
|
|
|
493
|
-
class
|
|
606
|
+
class LLGestureAPI(LEAPAPIWrapper):
|
|
494
607
|
PUMP_NAME = "LLGesture"
|
|
495
608
|
|
|
496
609
|
def get_active_gestures(self) -> Awaitable[list]:
|
|
@@ -516,26 +629,25 @@ class LLGesture(LEAPAPIWrapper):
|
|
|
516
629
|
self._client.void_command(self._pump_name, "stopGesture", {"id": gesture_id})
|
|
517
630
|
|
|
518
631
|
|
|
519
|
-
class
|
|
632
|
+
class GroupChatAPI(LEAPAPIWrapper):
|
|
520
633
|
PUMP_NAME = "GroupChat"
|
|
521
634
|
|
|
522
|
-
def start_im(self, group_id: uuid.UUID) -> Awaitable
|
|
523
|
-
"""Start an IM session for the specified group
|
|
524
|
-
|
|
525
|
-
return _data_unwrapper(fut, "session_id")
|
|
635
|
+
def start_im(self, group_id: uuid.UUID) -> Awaitable:
|
|
636
|
+
"""Start an IM session for the specified group"""
|
|
637
|
+
return self._client.command(self._pump_name, "startGroupChat", {"group_id": group_id})
|
|
526
638
|
|
|
527
639
|
def end_im(self, group_id: uuid.UUID):
|
|
528
640
|
"""End an IM session with the specified group"""
|
|
529
|
-
self._client.
|
|
641
|
+
return self._client.command(self._pump_name, "leaveGroupChat", {"group_id": group_id})
|
|
530
642
|
|
|
531
|
-
def send_im(self, group_id: uuid.UUID,
|
|
532
|
-
"""Send an IM to the specified group
|
|
533
|
-
self._client.
|
|
534
|
-
self._pump_name, "
|
|
643
|
+
def send_im(self, group_id: uuid.UUID, message: str) -> Awaitable:
|
|
644
|
+
"""Send an IM to the specified group"""
|
|
645
|
+
return self._client.command(
|
|
646
|
+
self._pump_name, "sendGroupIM", {"group_id": group_id, "message": message}
|
|
535
647
|
)
|
|
536
648
|
|
|
537
649
|
|
|
538
|
-
class
|
|
650
|
+
class LLChatBarAPI(LEAPAPIWrapper):
|
|
539
651
|
PUMP_NAME = "LLChatBar"
|
|
540
652
|
|
|
541
653
|
def send_chat(self, message: str, channel: int = 0, chat_type: str = "normal"):
|
|
@@ -551,7 +663,7 @@ class LLFloaterIMNearbyChat(LEAPAPIWrapper):
|
|
|
551
663
|
)
|
|
552
664
|
|
|
553
665
|
|
|
554
|
-
class
|
|
666
|
+
class LLAppViewerAPI(LEAPAPIWrapper):
|
|
555
667
|
PUMP_NAME = "LLAppViewer"
|
|
556
668
|
|
|
557
669
|
def request_quit(self):
|
|
@@ -561,40 +673,65 @@ class LLAppViewer(LEAPAPIWrapper):
|
|
|
561
673
|
self._client.void_command(self._pump_name, "forceQuit")
|
|
562
674
|
|
|
563
675
|
|
|
564
|
-
class
|
|
565
|
-
PUMP_NAME = "
|
|
566
|
-
OP_KEY: str = "command"
|
|
676
|
+
class LLTeleportHandlerAPI(LEAPAPIWrapper):
|
|
677
|
+
PUMP_NAME = "LLTeleportHandler"
|
|
567
678
|
|
|
568
|
-
def
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
679
|
+
def teleport(
|
|
680
|
+
self,
|
|
681
|
+
region_name: Optional[str] = None,
|
|
682
|
+
x: Optional[int] = None,
|
|
683
|
+
y: Optional[int] = None,
|
|
684
|
+
z: Optional[int] = None,
|
|
685
|
+
) -> None:
|
|
686
|
+
have_coords = all(_ is not None for _ in (x, y, z))
|
|
687
|
+
if not region_name and not have_coords:
|
|
688
|
+
raise ValueError("region_name or (x,y,z) is required")
|
|
572
689
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
690
|
+
params = {}
|
|
691
|
+
if region_name:
|
|
692
|
+
params["regionname"] = region_name
|
|
693
|
+
if have_coords:
|
|
694
|
+
params["x"] = x
|
|
695
|
+
params["y"] = y
|
|
696
|
+
params["z"] = z
|
|
577
697
|
|
|
578
|
-
|
|
579
|
-
"""
|
|
580
|
-
Request skeleton data
|
|
698
|
+
self._client.void_command(self._pump_name, "teleport", params)
|
|
581
699
|
|
|
582
|
-
Response will be sent over the "puppetry.command" listener as a "set_skeleton"
|
|
583
|
-
"""
|
|
584
|
-
self._client.void_command(self._pump_name, "send_skeleton", {}, op_key=self.OP_KEY)
|
|
585
700
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
701
|
+
class LLAppearanceAPI(LEAPAPIWrapper):
|
|
702
|
+
PUMP_NAME = "LLAppearance"
|
|
703
|
+
|
|
704
|
+
def wear_outfit(
|
|
705
|
+
self,
|
|
706
|
+
folder_id: Optional[uuid.UUID] = None,
|
|
707
|
+
folder_name: Optional[str] = None,
|
|
708
|
+
append: bool = False,
|
|
709
|
+
) -> Awaitable:
|
|
710
|
+
params: Dict = {"append": append}
|
|
711
|
+
if folder_id:
|
|
712
|
+
params["folder_id"] = folder_id
|
|
713
|
+
if folder_name:
|
|
714
|
+
params["folder_name"] = folder_name
|
|
715
|
+
return self._client.command(self._pump_name, "wearOutfit", params)
|
|
716
|
+
|
|
717
|
+
def wear_items(self, item_ids: Sequence[uuid.UUID], replace: bool = False) -> None:
|
|
718
|
+
self._client.void_command(
|
|
719
|
+
self._pump_name, "wearItems", {"items_id": list(item_ids), "replace": replace}
|
|
720
|
+
)
|
|
721
|
+
|
|
722
|
+
def detach_items(self, item_ids: Sequence[uuid.UUID], replace: bool = False) -> None:
|
|
723
|
+
self._client.void_command(
|
|
724
|
+
self._pump_name, "detachItems", {"items_id": list(item_ids), "replace": replace}
|
|
725
|
+
)
|
|
726
|
+
|
|
727
|
+
def get_outfits_list(self) -> Awaitable[Dict[str, str]]:
|
|
728
|
+
return _data_unwrapper(self._client.command(self._pump_name, "getOutfitsList", {}), "outfits")
|
|
729
|
+
|
|
730
|
+
def get_outfit_items(self, outfit_id: uuid.UUID) -> Awaitable[Dict[str, dict]]:
|
|
731
|
+
return _data_unwrapper(
|
|
732
|
+
self._client.command(self._pump_name, "getOutfitItems", {"outfit_id": outfit_id}),
|
|
733
|
+
"items",
|
|
734
|
+
)
|
|
598
735
|
|
|
599
736
|
|
|
600
737
|
__all__ = [
|
|
@@ -606,12 +743,13 @@ __all__ = [
|
|
|
606
743
|
"LLViewerWindowAPI",
|
|
607
744
|
"LLCommandDispatcherAPI",
|
|
608
745
|
"LLFloaterRegAPI",
|
|
609
|
-
"
|
|
610
|
-
"
|
|
611
|
-
"
|
|
612
|
-
"
|
|
613
|
-
"
|
|
614
|
-
"
|
|
615
|
-
"
|
|
746
|
+
"LLURLDispatcherAPI",
|
|
747
|
+
"LLFloaterAboutAPI",
|
|
748
|
+
"LLGestureAPI",
|
|
749
|
+
"GroupChatAPI",
|
|
750
|
+
"LLChatBarAPI",
|
|
751
|
+
"LLAppViewerAPI",
|
|
752
|
+
"LLTeleportHandlerAPI",
|
|
753
|
+
"LLAppearanceAPI",
|
|
616
754
|
"LEAPAPIWrapper",
|
|
617
755
|
]
|
|
@@ -100,6 +100,9 @@ class LEAPClient:
|
|
|
100
100
|
self.handle_message(await self._protocol.read_message())
|
|
101
101
|
except asyncio.IncompleteReadError:
|
|
102
102
|
pass
|
|
103
|
+
except ConnectionResetError:
|
|
104
|
+
# This can happen on Windows rather than `IncompleteReadError`
|
|
105
|
+
pass
|
|
103
106
|
finally:
|
|
104
107
|
self.disconnect()
|
|
105
108
|
|
|
@@ -5,7 +5,7 @@ from collections import namedtuple
|
|
|
5
5
|
#: A namedtuple of the version info for the current release.
|
|
6
6
|
_version_info = namedtuple("_version_info", "major minor micro status")
|
|
7
7
|
|
|
8
|
-
parts = "0.
|
|
8
|
+
parts = "0.7.1".split(".", 3)
|
|
9
9
|
version_info = _version_info(
|
|
10
10
|
int(parts[0]),
|
|
11
11
|
int(parts[1]),
|
|
@@ -16,4 +16,4 @@ version_info = _version_info(
|
|
|
16
16
|
# Remove everything but the 'version_info' from this module.
|
|
17
17
|
del namedtuple, _version_info, parts
|
|
18
18
|
|
|
19
|
-
__version__ = "0.
|
|
19
|
+
__version__ = "0.7.1"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: outleap
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Tools for using asyncio to control a Second Life viewer over the LEAP protocol
|
|
5
5
|
Author-email: Salad Dais <83434023+SaladDais@users.noreply.github.com>
|
|
6
6
|
License: MIT License
|
|
@@ -26,6 +26,7 @@ Provides-Extra: tools
|
|
|
26
26
|
Requires-Dist: ptpython<4,>=3; extra == "tools"
|
|
27
27
|
Requires-Dist: qasync; extra == "tools"
|
|
28
28
|
Requires-Dist: pyside6-essentials; extra == "tools"
|
|
29
|
+
Dynamic: license-file
|
|
29
30
|
|
|
30
31
|
# outleap
|
|
31
32
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|