Metadata-Version: 2.4
Name: vcti-path
Version: 1.0.3
Summary: Safe path handling for VCollab applications
Author: Visual Collaboration Technologies Inc.
Requires-Python: <3.15,>=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Provides-Extra: lint
Requires-Dist: ruff; extra == "lint"
Dynamic: license-file

# Path Utilities

## Purpose

Safe path handling for VCollab applications -- filename validation, file
identity (POSIX-style relative paths as stable IDs), and path resolution
with access validation.

This package has **zero external dependencies**.

---

## Installation

```bash
pip install vcti-path
```

### In `requirements.txt`

```
vcti-path>=1.0.3
```

### In `pyproject.toml` dependencies

```toml
dependencies = [
    "vcti-path>=1.0.3",
]
```

---

## Quick Start

### Validate filenames

```python
from vcti.path import FileNameValidator

FileNameValidator.is_valid("report.pdf")     # True
FileNameValidator.is_valid("bad|name")       # False
FileNameValidator.is_valid("..")             # False

FileNameValidator.validate("data.json")      # OK
FileNameValidator.validate("bad/name")       # Raises ValueError
```

### File IDs -- stable POSIX-style identifiers

A file ID is a POSIX-format relative path that uniquely identifies a
file or directory within a base directory. No leading `/`, `./`, or `../`.

```python
from pathlib import Path
from vcti.path import FileId

# Validate
FileId.is_valid("scripts/setup.sh")     # True
FileId.is_valid("/absolute/path")       # False
FileId.is_valid("../escape")            # False

# Resolve to filesystem path
base = Path("/project")
FileId.resolve_path("src/main.py", base)
# -> Path("/project/src/main.py")

# Extract file ID from a path
src = Path("/project/src/main.py")
FileId.get_file_id(src, base)
# -> "src/main.py"
```

### Path resolution and access validation

```python
from vcti.path import abs_path, validate_file_access, resolve_path

# Absolute path resolution
abs_path("relative/file.txt")
# -> Path("<cwd>/relative/file.txt")

# Validate that a file exists and is readable
validate_file_access("config.yaml")
# Raises FileNotFoundError, IsADirectoryError, or PermissionError

# Resolve relative to a base directory
resolve_path("data/input.csv", "/project")
# -> Path("/project/data/input.csv")
```

---

## Public API

| Symbol | Type | Purpose |
|--------|------|---------|
| `FileNameValidator.is_valid(name)` | classmethod | Check if a filename is valid |
| `FileNameValidator.validate(name)` | classmethod | Validate filename, raise `ValueError` if invalid |
| `FileId.is_valid(file_id)` | staticmethod | Check if a POSIX file ID is valid |
| `FileId.validate(file_id)` | staticmethod | Validate file ID, raise `ValueError` if invalid |
| `FileId.resolve_path(file_id, base_dir)` | staticmethod | Resolve file ID to absolute path |
| `FileId.get_file_id(file_path, base_dir)` | staticmethod | Extract file ID from absolute path |
| `abs_path(fp)` | function | Convert to absolute resolved `Path` |
| `validate_file_access(fp)` | function | Validate file exists and is readable |
| `validate_folder_access(fp)` | function | Validate directory exists |
| `resolve_path(path, base_dir)` | function | Resolve path relative to base directory |

---

## Documentation

- [Design](docs/design.md) -- Concepts, architecture decisions, and rationale
- [Source Guide](docs/source-guide.md) -- File descriptions and execution flow traces
- [API Reference](docs/api.md) -- Autodoc for all modules
