Skip to main content

Python wrapper for the Threadle command-line interface

Project description

threadlepy

threadlepy is a Python client for the Threadle CLI JSON interface. It starts a Threadle subprocess, sends commands over stdin/stdout, and exposes Python wrappers that mirror the core workflow of YukunJiao/threadleR.

Status: experimental. The wrapper names and returned payload shapes follow the Threadle CLI and may evolve with the backend.

threadlepy follows its own PyPI versioning. Its API is designed to correspond to Threadle CLI commands and is inspired by threadleR, but version numbers are not synchronized with threadleR releases.

Installation

pip install threadlepy

For local development:

pip install -e .

Requirements:

  • Python 3.9+
  • A working Threadle CLI executable named threadle on PATH, or a full path passed to threadlepy.start()

Quick Start

import threadlepy
import threadlepy.commands as th

threadlepy.configure(timeout=3600)
threadlepy.start()

examples = th.load_examples("lazega")
lazega = examples["lazega"]

th.info(lazega)
th.get_node_alters(lazega, nodeid=23, layernames="friends", direction="out")
th.shortest_path(lazega, node1id=1, node2id=23, layernames="friends")

threadlepy.stop()

You can also manage the Threadle process with a context manager:

import threadlepy
import threadlepy.commands as th

with threadlepy.session(timeout=3600):
    examples = th.load_examples("mynet")
    print(th.info(examples["mynet"]))

If threadle is not on PATH, pass the full executable path to threadlepy.start("/full/path/to/threadle") or threadlepy.session("/full/path/to/threadle").

Integration Test Script

The repository includes a threadleR-style smoke test that exercises the public command wrappers against bundled example data:

python scripts/test_commands.py

If threadle is not on PATH, pass the executable explicitly:

python scripts/test_commands.py --threadle /full/path/to/threadle

There is also a small lifecycle smoke test for the recommended scripting style with threadlepy.session():

python scripts/test_session.py

or:

python scripts/test_session.py --threadle /full/path/to/threadle

The script:

  • starts and stops the Threadle CLI process
  • loads mynet from the bundled example data
  • runs inventory, metadata, node, attribute, edge, path, degree, density, component, two-mode, transformation, import/export, raw-command, and cleanup commands
  • creates a scratch network for mutating commands so the example workflow stays easy to inspect

When the Threadle executable is unavailable, the script exits with code 77 and prints a skip message.

Tutorial Notebook

A runnable tutorial notebook is available at:

docs/threadlepy_tutorial.ipynb

Open it with Jupyter, VS Code, or another notebook UI:

jupyter notebook docs/threadlepy_tutorial.ipynb

The notebook follows the same design as the threadleR vignette: start Threadle, load example data, inspect nodes and attributes, work with one-mode and two-mode layers, derive structures, edit a scratch network, import/export files, and clean up.

Handles

Commands that create or load structures return lightweight Python handles:

ns = th.create_nodeset("ns", createnodes=5)
net = th.create_network("net", ns)

A handle stores the backend variable name. Any wrapper that expects a network or nodeset also accepts the raw backend name as a string.

Most wrappers are available in two styles: Pythonic names such as create_nodeset() and shortest_path(), plus threadleR-style aliases such as th_create_nodeset() and th_shortest_path().

Working Directory and Examples

th.get_workdir()
th.set_workdir("~/my_threadle_workspace")
th.sync_wd()

example_dir = th.stage_examples_to_wd("threadle_examples")
th.set_workdir(example_dir)

Bundled datasets can be loaded directly:

objs = th.load_examples(["mynet", "lazega"])
mynet = objs["mynet"]

Creating and Editing Networks

ns = th.create_nodeset("people", createnodes=10)
net = th.create_network("relations", ns)

th.add_layer(net, "friends", mode=1, directed=False, valuetype="binary")
th.add_edge(net, "friends", 1, 2)
th.check_edge(net, "friends", 1, 2)
th.remove_edge(net, "friends", 1, 2)

