Raman Gupta 4d2d367651 python-client: package as scrypted-sdk for PyPI (#2095)
* python-client: link transitive server modules required by plugin_remote

plugin_remote now imports cluster_labels, cluster_setup, plugin_console,
plugin_pip, and plugin_volume (plus a lazy plugin_repl import), but
packages/python-client only symlinks plugin_remote, rpc, rpc_reader, and
scrypted_python. As a result the client cannot be imported at all:

    ModuleNotFoundError: No module named 'cluster_labels'

Add symlinks for the missing modules, matching the existing pattern of
sharing one implementation with server/python.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WaSWgBV1XsZxWiYM16sWME

* python-client: extract reusable scrypted_client library from test.py

The only way to connect to Scrypted from Python has been to copy the
bootstrap out of test.py, which is not importable (module-level event
loop) and had drifted from the current rpc_reader/PluginRemote APIs
(writeJSON vs writeSerialized, missing ClusterSetup argument).

Move the transport and connection handshake into an importable
scrypted_client module:

- EioRpcTransport gains a close() method, an optional injectable
  aiohttp session for the engine.io connection, and queues its send
  loop on the running loop instead of via run_coroutine_threadsafe.
- connect_scrypted_client() performs login, the engine.io connect, and
  the getRemote handshake, with a connect timeout and consistent
  ScryptedConnectionError on failure. It also attaches the constructed
  SystemManager to remote.systemManager, the same wiring loadZip does
  for plugins, so PluginRemote.notify can dispatch events to
  systemManager.listen() callbacks.
- test.py becomes a small demo of the library and exits cleanly
  without os._exit(); the server URL is configurable via
  SCRYPTED_BASE_URL.

Verified live against a Scrypted server (device enumeration and OnOff
state reads).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WaSWgBV1XsZxWiYM16sWME

* python-client: bound all connect phases and tear down tasks on close

Address review feedback:

- close() now cancels and awaits both the send loop and the peer read
  loop (previously the send task was cancelled but never awaited and
  the read task was untracked), so closing the event loop after
  close() no longer risks 'Task was destroyed but it is pending'
  warnings.
- connect_scrypted_client() stores the read-loop task on the transport
  and propagates read-loop failures into the pending handshake future,
  so a link that dies mid-handshake fails immediately with the
  underlying error instead of waiting out the timeout.
- The timeout parameter now bounds every phase: the login POST
  (aiohttp ClientTimeout), the engine.io connect (asyncio.wait_for),
  and the wait for initial system state.
- Document session ownership: login_session is borrowed and never
  closed; an http_session given to EioRpcTransport is owned by the
  transport and closed by close().

Verified live against a Scrypted server: clean run with empty stderr,
plus connection-refused and bad-credential paths both raising
ScryptedConnectionError.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WaSWgBV1XsZxWiYM16sWME

* python-client: lazily import plugin host modules in plugin_remote

A client consuming plugin_remote (for SystemManager, DeviceManager,
MediaManager) only needs the types and the engine.io/rpc bits. The
plugin host modules (cluster_labels, plugin_console, plugin_pip,
plugin_volume) are only used inside loadZipWrapped, so import them
there -- importing plugin_remote no longer requires them, and the
client directory drops those symlinks (plugin_repl was already a lazy
import). cluster_setup stays: the client bootstrap constructs a
ClusterSetup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* python-client: package as scrypted-sdk for PyPI

Adds a pyproject.toml and a hatchling build hook that generates the
scrypted_sdk package at build time: it copies the client-required
modules (client.py, rpc, rpc_reader, cluster_setup, plugin_remote, and
the scrypted_python types -- reading through the symlinks into
server/python and sdk/types) and mechanically rewrites the flat imports
to package-qualified ones (import rpc -> from scrypted_sdk import rpc),
so nothing is installed into consumers' top-level namespace. No runtime
code is modified and nothing generated is committed.

A python-sdk-v* tag builds, smoke-tests, and publishes to the existing
scrypted-sdk PyPI project via trusted publishing; the same workflow
builds and smoke-tests on PRs that touch the shared Python sources.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* python-client: add examples/light.py mirroring the typescript client example

The Python equivalent of packages/client/examples/light.ts: connect,
look up a light by name, turn it on, wait, turn it off, disconnect.
Works both with the installed scrypted-sdk package and directly from a
repo checkout (falls back to the flat modules in the parent directory).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 13:53:04 -07:00
2025-10-29 11:36:04 -07:00
2024-07-18 10:24:34 -07:00
2021-10-02 20:52:59 -07:00
2024-10-26 16:19:52 -05:00
2022-11-16 11:17:11 -08:00
2025-01-18 15:04:59 -08:00
2023-07-11 11:18:44 -07:00
2023-05-08 14:48:19 -07:00

Scrypted

Scrypted is a high performance home video integration platform and NVR with smart detections. Instant, low latency, streaming to HomeKit, Google Home, and Alexa. Supports most cameras. Learn more.

Installation and Documentation

Installation and camera onboarding instructions can be found in the docs.

Community

Scrypted has active communities on Discord, Reddit, and Github. Check them out if you have questions!

Development

Debug Scrypted Plugins in VS Code

# this is an example for homekit.
# check out the code
git clone https://github.com/koush/scrypted
cd scrypted
# get the dependencies for the server and various plugins
./npm-install.sh
# open the homekit project in VS Code
code plugins/homekit

You can now launch (using the Start Debugging play button) the HomeKit Plugin in VS Code. Please be aware that you do not need to restart the Scrypted Server if you make changes to a plugin. Edit the plugin, launch, and the updated plugin will deploy on the running server.

If you do not want to set up VS Code, you can also run build and install the plugin directly from the command line:

# currently in the plugins/homekit directory.
npm run build && npm run scrypted-deploy 127.0.0.1

Plugin SDK Documentation

Want to write your own plugin? Full documentation is available here: https://developer.scrypted.app

Debug the Scrypted Server in VS Code

Debugging the server should not be necessary, as the server only provides the hosting and RPC mechanism for plugins. The following is for reference purpose. Most development can be done by debugging the relevant plugin.

# check out the code
git clone https://github.com/koush/scrypted
cd scrypted
# get the dependencies for the server and various plugins
./npm-install.sh
# open server project in VS Code
code server

You can now launch the Scrypted Server in VS Code.

Description
No description provided
Readme 67 MiB
Languages
TypeScript 79.6%
Python 16.6%
JavaScript 2.2%
Shell 1.4%
PowerShell 0.1%