Skip to main content

syq for Python

The official Python client for syq, a fast file transfer tool. Call syq.cp(...) (including cp --prune), syq.rm(...), and syq.map(...) and get typed results back; every other syq command remains one syq.run([...]) away.

python -m pip install syq

Installing the package does not install syq itself. The first default call that needs syq downloads the matching syq release if it is not already cached, checks it against the signed release manifest, and uses that managed binary for subsequent default calls. The Python package and its managed syq executable share one version: package 0.4.0 manages syq 0.4.0. syq always runs as a subprocess with an argument list, never through a shell.

import syq

print(syq.__version__)           # Python package version
print(syq.PINNED_SYQ_VERSION)    # tested executable version
print(syq.managed_executable())  # downloads once, then returns the cached path

plan = syq.cp("project", to="server", into="/backup", dry_run=True)
print(plan.files_transferred, plan.bytes_transferred)

The typed API validates syq's complete automation results stream and its agreement with the process status. Dry and live calls return the same CpResult type; dry runs report planned mutation totals and emit TraceEvent records:

client = syq.Client(process_cwd="/srv/jobs")

preview = client.cp(
    srcs_in="build",
    to="server",
    into_existing="/srv/app",
    prune=True,
    max_delete=100,
    dry_run=True,
)

removal = client.rm(
    src_dir="old-output",
    from_="server",
    root="/srv",
)
print(removal.entries_removed, removal.selectors_missing)

Typed rm works for local and ordinary SSH endpoints. A command-restricted receiver rejects native removal because its signed grants currently authorize copy mutations only.

Remote-copy controls use the same names with underscores, including coordinate_at, rsh, pscope, syq_path, no_bootstrap, tcp_plain, no_tcp, tcp_ports, tcp_congestion, and peer_auth. detach stays on raw run() because a detached command cannot return typed attached results. pscope is also available on typed rm. Direct remote-to-remote copies can lower the enrolled receiver's entry and byte ceilings with receiver_max_entries= and receiver_max_bytes=, and can request receipt detail with receiver_receipt="sizes" or receiver_receipt="digests". Ignore rules retain native ordering when interleaved by using ignore=[syq.IgnoreFrom("rules"), "!keep.tmp"]; ignore_from= remains the simple form when every file follows the inline patterns.

on_event receives typed records as syq produces them without keeping a potentially enormous operation ledger in memory:

def observe(event: syq.AutomationEvent) -> None:
    if isinstance(event, (syq.TraceEvent, syq.OperationResult)):
        print(event.action, event.dst)
    elif isinstance(event, (syq.RemovalTrace, syq.RemovalResult)):
        print(event.disposition, event.path)

result = syq.cp("data", into="backup", on_event=observe)

Pass a caller-owned binary file-like object as results= to retain the same validated NDJSON stream that produced the returned CpResult or RmResult:

with open("run.ndjson", "wb") as records:
    result = syq.cp("data", into="backup", results=records)

The object must report positive byte counts for non-empty writes. Nonblocking sinks that return None when full are rejected so an incomplete result stream cannot appear successful. The SDK flushes but never closes the object. Typed calls receive automation records through native --results-fd; stdout is not treated as machine output. Callers that need native --results FILE path behavior can use run().

Asyncio applications use the same command names and result types. Native asyncio subprocesses keep the event loop responsive; async callbacks are awaited in stream order:

import asyncio
import syq

client = syq.AsyncClient(process_cwd="/srv/jobs")
events = asyncio.Queue()

async def observe(event: syq.AutomationEvent) -> None:
    await events.put(event)

result = await client.cp(
    "data",
    to="server",
    into="backup",
    on_event=observe,
)

removed = await client.rm("old-data", from_="server", on_event=observe)

Mapping output is streaming and context-managed. Passing Python mapping entries to cp first materializes the complete iterable on disk, so a failed transform cannot launch a copy with only a valid prefix:

from dataclasses import replace

with syq.map(srcs_in="photos") as mapping:
    entries = (
        replace(entry, dst=syq.RelativePath("archive") / entry.dst)
        for entry in mapping
    )
    result = syq.cp(mapping=entries, cwd=mapping.cwd, into="published")

The async mapping stream is lazy and uses an async context manager:

async with client.map(srcs_in="photos") as mapping:
    result = await client.cp(
        mapping=mapping,
        cwd=mapping.cwd,
        into="published",
    )

mapping.cwd is the absolute source-base spelling to pass to the consuming copy. It preserves component order such as link/../selected so the native walker encounters the link before .., and it expands ~/ with the mapping subprocess's HOME. Do not normalize or resolve it between map and cp.

The source tree may contain typed support ahead of the latest released syq pin. During that development interval, use Client(executable=...) or AsyncClient(executable=...) with the candidate binary; the next SDK release updates the immutable pin only after candidate conformance tests pass.

The managed executable is stored below $XDG_CACHE_HOME/syq/sdk/python/v0.4.0/ or, when XDG_CACHE_HOME is not an absolute path, ~/.cache/syq/sdk/python/v0.4.0/. The SDK checks the complete cached binary against its embedded release manifest before every use. A corrupt or missing cache entry is replaced atomically with a freshly downloaded, verified binary.

run() raises SyqProcessError for a nonzero process status by default. The exception retains the complete result, including stdout and stderr as bytes. Pass check=False when the caller wants to interpret the status directly. When timeout expires or the caller is interrupted, the SDK kills and reaps syq's local process group, including child processes such as SSH transports, before propagating the exception.

Custom executable override

An explicit executable bypasses the managed version:

result = syq.run(["--help"], executable="/opt/custom/bin/syq")
custom_version = syq.version(executable="syq")  # intentional PATH lookup

The SDK makes no compatibility or provenance guarantee for an override. Use it for local development, controlled offline provisioning, or when deliberately testing a different syq release.

The package targets Python 3.10 or newer on Linux and macOS and has no runtime Python dependencies. See the SDK compatibility policy for the release mapping.

Native API reference

See Python native API for command signatures, mappings, failure behavior, resource ownership, and the CLI/SDK synchronization policy.

Download files

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

Source Distribution

syq-0.4.0.tar.gz (65.2 kB view details)

Uploaded Source

Built Distribution

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

syq-0.4.0-py3-none-any.whl (38.2 kB view details)

Uploaded Python 3

File details

Details for the file syq-0.4.0.tar.gz.

File metadata

  • Download URL: syq-0.4.0.tar.gz
  • Upload date:
  • Size: 65.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for syq-0.4.0.tar.gz
Algorithm Hash digest
SHA256 b3d4d10b2ceda290d5e4bb83ef61a15c6d6ddafdd2457831647d3c8e8c25ba6d
MD5 cc07abcdc2b0d1b3832588b3a030b4c1
BLAKE2b-256 26b584ffd8e65d1edf66fcc876fc87af0435abca90156aa1e245e0a5c3947e51

See more details on using hashes here.

File details

Details for the file syq-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: syq-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 38.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for syq-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dc0e34075b8eea52e2829d72b9c34a731d92e616af876da006fd424325afb765
MD5 78b35cb107cc4eec45d5dd25cd100b20
BLAKE2b-256 e0f67f184d64caf77d7163426d1138fead4be03c9759eb8f2fb8a40aa2729a62

See more details on using hashes here.

Release history Release notifications | RSS feed

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

0.4.1

2 files

This release

0.4.0 This release

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page