Metadata-Version: 2.4
Name: pytruenas
Version: 0.0.0
Summary: A typed, Pythonic client and CLI for the TrueNAS middleware API
Project-URL: Homepage, https://github.com/jose-pr/pytruenas/
Project-URL: Issues, https://github.com/jose-pr/pytruenas/issues
Project-URL: Repository, https://github.com/jose-pr/pytruenas
Author: Jose A.
License: MIT License
        
        Copyright (c) 2026 Jose A.
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: cli,jsonrpc,middleware,sysadmin,truenas,websocket
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: System :: Filesystems
Classifier: Topic :: System :: Systems Administration
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: duho>=0.3.2
Requires-Dist: netimps>=0.0.1
Requires-Dist: pathlib-next[uri]>=0.8.2
Requires-Dist: requests
Requires-Dist: websocket-client
Provides-Extra: codegen
Requires-Dist: jinja2; extra == 'codegen'
Provides-Extra: config
Requires-Dist: pyyaml; extra == 'config'
Provides-Extra: dev
Requires-Dist: asyncssh; extra == 'dev'
Requires-Dist: build; extra == 'dev'
Requires-Dist: hatchling; extra == 'dev'
Requires-Dist: jinja2; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: pyyaml; extra == 'dev'
Requires-Dist: twine; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs; extra == 'docs'
Requires-Dist: mkdocs-material; extra == 'docs'
Requires-Dist: mkdocstrings[python]; extra == 'docs'
Provides-Extra: host
Requires-Dist: ifaddr; extra == 'host'
Provides-Extra: ssh
Requires-Dist: asyncssh; extra == 'ssh'
Requires-Dist: pathlib-next[sftp-async]>=0.8.3; extra == 'ssh'
Description-Content-Type: text/markdown

# pytruenas

[![PyPI version](https://img.shields.io/pypi/v/pytruenas.svg)](https://pypi.org/project/pytruenas/)
[![Python versions](https://img.shields.io/pypi/pyversions/pytruenas.svg)](https://pypi.org/project/pytruenas/)
[![Documentation](https://img.shields.io/badge/docs-jose--pr.github.io%2Fpytruenas-blue.svg)](https://jose-pr.github.io/pytruenas/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/jose-pr/pytruenas/blob/main/LICENSE)

A typed, Pythonic client and CLI for the [TrueNAS](https://www.truenas.com/)
middleware API.

`pytruenas` speaks the middleware's JSON-RPC 2.0 websocket protocol directly —
over `wss://`/`ws://` to a remote host, or over the local unix socket
(`ws+unix://`) when running on the NAS itself. It exposes the whole API surface
through an attribute-style namespace, adds convenience helpers for the common
create/update/upsert patterns, a remote-filesystem abstraction, an optional
typings generator, and a small CLI for scripting host configuration.

## Install

```sh
pip install pytruenas          # once published to PyPI
# or, from a checkout:
pip install .
```

Optional extras:

| Extra | Enables |
| ----- | ------- |
| `pytruenas[ssh]` | Remote shell + SFTP filesystem backend (`asyncssh`) |
| `pytruenas[config]` | YAML config/targets file for the CLI (`pyyaml`) |
| `pytruenas[codegen]` | `generate-typings` command (`jinja2`) |
| `pytruenas[host]` | Local network-adapter / packaging helpers (`ifaddr`) |

## Quickstart

```python
from pytruenas import TrueNASClient

# Remote host (api key, or "user:password", or a token)
client = TrueNASClient("nas.example.com", "1-<64-char-api-key>", sslverify=False)

# Attribute-style access to any API namespace/method:
for user in client.api.user.query():
    print(user["username"])

# Convenience helpers for common DB patterns:
client.api.user._upsert("username", username="svc", full_name="Service", group_create=True)

# Running on the NAS itself talks to the local unix socket, no auth:
local = TrueNASClient()            # ws+unix:///var/run/middleware/middlewared.sock
print(local.api.system.info())
```

### Credentials

`TrueNASClient(target, creds)` accepts, for `creds`:

- an **API key** string `"<id>-<64 chars>"`,
- `"user:password"` (optionally `"user:password\n<otp>"`),
- a **token** string,
- a `(user, password)` tuple,
- `None` / omitted → local socket auth.

`Credentials.from_env()` reads `TN_CREDS`.

## CLI

```sh
pytruenas --help
pytruenas query user -f username=root nas.example.com
pytruenas call system.info nas.example.com          # any method by dotted name
pytruenas dump-api nas.example.com > api.json
pytruenas generate-typings --path typings --api-version v26.0.0 nas.example.com
```

The target host(s) are the **trailing positional arguments** — a command's own
positionals (like `query`'s namespace) come first, then the hosts. Each target
may be comma-separated and supports `[A-Z]`/`[0-9]` range expansion (e.g.
`'nas[1-3].example.com'`); with no target the command runs against `localhost`.
`--parallel N` runs several targets concurrently. Filter `query` with
`-f/--filter KEY=VALUE` (repeatable).

## Typings generator

`generate-typings` turns a host's API definition into a package of `.pyi` stubs
so editors and type checkers understand `client.api.<namespace>.<method>(...)`.
It is validated against the full real API (every version in a live dump).

```sh
pytruenas generate-typings --path truenasapi_typings/current nas.example.com
```

## Development

```sh
py -3.14 -m venv .venv
.venv/Scripts/python -m pip install -e .[dev]
.venv/Scripts/python -m pytest
```

Supports Python 3.9+.

## License

MIT — see [LICENSE](LICENSE).
