Metadata-Version: 2.4
Name: vcti-fileloader-mesh
Version: 1.0.0
Summary: Base classes for mesh fileloader plugins producing mesh-schema DataNode trees
Author: Visual Collaboration Technologies Inc.
Requires-Python: <3.15,>=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Requires-Dist: vcti-fileloader>=5.1
Requires-Dist: vcti-mesh-schema>=1.0.0
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Provides-Extra: lint
Requires-Dist: ruff; extra == "lint"
Provides-Extra: typecheck
Requires-Dist: mypy; extra == "typecheck"
Dynamic: license-file

# vcti-fileloader-mesh

Base classes for mesh fileloader plugins producing mesh-schema DataNode trees.

## Overview

`vcti-fileloader-mesh` is the shared base of the mesh loader family. A
mesh format loader (SLIM, PLY, ...) differs from its siblings only in how
it opens a file and enumerates its blocks; everything else — the subtree
transaction, lazy-vs-eager attachment, schema guarantees, locking, and
rollback — is identical. `MeshLoaderBase` implements that shared part
once: subclasses provide `can_load` / `load` / `unload` plus a
`block_specs()` that yields one `MeshBlockSpec` per block, and inherit a
`populate()` that grafts a locked, [mesh-schema](https://pypi.org/project/vcti-mesh-schema/)-conforming
subtree into any `LockableTree`. The result satisfies the
`vcti.fileloader.core.Loader` protocol, so mesh loaders register and
dispatch like every other fileloader plugin.

## Installation

```bash
pip install vcti-fileloader-mesh
```

### In `requirements.txt`

```
vcti-fileloader-mesh>=1.0.0
```

### In `pyproject.toml` dependencies

```toml
dependencies = [
    "vcti-fileloader-mesh>=1.0.0",
]
```

---

## Quick Start

A complete mesh format loader is the format-specific part only:

```python
from pathlib import Path
from typing import Any

from vcti.fileloader.mesh import MeshBlockSpec, MeshLoaderBase

class MyMeshLoader(MeshLoaderBase):
    id = "mymesh-numpy-loader"

    def can_load(self, path: Path) -> bool:
        return path.suffix.lower() == ".mymesh"

    def load(self, path: Path, **options: Any):
        return open_my_format(path)          # opaque handle

    def unload(self, handle) -> None:
        handle.close()                        # idempotent

    def block_specs(self, handle, **options):
        for element in handle.header:         # cheap metadata only
            yield MeshBlockSpec(
                name=element.name,            # "node", "triangle", ...
                count=element.count,
                dtype=element.record_dtype,
                read=lambda e=element: handle.read_block(e),
            )
```

Using it is the standard fileloader lifecycle:

```python
from vcti.fileloader.core import DataNode
from vcti.tree.core import DictTree

loader = MyMeshLoader()
tree = DictTree(root_data=DataNode())
with loader.open(Path("part.mymesh")) as handle:
    mesh_root = loader.populate(handle, tree, tree.root_handle)
```

Blocks attach lazily — nothing is read until a block's `.load()` — and
the subtree is guaranteed to conform to the mesh schema's structure, so
`vcti.mesh.schema` accessors and the mesh exporters consume it directly.

---

## API surface

| Name | Kind | Purpose |
|------|------|---------|
| `MeshLoaderBase` | ABC | `populate()` template; subclasses add `can_load`/`load`/`unload`/`block_specs` |
| `MeshLoaderBase.populate(handle, tree, parent, *, before_lock, lazy)` | method | Attach a locked mesh subtree (lazy blocks by default) |
| `MeshLoaderBase.root_attributes(handle)` | hook | File-native attributes for the mesh root (default: none) |
| `MeshLoaderBase.open(path)` | context manager | `load()`/`unload()` pairing |
| `MeshBlockSpec` | dataclass | One block: name, count, dtype, `read` callable, attributes |

See [docs/design.md](docs/design.md) for the model and
[docs/extending.md](docs/extending.md) for the full guide to writing a
format loader.

---

## Dependencies

- [vcti-fileloader](https://pypi.org/project/vcti-fileloader/) — the `Loader` contract and `SubtreeBuilder`.
- [vcti-mesh-schema](https://pypi.org/project/vcti-mesh-schema/) — the mesh block schema the base assembles.
- [numpy](https://numpy.org/) — block arrays.
