Metadata-Version: 2.4
Name: vcti-path
Version: 1.1.0
Summary: Safe path handling for VCollab applications
Author: Visual Collaboration Technologies Inc.
License-Expression: LicenseRef-Proprietary
Project-URL: Repository, https://github.com/vcollab/vcti-python-path
Project-URL: Changelog, https://github.com/vcollab/vcti-python-path/blob/main/CHANGELOG.md
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
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"
Provides-Extra: typecheck
Requires-Dist: mypy; extra == "typecheck"
Dynamic: license-file

# Path Utilities

## Overview

Safe path handling for VCollab applications -- filename validation, file
identity (POSIX-style relative paths as stable IDs), and path resolution
with access validation. It gives you one place to validate untrusted
names and file IDs before touching the filesystem, and a stable,
platform-independent way to identify files inside a base directory.
`FileId.resolve_path` rejects absolute paths, `..` traversal, and
symbolic links so a resolved ID cannot escape its base directory.

This package has **zero external dependencies**.

---

## Installation

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

### In `requirements.txt`

```
vcti-path>=1.1.0
```

### In `pyproject.toml` dependencies

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

---

## 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

| If you want to… | Read |
|---|---|
| Get started using the package | [Quick Start](#quick-start) above |
| Understand the concepts and design decisions | [docs/design.md](docs/design.md) |
| Navigate and understand the source | [docs/source-guide.md](docs/source-guide.md) |
| Look up a specific function or type | [docs/api.md](docs/api.md) |
