Metadata-Version: 2.1
Name: pycoreconf
Version: 0.2.0
Summary: open-source implementation of CORECONF (CoAP Management Interface)
Home-page: https://github.com/alex-fddz/pycoreconf
Author: Javier A. Fernandez
Author-email: javier.fddz@gmail.com
License: UNKNOWN
Project-URL: Source Code, https://github.com/alex-fddz/pycoreconf
Project-URL: Bug Tracker, https://github.com/alex-fddz/pycoreconf/issues
Keywords: coreconf,comi,coap,yang
Platform: UNKNOWN
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: <4,>=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cbor2 (<6.0,>=5.8)
Provides-Extra: validation
Requires-Dist: yangson (<2.0,>=1.6) ; extra == 'validation'

# pycoreconf

Open-source implementation library of CORECONF (CoAP Management Interface) for Python.

## What is CORECONF?

The [CoAP Management Interface (CORECONF)](https://datatracker.ietf.org/doc/html/draft-ietf-core-comi-11) is a network management protocol designed for constrained devices and networks. It uses the CoAP protocol to maintain a low message footprint, follows a stateless client-server architecture, and manages resources and properties defined in a [YANG](https://www.rfc-editor.org/rfc/rfc7950) data model.

CORECONF uses a CBOR mapping of YANG to keep message sizes extremely low, and substitutes the nodes' names for [YANG Schema Item iDentifiers (SIDs)](200~https://datatracker.ietf.org/doc/html/draft-ietf-core-sid-15). These are numeric values that are assigned to the model in ranges, so that each node has a corresponding SID. Moreover, the SIDs are assigned in a delta structure, which contributes to achieving a very small memory footprint.

## Installation

From PyPI, minimal install or with optional data validation support:

```
pip install pycoreconf
pip install pycoreconf[validation]
```

From source:

```
git clone https://github.com/alex-fddz/pycoreconf.git
cd pycoreconf
python3 setup.py install    # this might require root access
```

For development and testing (venv):

```
git clone https://github.com/alex-fddz/pycoreconf.git
cd pycoreconf
python3 -m venv .venv
source .venv/bin/activate # or .venv\Scripts\activate
pip install -r requirements.txt
```

### To uninstall

```
pip uninstall pycoreconf
```

## Requirements & Setup

- [ltn22/pyang](https://github.com/ltn22/pyang/) module. Allows the generation of the model's SID file including leaves' data types and list key mappings.
- Extended SID file, generated as follows (see `tools/gen_sid.sh`):

    ```
    pyang --sid-generate-file $ENTRY:$SIZE --sid-list --sid-extension $YANG [-p $MODULES]
    ```

    Where:
    - `$ENTRY`: Entry point of allocated YANG SID Range.
    - `$SIZE`: Size of allocated YANG SID Range.
    - `$YANG`: Path to the .yang data model file.
    - `$MODULES`: (Optional) Path to directories containing dependent YANG modules. Include with -p if your model requires additional modules.

    > *Note*: The range of 60,000 to 99,999 (size 40,000) is reserved for experimental YANG modules. The size of the SID range allocated for a YANG module is recommended to be a multiple of 50 and to be at least 33% above the current number of YANG items.

- For data validation against YANG data model(s):
    - A YANG data model description JSON file (see `samples/validation/description.json`).
    - Validation dependency install (`pycoreconf[validation]`).

## API and Usage

Import the module with:

```
import pycoreconf
```

### `ccm = pycoreconf.CORECONFModel(sid_files, model_description_file=None)`

Create a CORECONF Model object with an associated YANG SID file.

- `sid_files`: A single path string or a list of path strings to one or more .sid files. Generate using [ltn22/pyang](https://github.com/ltn22/pyang/) module.
- `model_description_file`: Optional model description file used for config validation.

### `ccm.add_modules_path(ietf_modules_loc)`

- `ietf_modules_loc`: Path or list of paths where IETF and other modules used in the YANG model may be found.

Returns nothing. Required for decoded configuration data validation.

### `ccm.toCORECONF(config)` 

- `config`: Configuration data as a dict, JSON string, or path to a .json file.

Returns (CBOR encoded) CORECONF configuration data. Validates config data if a model description file has been provided.

### `ccm.toJSON(cbor_data, return_pydict=False)`

- `cbor_data`: (CBOR encoded) CORECONF configuration data.
- `return_pydict`: Return data as a Python dictionary instead (useful if doing further processing or conversions to other formats)

Returns decoded configuration data as a JSON string (or Python dictionary). Validates config data if a model description file has been provided.

### `ds = ccm.create_datastore(cbor_data=None)`

Create a `CORECONFDatastore` object tied to this model, for high-level manipulation of configuration data using XPath-like paths.

- `cbor_data`: CBOR-encoded configuration data. If not provided, an empty datastore is created.

Returns a `CORECONFDatastore` instance.

### `ds[path]`

Access or modify configuration data using XPath-like syntax.

- `path`: String representing a path in the YANG data tree (e.g. "/container/list[key='value']/leaf")

Returns the value at the given path when reading.

#### Notes

- Uses a simplified XPath-like syntax (not full XML XPath)
- Predicates (`[key='value']`) are used to identify list entries
- Writing to a non-existent path **automatically creates** missing nodes
- Supports standard Python operations (`=`, `+=`, `del`, etc.)
- Refer to `docs/xpath_api.md` and `docs/xpath_api_examples.py` for more information.

#### Examples

```
# Read a value
value = ds["/measurements/measurement[type='temp'][id='0']/value"]

# Write a value
ds["/measurements/measurement[type='temp'][id='0']/value"] = 42

# Create entries (auto-created if missing)
ds["/measurements/measurement[type='humidity'][id='1']/value"] = 80

# Delete a value or entry
del ds["/measurements/measurement[type='temp'][id='0']"]
```

### `ds.predicates(path)`

Retrieve list entry key predicates for a given list path.

- `path`: XPath-like string pointing to a list node

Returns a list of predicate strings identifying existing entries.

### `ds.to_cbor()`

Export the current datastore state to CBOR-encoded CORECONF data.

Returns CBOR bytes.

### `ds.to_json()`

Export the current datastore state to a JSON string.

Returns a JSON string representation of the data.

### Other methods

### `ccm.validateConfig(config_data)`

Validates input configuration data according to the YANG data model(s). A model description file must be provided. Runs automatically during encoding/decoding.

- `config_data`: Python dictionary holding configuration data.

Returns `True` if data is valid. Raises on invalid data, or returns `False` if model description file was not provided.

### `ccm.lookupSID(config_pydict)`

- `config_pydict`: Python dictionary holding configuration data.

Returns a python dictionary with configuration keys/leaves substituted by their corresponding SID delta values.

### `ccm.lookupIdentifier(config_pydict)`

- `config_pydict`: Python dictionary holding configuration data, with SID delta values as keys.

Returns a python dictionary with SID delta keys substituted by their corresponding leaf identifiers.

## Tests

```
python3 -m unittest discover -s tests/
```

## Changelog

See [CHANGELOG.md](./CHANGELOG.md).


