threadlepy 0.1.0__tar.gz → 0.1.2__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.
- {threadlepy-0.1.0 → threadlepy-0.1.2}/CHANGELOG.md +11 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/MANIFEST.in +1 -0
- threadlepy-0.1.2/PKG-INFO +69 -0
- threadlepy-0.1.2/README.md +52 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/pyproject.toml +3 -3
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy/__init__.py +1 -1
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy/client.py +7 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy/commands.py +120 -34
- threadlepy-0.1.2/src/threadlepy/py.typed +1 -0
- threadlepy-0.1.2/src/threadlepy.egg-info/PKG-INFO +69 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy.egg-info/SOURCES.txt +1 -0
- threadlepy-0.1.0/PKG-INFO +0 -278
- threadlepy-0.1.0/README.md +0 -261
- threadlepy-0.1.0/src/threadlepy.egg-info/PKG-INFO +0 -278
- {threadlepy-0.1.0 → threadlepy-0.1.2}/LICENSE +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/docs/threadlepy_tutorial.ipynb +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/scripts/test_commands.py +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/scripts/test_session.py +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/setup.cfg +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy/Examples/Scripts/create.txt +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy/Examples/dscw.tsv +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy/Examples/dscw_nodeset.tsv +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy/Examples/lazega.tsv +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy/Examples/lazega_female.tsv +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy/Examples/lazega_female_nodeset.tsv +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy/Examples/lazega_nodes.tsv +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy/Examples/mynet.tsv +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy/Examples/mynet_nodesetfile.tsv +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy/Examples/mynodes.tsv +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy.egg-info/dependency_links.txt +0 -0
- {threadlepy-0.1.0 → threadlepy-0.1.2}/src/threadlepy.egg-info/top_level.txt +0 -0
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.2
|
|
4
|
+
|
|
5
|
+
- Added one-line docstrings for public command wrappers.
|
|
6
|
+
- Added `Literal` type hints for finite-choice parameters to improve editor completions.
|
|
7
|
+
- Marked the package as typed with `py.typed`.
|
|
8
|
+
|
|
9
|
+
## 0.1.1
|
|
10
|
+
|
|
11
|
+
- Updated PyPI project description to match README.
|
|
12
|
+
- Synchronized package metadata version with the 0.1.1 release.
|
|
13
|
+
|
|
3
14
|
## 0.1.0
|
|
4
15
|
|
|
5
16
|
- Expanded Python command wrappers to better correspond to Threadle.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: threadlepy
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Python client for the Threadle CLI JSON interface.
|
|
5
|
+
Author: Yukun Jiao
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/YukunJiao/threadlepy
|
|
8
|
+
Project-URL: Issues, https://github.com/YukunJiao/threadlepy/issues
|
|
9
|
+
Project-URL: Documentation, https://github.com/YukunJiao/threadlepy#readme
|
|
10
|
+
Project-URL: Source, https://github.com/YukunJiao/threadlepy
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Requires-Python: >=3.9
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Dynamic: license-file
|
|
17
|
+
|
|
18
|
+
# threadlepy
|
|
19
|
+
|
|
20
|
+
Python client for the Threadle CLI JSON interface.
|
|
21
|
+
|
|
22
|
+
`threadlepy` starts a Threadle subprocess and exposes Python wrappers for core Threadle workflows.
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install threadlepy
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Requirements:
|
|
31
|
+
|
|
32
|
+
- Python 3.9+
|
|
33
|
+
- A working `threadle` executable available on `PATH`
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
import threadlepy
|
|
39
|
+
import threadlepy.commands as th
|
|
40
|
+
|
|
41
|
+
with threadlepy.session(timeout=3600):
|
|
42
|
+
examples = th.load_examples("lazega")
|
|
43
|
+
lazega = examples["lazega"]
|
|
44
|
+
|
|
45
|
+
print(th.info(lazega))
|
|
46
|
+
|
|
47
|
+
path = th.shortest_path(
|
|
48
|
+
lazega,
|
|
49
|
+
node1id=1,
|
|
50
|
+
node2id=23,
|
|
51
|
+
layernames="friends",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
print(path)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
If `threadle` is not on `PATH`, pass the executable path explicitly:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
threadlepy.start("/full/path/to/threadle")
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Documentation
|
|
64
|
+
|
|
65
|
+
For more examples and workflows, see:
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
docs/threadlepy_tutorial.ipynb
|
|
69
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# threadlepy
|
|
2
|
+
|
|
3
|
+
Python client for the Threadle CLI JSON interface.
|
|
4
|
+
|
|
5
|
+
`threadlepy` starts a Threadle subprocess and exposes Python wrappers for core Threadle workflows.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install threadlepy
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Requirements:
|
|
14
|
+
|
|
15
|
+
- Python 3.9+
|
|
16
|
+
- A working `threadle` executable available on `PATH`
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
import threadlepy
|
|
22
|
+
import threadlepy.commands as th
|
|
23
|
+
|
|
24
|
+
with threadlepy.session(timeout=3600):
|
|
25
|
+
examples = th.load_examples("lazega")
|
|
26
|
+
lazega = examples["lazega"]
|
|
27
|
+
|
|
28
|
+
print(th.info(lazega))
|
|
29
|
+
|
|
30
|
+
path = th.shortest_path(
|
|
31
|
+
lazega,
|
|
32
|
+
node1id=1,
|
|
33
|
+
node2id=23,
|
|
34
|
+
layernames="friends",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
print(path)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If `threadle` is not on `PATH`, pass the executable path explicitly:
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
threadlepy.start("/full/path/to/threadle")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Documentation
|
|
47
|
+
|
|
48
|
+
For more examples and workflows, see:
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
docs/threadlepy_tutorial.ipynb
|
|
52
|
+
```
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "threadlepy"
|
|
7
|
-
version = "0.1.
|
|
8
|
-
description = "Python
|
|
7
|
+
version = "0.1.2"
|
|
8
|
+
description = "Python client for the Threadle CLI JSON interface."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
11
11
|
license = "MIT"
|
|
@@ -27,4 +27,4 @@ Source = "https://github.com/YukunJiao/threadlepy"
|
|
|
27
27
|
where = ["src"]
|
|
28
28
|
|
|
29
29
|
[tool.setuptools.package-data]
|
|
30
|
-
threadlepy = ["Examples/*.tsv", "Examples/Scripts/*.txt"]
|
|
30
|
+
threadlepy = ["py.typed", "Examples/*.tsv", "Examples/Scripts/*.txt"]
|
|
@@ -48,6 +48,7 @@ def configure(
|
|
|
48
48
|
default_timeout = float(timeout)
|
|
49
49
|
|
|
50
50
|
def stop():
|
|
51
|
+
"""Stop the running Threadle subprocess, if one is active."""
|
|
51
52
|
global proc
|
|
52
53
|
if proc and proc.poll() is None:
|
|
53
54
|
print("threadle stopped")
|
|
@@ -56,6 +57,7 @@ def stop():
|
|
|
56
57
|
proc = None
|
|
57
58
|
|
|
58
59
|
def start(path: str | None = None) -> subprocess.Popen[str]:
|
|
60
|
+
"""Start the Threadle CLI JSON subprocess and return the process handle."""
|
|
59
61
|
global proc
|
|
60
62
|
if path is None or not str(path).strip():
|
|
61
63
|
exe = shutil.which("threadle")
|
|
@@ -112,9 +114,11 @@ def session(path: str | None = None, **config: Any) -> Iterator[subprocess.Popen
|
|
|
112
114
|
stop()
|
|
113
115
|
|
|
114
116
|
def collect_args(**kwargs):
|
|
117
|
+
"""Return keyword arguments whose values are not ``None``."""
|
|
115
118
|
return {k: v for k, v in kwargs.items() if v is not None}
|
|
116
119
|
|
|
117
120
|
def json_cmd(command: str, args: Optional[Dict[str, Any]] = None, assign: Optional[str] = None) -> str:
|
|
121
|
+
"""Build a JSON command payload for the Threadle CLI."""
|
|
118
122
|
dto = {
|
|
119
123
|
"Assign": assign,
|
|
120
124
|
"Command": str(command),
|
|
@@ -123,6 +127,7 @@ def json_cmd(command: str, args: Optional[Dict[str, Any]] = None, assign: Option
|
|
|
123
127
|
return json.dumps(dto, ensure_ascii=False)
|
|
124
128
|
|
|
125
129
|
def send_command(cmd_json: str, timeout: Optional[float] = None) -> Dict[str, Any]:
|
|
130
|
+
"""Send a JSON command to Threadle and wait for a JSON response."""
|
|
126
131
|
global proc
|
|
127
132
|
if proc is None or proc.poll() is not None:
|
|
128
133
|
raise RuntimeError("Threadle process is not running.")
|
|
@@ -177,6 +182,7 @@ def send_command(cmd_json: str, timeout: Optional[float] = None) -> Dict[str, An
|
|
|
177
182
|
raise TimeoutError(hint)
|
|
178
183
|
|
|
179
184
|
def unwrap(resp: Dict[str, Any], *, print_message: bool = True) -> Any:
|
|
185
|
+
"""Validate a Threadle response and return its payload."""
|
|
180
186
|
if resp.get("Success") is not True:
|
|
181
187
|
code = resp.get("Code") or "Error"
|
|
182
188
|
msg = resp.get("Message") or "Threadle error"
|
|
@@ -209,6 +215,7 @@ def call(
|
|
|
209
215
|
return_response: bool = False,
|
|
210
216
|
drop: tuple[str, ...] = (),
|
|
211
217
|
) -> Any:
|
|
218
|
+
"""Call a typed Threadle command wrapper using the caller's local variables."""
|
|
212
219
|
args = collect_args(**locals_dict)
|
|
213
220
|
args.pop("cmd", None)
|
|
214
221
|
args.pop("assign", None)
|