Metadata-Version: 2.5
Name: dikolab-horde-common
Version: 0.0.2
Summary: The shared implementation layer under horde, its plugins, and the protocol library.
Project-URL: Homepage, https://diko316.gitlab.io/dikolab-horde/
Project-URL: Documentation, https://diko316.gitlab.io/dikolab-horde/
Project-URL: Funding, https://paypal.me/dikolab
Author-email: Diko TechSlave <diko316@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: dotenv,horde,monorepo,plugin,semver,toml
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: tomlkit>=0.13
Description-Content-Type: text/markdown

<img src="https://diko316.gitlab.io/dikolab-horde/assets/horde-logo.png" alt="horde" width="140">

# dikolab-horde-common

**The shared implementation layer under horde, its plugins, and the protocol.**
It is the base of the workspace: it depends on no other package here, so
anything above it may reuse what it provides without pulling a graph in behind
it.

TOML documents that survive a round trip, the fields horde owns in a package
file, semver arithmetic, `.env` parsing, and secret masking.

Most plugin authors want [dikolab-horde-sdk](https://pypi.org/project/dikolab-horde-sdk/),
which is built on this and covers the common cases. Reach here when it does not.

> **Status: alpha.** `0.0.2` ships the TOML document model, the package-file
> readers, semver, `.env` parsing, secret masking, and the debug tracer. The
> interfaces may still move.

## Prerequisites

- Python 3.11 or newer
- One dependency, `tomlkit`

## Getting started

```sh
pip install dikolab-horde-common
```

Every manifest horde touches belongs to somebody, so the round trip has to give
the file back the way it was found — comments, key order and formatting intact:

```python
import dikolab_horde_common_shared as common

document = common.read_document(root / "pyproject.toml")
common.write_path(document, ["project", "version"], common.next_version("1.2.3"))
(root / "pyproject.toml").write_text(common.dumps(document))
```

`read_document` returns an empty document for a file that is not there, so
"create or update" is one path rather than two.

### Reading `.env`, and why blanks matter

```python
env = common.parse_env(text)  # {"NAME": "value"}
text = common.compose_env(text, {"TOKEN": "abc"})  # add without disturbing
```

`parse_env("A=")` gives `{"A": ""}` — an empty value is a real entry, and it
*overrides* the same variable from the shell rather than sitting beside it.
Which is why `compose_env` drops empty answers rather than writing them.

### Credentials a command declares

```python
forms = [["UV_PUBLISH_TOKEN"], ["UV_PUBLISH_USERNAME", "UV_PUBLISH_PASSWORD"]]
missing = common.unsatisfied_form(forms, common.parse_env(text))
```

Each inner list is a **form**, and any one whole form is enough — so a workspace
holding a username and password is never asked for a token.

Everything raises `CommonError` and nothing else, so a caller wraps one type.

**The API reference and runnable examples:**
https://diko316.gitlab.io/dikolab-horde/dikolab-horde-common/api/

## Documentation

- [API reference](https://diko316.gitlab.io/dikolab-horde/dikolab-horde-common/api/) — with [examples](https://diko316.gitlab.io/dikolab-horde/dikolab-horde-common/api/examples/)
- [Manual](https://diko316.gitlab.io/dikolab-horde/dikolab-horde-common/manual/) · [Release notes](https://diko316.gitlab.io/dikolab-horde/dikolab-horde-common/release-notes/)

## Support

If horde saves you time, you can support its development:
https://paypal.me/dikolab

---

© 2025–2026 dikolab. Released under the MIT License.
