flcpy 0.2.6__tar.gz → 0.3.0__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.
- flcpy-0.3.0/PKG-INFO +73 -0
- flcpy-0.3.0/README.md +60 -0
- {flcpy-0.2.6 → flcpy-0.3.0}/pyproject.toml +1 -1
- {flcpy-0.2.6 → flcpy-0.3.0}/src/flcpy/flcpy.py +26 -5
- flcpy-0.3.0/src/flcpy.egg-info/PKG-INFO +73 -0
- {flcpy-0.2.6 → flcpy-0.3.0}/src/flcpy.egg-info/SOURCES.txt +2 -1
- flcpy-0.3.0/tests/test_messaging.py +74 -0
- flcpy-0.2.6/PKG-INFO +0 -32
- flcpy-0.2.6/README.md +0 -19
- flcpy-0.2.6/src/flcpy.egg-info/PKG-INFO +0 -32
- {flcpy-0.2.6 → flcpy-0.3.0}/LICENSE +0 -0
- {flcpy-0.2.6 → flcpy-0.3.0}/MANIFEST.in +0 -0
- {flcpy-0.2.6 → flcpy-0.3.0}/setup.cfg +0 -0
- {flcpy-0.2.6 → flcpy-0.3.0}/src/flcpy/__init__.py +0 -0
- {flcpy-0.2.6 → flcpy-0.3.0}/src/flcpy.egg-info/dependency_links.txt +0 -0
- {flcpy-0.2.6 → flcpy-0.3.0}/src/flcpy.egg-info/top_level.txt +0 -0
flcpy-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flcpy
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Python control interface for Flare Live / Flare Real
|
|
5
|
+
Author-email: Jiwei Wang <zmh78879@gmail.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
# Flare Python Controller (flcpy)
|
|
15
|
+
|
|
16
|
+
Python networking interface for Flare Live / Flare Real.
|
|
17
|
+
|
|
18
|
+
## Install & Upgrade
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
pip install --upgrade flcpy
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Use
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
import flcpy
|
|
28
|
+
|
|
29
|
+
s = flcpy.connect() # Connect only; does not clear simulation or recover the World.
|
|
30
|
+
obj = s.get_object(...)
|
|
31
|
+
...
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Temporary experiments
|
|
35
|
+
|
|
36
|
+
With a current Flare Live server, explicitly begin an experiment before making
|
|
37
|
+
temporary scene edits. Clear simulation before ending the experiment:
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import flcpy
|
|
41
|
+
|
|
42
|
+
s = flcpy.connect()
|
|
43
|
+
try:
|
|
44
|
+
if not s.begin_experiment():
|
|
45
|
+
raise RuntimeError("Could not begin experiment; see the Flare Live log")
|
|
46
|
+
try:
|
|
47
|
+
# Clone objects, randomize properties, etc. These edits stay temporary.
|
|
48
|
+
# s.start() initializes simulation; s.simulate(...) advances it.
|
|
49
|
+
...
|
|
50
|
+
finally:
|
|
51
|
+
s.clear() # Required if simulation was initialized.
|
|
52
|
+
s.end_experiment() # Discard temporary edits and return to the document.
|
|
53
|
+
finally:
|
|
54
|
+
s.close()
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`begin_experiment()` and `end_experiment()` return `True` on success and `False`
|
|
58
|
+
on failure; failure details appear in the Flare Live log. They do not implicitly
|
|
59
|
+
initialize or clear simulation. Without an experiment, scene edits affect the
|
|
60
|
+
Document World and participate in its undo/redo history.
|
|
61
|
+
|
|
62
|
+
`recover_world()` is retained for older Flare Live servers. Both `connect()`
|
|
63
|
+
and `Simulator()` now default to `recover_world=False`. For an older server,
|
|
64
|
+
explicitly pass `recover_world=True` to retain the previous clear-and-recover
|
|
65
|
+
behavior on connection. Modern servers reject recovery; use experiments instead.
|
|
66
|
+
|
|
67
|
+
### Tests
|
|
68
|
+
|
|
69
|
+
Run the dependency-free client contract tests from this repository:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
python -m unittest discover -s tests -v
|
|
73
|
+
```
|
flcpy-0.3.0/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Flare Python Controller (flcpy)
|
|
2
|
+
|
|
3
|
+
Python networking interface for Flare Live / Flare Real.
|
|
4
|
+
|
|
5
|
+
## Install & Upgrade
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
pip install --upgrade flcpy
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Use
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
import flcpy
|
|
15
|
+
|
|
16
|
+
s = flcpy.connect() # Connect only; does not clear simulation or recover the World.
|
|
17
|
+
obj = s.get_object(...)
|
|
18
|
+
...
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Temporary experiments
|
|
22
|
+
|
|
23
|
+
With a current Flare Live server, explicitly begin an experiment before making
|
|
24
|
+
temporary scene edits. Clear simulation before ending the experiment:
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
import flcpy
|
|
28
|
+
|
|
29
|
+
s = flcpy.connect()
|
|
30
|
+
try:
|
|
31
|
+
if not s.begin_experiment():
|
|
32
|
+
raise RuntimeError("Could not begin experiment; see the Flare Live log")
|
|
33
|
+
try:
|
|
34
|
+
# Clone objects, randomize properties, etc. These edits stay temporary.
|
|
35
|
+
# s.start() initializes simulation; s.simulate(...) advances it.
|
|
36
|
+
...
|
|
37
|
+
finally:
|
|
38
|
+
s.clear() # Required if simulation was initialized.
|
|
39
|
+
s.end_experiment() # Discard temporary edits and return to the document.
|
|
40
|
+
finally:
|
|
41
|
+
s.close()
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`begin_experiment()` and `end_experiment()` return `True` on success and `False`
|
|
45
|
+
on failure; failure details appear in the Flare Live log. They do not implicitly
|
|
46
|
+
initialize or clear simulation. Without an experiment, scene edits affect the
|
|
47
|
+
Document World and participate in its undo/redo history.
|
|
48
|
+
|
|
49
|
+
`recover_world()` is retained for older Flare Live servers. Both `connect()`
|
|
50
|
+
and `Simulator()` now default to `recover_world=False`. For an older server,
|
|
51
|
+
explicitly pass `recover_world=True` to retain the previous clear-and-recover
|
|
52
|
+
behavior on connection. Modern servers reject recovery; use experiments instead.
|
|
53
|
+
|
|
54
|
+
### Tests
|
|
55
|
+
|
|
56
|
+
Run the dependency-free client contract tests from this repository:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
python -m unittest discover -s tests -v
|
|
60
|
+
```
|
|
@@ -65,7 +65,7 @@ class MessagingClient:
|
|
|
65
65
|
self.socket.close()
|
|
66
66
|
|
|
67
67
|
class Simulator:
|
|
68
|
-
def __init__(self, host : str = 'localhost', port : int = 25556, recover_world =
|
|
68
|
+
def __init__(self, host : str = 'localhost', port : int = 25556, recover_world = False):
|
|
69
69
|
self.messaging = MessagingClient(host, port)
|
|
70
70
|
if recover_world:
|
|
71
71
|
self.clear()
|
|
@@ -300,9 +300,30 @@ class Simulator:
|
|
|
300
300
|
def set_object_property_reference(self, obj: int, property_path: str, value: int) -> bool:
|
|
301
301
|
return self.set_object_property(obj, property_path, uint_to_bytes(value))
|
|
302
302
|
|
|
303
|
-
|
|
304
|
-
|
|
303
|
+
def begin_experiment(self) -> bool:
|
|
304
|
+
"""Begin a temporary editable World without initializing simulation.
|
|
305
|
+
|
|
306
|
+
Requires no existing experiment or initialized simulation. Edits in the
|
|
307
|
+
experiment do not change the document or its undo/redo history.
|
|
308
|
+
"""
|
|
309
|
+
reply = self.messaging.request(uint_to_bytes(12) + b'\x00')
|
|
310
|
+
return reply[0:1] == b'\x00'
|
|
311
|
+
|
|
312
|
+
def end_experiment(self) -> bool:
|
|
313
|
+
"""Discard the experiment and return to the document.
|
|
314
|
+
|
|
315
|
+
Clear any initialized simulation first. Returns False on failure;
|
|
316
|
+
details are logged by Flare Live.
|
|
317
|
+
"""
|
|
318
|
+
reply = self.messaging.request(uint_to_bytes(12) + b'\x01')
|
|
319
|
+
return reply[0:1] == b'\x00'
|
|
320
|
+
|
|
305
321
|
def recover_world(self) -> bool:
|
|
322
|
+
"""Recover the initial World on older Flare Live versions only.
|
|
323
|
+
|
|
324
|
+
Kept for compatibility. Modern Flare Live rejects this request; use
|
|
325
|
+
begin_experiment()/end_experiment() for temporary edits instead.
|
|
326
|
+
"""
|
|
306
327
|
request = uint_to_bytes(8)
|
|
307
328
|
reply = self.messaging.request(request)
|
|
308
329
|
return reply[0:1] == b'\x00'
|
|
@@ -341,5 +362,5 @@ class Simulator:
|
|
|
341
362
|
self.recover_world()
|
|
342
363
|
self.messaging.close()
|
|
343
364
|
|
|
344
|
-
def connect(host : str = 'localhost', port : int = 25556, recover_world =
|
|
345
|
-
return Simulator(host, port, recover_world)
|
|
365
|
+
def connect(host : str = 'localhost', port : int = 25556, recover_world = False) -> Simulator:
|
|
366
|
+
return Simulator(host, port, recover_world)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flcpy
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Python control interface for Flare Live / Flare Real
|
|
5
|
+
Author-email: Jiwei Wang <zmh78879@gmail.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
# Flare Python Controller (flcpy)
|
|
15
|
+
|
|
16
|
+
Python networking interface for Flare Live / Flare Real.
|
|
17
|
+
|
|
18
|
+
## Install & Upgrade
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
pip install --upgrade flcpy
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Use
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
import flcpy
|
|
28
|
+
|
|
29
|
+
s = flcpy.connect() # Connect only; does not clear simulation or recover the World.
|
|
30
|
+
obj = s.get_object(...)
|
|
31
|
+
...
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Temporary experiments
|
|
35
|
+
|
|
36
|
+
With a current Flare Live server, explicitly begin an experiment before making
|
|
37
|
+
temporary scene edits. Clear simulation before ending the experiment:
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import flcpy
|
|
41
|
+
|
|
42
|
+
s = flcpy.connect()
|
|
43
|
+
try:
|
|
44
|
+
if not s.begin_experiment():
|
|
45
|
+
raise RuntimeError("Could not begin experiment; see the Flare Live log")
|
|
46
|
+
try:
|
|
47
|
+
# Clone objects, randomize properties, etc. These edits stay temporary.
|
|
48
|
+
# s.start() initializes simulation; s.simulate(...) advances it.
|
|
49
|
+
...
|
|
50
|
+
finally:
|
|
51
|
+
s.clear() # Required if simulation was initialized.
|
|
52
|
+
s.end_experiment() # Discard temporary edits and return to the document.
|
|
53
|
+
finally:
|
|
54
|
+
s.close()
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`begin_experiment()` and `end_experiment()` return `True` on success and `False`
|
|
58
|
+
on failure; failure details appear in the Flare Live log. They do not implicitly
|
|
59
|
+
initialize or clear simulation. Without an experiment, scene edits affect the
|
|
60
|
+
Document World and participate in its undo/redo history.
|
|
61
|
+
|
|
62
|
+
`recover_world()` is retained for older Flare Live servers. Both `connect()`
|
|
63
|
+
and `Simulator()` now default to `recover_world=False`. For an older server,
|
|
64
|
+
explicitly pass `recover_world=True` to retain the previous clear-and-recover
|
|
65
|
+
behavior on connection. Modern servers reject recovery; use experiments instead.
|
|
66
|
+
|
|
67
|
+
### Tests
|
|
68
|
+
|
|
69
|
+
Run the dependency-free client contract tests from this repository:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
python -m unittest discover -s tests -v
|
|
73
|
+
```
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Client wire contracts; no running simulator or third-party packages needed."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import struct
|
|
5
|
+
import sys
|
|
6
|
+
import unittest
|
|
7
|
+
from unittest.mock import patch
|
|
8
|
+
|
|
9
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
|
10
|
+
|
|
11
|
+
import flcpy
|
|
12
|
+
from flcpy.flcpy import Simulator
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MessagingCommandsTest(unittest.TestCase):
|
|
16
|
+
def setUp(self):
|
|
17
|
+
patcher = patch("flcpy.flcpy.MessagingClient")
|
|
18
|
+
self.client_class = patcher.start()
|
|
19
|
+
self.addCleanup(patcher.stop)
|
|
20
|
+
self.client = self.client_class.return_value
|
|
21
|
+
self.client.request.return_value = b"\x00"
|
|
22
|
+
|
|
23
|
+
def test_connect_defaults_to_no_world_mutation(self):
|
|
24
|
+
sim = flcpy.connect("localhost", 12345)
|
|
25
|
+
self.client_class.assert_called_once_with("localhost", 12345)
|
|
26
|
+
self.client.request.assert_not_called()
|
|
27
|
+
sim.close()
|
|
28
|
+
self.client.request.assert_not_called()
|
|
29
|
+
self.client.close.assert_called_once_with()
|
|
30
|
+
|
|
31
|
+
def test_simulator_defaults_to_no_world_mutation(self):
|
|
32
|
+
Simulator()
|
|
33
|
+
self.client.request.assert_not_called()
|
|
34
|
+
|
|
35
|
+
def test_explicit_no_recover_remains_supported(self):
|
|
36
|
+
flcpy.connect(recover_world=False)
|
|
37
|
+
self.client.request.assert_not_called()
|
|
38
|
+
|
|
39
|
+
def test_legacy_recovery_on_connection_remains_supported(self):
|
|
40
|
+
for factory in (flcpy.connect, Simulator):
|
|
41
|
+
with self.subTest(factory=factory):
|
|
42
|
+
self.client.request.reset_mock()
|
|
43
|
+
factory(recover_world=True)
|
|
44
|
+
self.assertEqual([call.args[0] for call in self.client.request.call_args_list],
|
|
45
|
+
[struct.pack("<IB", 3, 2), struct.pack("<I", 8)])
|
|
46
|
+
|
|
47
|
+
def test_experiment_commands_and_status(self):
|
|
48
|
+
sim = flcpy.connect()
|
|
49
|
+
for method, command in ((sim.begin_experiment, 0), (sim.end_experiment, 1)):
|
|
50
|
+
for reply, expected in ((b"\x00", True), (b"\x01", False), (b"\xff", False), (b"", False)):
|
|
51
|
+
with self.subTest(command=command, reply=reply):
|
|
52
|
+
self.client.request.reset_mock()
|
|
53
|
+
self.client.request.return_value = reply
|
|
54
|
+
self.assertIs(method(), expected)
|
|
55
|
+
self.client.request.assert_called_once_with(struct.pack("<IB", 12, command))
|
|
56
|
+
|
|
57
|
+
def test_legacy_recover_command_and_status(self):
|
|
58
|
+
sim = flcpy.connect()
|
|
59
|
+
for reply, expected in ((b"\x00", True), (b"\x01", False)):
|
|
60
|
+
self.client.request.reset_mock()
|
|
61
|
+
self.client.request.return_value = reply
|
|
62
|
+
self.assertIs(sim.recover_world(), expected)
|
|
63
|
+
self.client.request.assert_called_once_with(struct.pack("<I", 8))
|
|
64
|
+
|
|
65
|
+
def test_legacy_recovery_on_close_remains_supported(self):
|
|
66
|
+
sim = flcpy.connect()
|
|
67
|
+
sim.close(recover_world=True)
|
|
68
|
+
self.assertEqual([call.args[0] for call in self.client.request.call_args_list],
|
|
69
|
+
[struct.pack("<IB", 3, 2), struct.pack("<I", 8)])
|
|
70
|
+
self.client.close.assert_called_once_with()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
if __name__ == "__main__":
|
|
74
|
+
unittest.main()
|
flcpy-0.2.6/PKG-INFO
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: flcpy
|
|
3
|
-
Version: 0.2.6
|
|
4
|
-
Summary: Python control interface for Flare Live / Flare Real
|
|
5
|
-
Author-email: Jiwei Wang <zmh78879@gmail.com>
|
|
6
|
-
Classifier: Programming Language :: Python :: 3
|
|
7
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
-
Classifier: Operating System :: OS Independent
|
|
9
|
-
Requires-Python: >=3.8
|
|
10
|
-
Description-Content-Type: text/markdown
|
|
11
|
-
License-File: LICENSE
|
|
12
|
-
Dynamic: license-file
|
|
13
|
-
|
|
14
|
-
# Flare Python Controller (flcpy)
|
|
15
|
-
|
|
16
|
-
Python networking interface for Flare Live / Flare Real.
|
|
17
|
-
|
|
18
|
-
## Install & Upgrade
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
pip install --upgrade flcpy
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Use
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
import flcpy
|
|
28
|
-
|
|
29
|
-
s = flcpy.Simulator()
|
|
30
|
-
obj = s.get_object(...)
|
|
31
|
-
...
|
|
32
|
-
```
|
flcpy-0.2.6/README.md
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# Flare Python Controller (flcpy)
|
|
2
|
-
|
|
3
|
-
Python networking interface for Flare Live / Flare Real.
|
|
4
|
-
|
|
5
|
-
## Install & Upgrade
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
pip install --upgrade flcpy
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Use
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
import flcpy
|
|
15
|
-
|
|
16
|
-
s = flcpy.Simulator()
|
|
17
|
-
obj = s.get_object(...)
|
|
18
|
-
...
|
|
19
|
-
```
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: flcpy
|
|
3
|
-
Version: 0.2.6
|
|
4
|
-
Summary: Python control interface for Flare Live / Flare Real
|
|
5
|
-
Author-email: Jiwei Wang <zmh78879@gmail.com>
|
|
6
|
-
Classifier: Programming Language :: Python :: 3
|
|
7
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
-
Classifier: Operating System :: OS Independent
|
|
9
|
-
Requires-Python: >=3.8
|
|
10
|
-
Description-Content-Type: text/markdown
|
|
11
|
-
License-File: LICENSE
|
|
12
|
-
Dynamic: license-file
|
|
13
|
-
|
|
14
|
-
# Flare Python Controller (flcpy)
|
|
15
|
-
|
|
16
|
-
Python networking interface for Flare Live / Flare Real.
|
|
17
|
-
|
|
18
|
-
## Install & Upgrade
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
pip install --upgrade flcpy
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Use
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
import flcpy
|
|
28
|
-
|
|
29
|
-
s = flcpy.Simulator()
|
|
30
|
-
obj = s.get_object(...)
|
|
31
|
-
...
|
|
32
|
-
```
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|