th.add_layer(net, "clubs", mode=2)
th.add_hyper(net, "clubs", "club_a", nodes=[1, 2, 3])
th.add_aff(net, "clubs", nodeid=4, hypername="club_a")
th.get_hyperedge_nodes(net, "clubs", "club_a")

Attributes

th.define_attr(ns, "group", "string")
th.set_attr(ns, nodeid=1, attrname="group", attrvalue="A")
th.get_attr(ns, nodeid=1, attrname="group")

th.generate_attr(ns, "score", attrtype="int", min=1, max=10)
th.get_attr_summary(ns, "score")
th.get_attrs(ns, nodes=[1, 2, 3], attrname="score")

Queries and Measures

th.get_all_nodes(ns, offset=0, limit=100)
th.get_all_edges(net, "friends", offset=0, limit=1000)
th.get_degree(net, nodeid=1, layernames="friends", direction="both")
th.degree(net, "friends", attrname="friends_degree", direction="both")
th.density(net, "friends", samplesize=500)
th.components(net, "friends", attrname="component")

Multiple layer names can be passed as a Python list; the client sends the semicolon-separated format expected by Threadle:

th.shortest_path(net, 1, 8, layernames=["friends", "coworkers"])

Transformations and Random Walks

th.symmetrize(net, "advice", method="max", newlayername="advice_sym")
th.project_two_mode(net, "clubs", method="count", newlayername="club_projection")
th.pack(net, "friends")
th.unpack(net, "friends")

rw = th.rwdistances("rw_dist", net, attrname="group", maxsteps=100)
mfpt = th.rwfpt("mfpt", net, attrname="group", maxsteps=100, minpairobs=10)

File IO

th.save_file(ns, "people.tsv")
ns2 = th.load_file("people2", "people.tsv", type="nodeset")

th.export_layer(net, "friends", "friends.tsv", header=True, sep="\t")
th.import_layer(net, "friends", "friends.tsv", format="edgelist", header=True)
th.export(net, format="gexf", file="friends.gexf", layername="friends")

Raw Commands

Use threadlepy.raw_cmd() or th.cmd() for backend commands that do not yet have a typed wrapper:

payload = threadlepy.raw_cmd("i")
handle = th.cmd("createnodeset", {"createnodes": 3}, assign="tmp", type="nodeset")

Function Coverage

threadlepy.commands includes wrappers for Threadle process workflow, inventory, file IO, layer editing, node editing, attributes, shortest paths, degree and density, components, random generation, random walks, packing, projection, filtering, subnetwork creation, and export utilities.

Release Checklist

Before publishing a new PyPI release:

python3 -m compileall src/threadlepy scripts/test_commands.py
python3 -m json.tool docs/threadlepy_tutorial.ipynb > /tmp/threadlepy_tutorial_checked.json
python3 scripts/test_commands.py
python3 scripts/test_session.py
python3 -m build
python3 -m twine check dist/*

Use TestPyPI first when publishing a new release line.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

threadlepy-0.1.0.tar.gz (25.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

threadlepy-0.1.0-py3-none-any.whl (19.6 kB view details)

Uploaded Python 3

File details

Details for the file threadlepy-0.1.0.tar.gz.

File metadata

  • Download URL: threadlepy-0.1.0.tar.gz
  • Upload date:
  • Size: 25.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for threadlepy-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5ac529687d346b3c1929cf72ac13ef21d31648ed3e1a2225b8cb2b7392208fe8
MD5 8cf7169159d55a9917efac21c5102e4f
BLAKE2b-256 e20c2a5daba6b9cac490e8e2d92693830e6c387fa233949635933a3b74bdca25

See more details on using hashes here.

File details

Details for the file threadlepy-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: threadlepy-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 19.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for threadlepy-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7fd80767952be00592c8f536ecf6a2980908767106e77fdca89146a4bfcf1c61
MD5 b191e7b5389b5762fe4eb5eab35be6e5
BLAKE2b-256 c5434ad152ba7f97222c3bc005d4cd775d0b68840d43b52167e371e3f5711d82

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page