Metadata-Version: 2.4
Name: oaknut-file
Version: 10.0.2
Summary: Acorn file metadata handling: INF sidecars, filename encoding, xattrs, and access flags
Author-email: Robert Smallshire <robert@smallshire.org.uk>
License-Expression: MIT
Project-URL: Homepage, https://github.com/rob-smallshire/oaknut
Project-URL: Repository, https://github.com/rob-smallshire/oaknut
Project-URL: Issues, https://github.com/rob-smallshire/oaknut/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: System :: Filesystems
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: xattr>=1.0; sys_platform == "darwin"
Dynamic: license-file

# oaknut-file

[![PyPI version](https://img.shields.io/pypi/v/oaknut-file.svg)](https://pypi.org/project/oaknut-file/)
[![CI](https://github.com/rob-smallshire/oaknut-file/actions/workflows/tests.yml/badge.svg)](https://github.com/rob-smallshire/oaknut-file/actions/workflows/tests.yml)
[![Python versions](https://img.shields.io/pypi/pyversions/oaknut-file.svg)](https://pypi.org/project/oaknut-file/)
[![License: MIT](https://img.shields.io/pypi/l/oaknut-file.svg)](https://github.com/rob-smallshire/oaknut-file/blob/master/LICENSE)

Acorn file metadata handling for the oaknut package family.

`oaknut-file` is the shared metadata layer used by
[`oaknut-zip`](https://github.com/rob-smallshire/oaknut-zip) and
[`oaknut-dfs`](https://github.com/rob-smallshire/oaknut-dfs). It provides:

- The `Access` IntFlag enum for Acorn file attribute bytes
- The `AcornMeta` dataclass for load/exec addresses and attributes
- INF sidecar file parsing and formatting (traditional and PiEconetBridge variants)
- Filename metadata encoding (`,xxx`, `,llllllll,eeeeeeee`, `,load-exec`)
- Extended attribute read/write under `user.acorn.*` and `user.econet_*`

## Installation

Using [uv](https://docs.astral.sh/uv/) (recommended):

```bash
uv add oaknut-file
```

`pip install oaknut-file` also works.

The `xattr` package is automatically installed on macOS, where it is
required for extended attribute support. Linux uses `os.setxattr` from
the standard library and needs no additional dependency. Windows does
not support extended attributes; the xattr functions will raise on use.

## Quick start

### Access flags

The `Access` IntFlag enum represents the standard Acorn OSFILE attribute byte.
Bit values match the filing system API convention used by PiEconetBridge and
the `user.acorn.attr` extended attribute.

```python
from oaknut.file import Access

# Compose flags with bitwise OR
flags = Access.R | Access.W | Access.L
print(repr(flags))   # <Access.R|W|L: 11>
print(hex(flags))    # 0x0B
```

| Flag | Value | Meaning |
|------|-------|---------|
| `Access.R`  | 0x01 | Owner read |
| `Access.W`  | 0x02 | Owner write |
| `Access.E`  | 0x04 | Execute only |
| `Access.L`  | 0x08 | Locked |
| `Access.PR` | 0x10 | Public read |
| `Access.PW` | 0x20 | Public write |

### INF sidecar files

Two INF sidecar formats are supported. `parse_inf_line()` auto-detects which
format a line uses, while `format_trad_inf_line()` and `format_pieb_inf_line()`
let you choose explicitly when writing.

```python
from oaknut.file import (
    Access, format_trad_inf_line, format_pieb_inf_line, parse_inf_line,
)

# Traditional INF: filename load exec length [attr]
trad = format_trad_inf_line(
    filename="HELLO",
    load_addr=0x1900,
    exec_addr=0x8023,
    length=0x100,
    attr=int(Access.R | Access.W),
)
print(trad)
# HELLO       00001900 00008023 00000100 03

# PiEconetBridge INF: owner load exec perm
pieb = format_pieb_inf_line(
    load_addr=0xFFFFDD00,
    exec_addr=0xFFFFDD00,
    attr=int(Access.R | Access.W | Access.L | Access.PR),
)
print(pieb)
# 0 ffffdd00 ffffdd00 1b

# Auto-detect format on parse
source, meta = parse_inf_line(trad)
print(meta)
# AcornMeta(load_addr=0x1900, exec_addr=0x8023, attr=0x03)

source, meta = parse_inf_line(pieb)
print(meta)
# AcornMeta(load_addr=0xFFFFDD00, exec_addr=0xFFFFDD00, attr=0x1B, filetype=0xFDD)
```

### Filename metadata encoding

Three filename suffix conventions are supported for embedding load/exec
addresses or RISC OS filetypes in host filenames.

```python
from oaknut.file import parse_encoded_filename

# RISC OS filetype suffix (3 hex digits)
clean, meta = parse_encoded_filename("PROG,ffb")
print(clean, meta.infer_filetype())
# ('PROG', filetype=0xFFB)

# MOS load-exec suffix (variable-width hex)
clean, meta = parse_encoded_filename("PROG,1900-801f")
print(clean, meta.load_addr, meta.exec_addr)
# ('PROG', load_addr=0x1900, exec_addr=0x801F)
```

### Filetype-stamped load addresses

When a load address has its top 12 bits set to `0xFFF`, the next 12 bits
encode a RISC OS filetype.

```python
from oaknut.file import AcornMeta

meta = AcornMeta(load_addr=0xFFFF0E10)
print(meta.is_filetype_stamped, hex(meta.infer_filetype()))
# is_filetype_stamped=True, infer_filetype()=0xF0E
```

### Extended attributes

```python
from oaknut.file import write_acorn_xattrs, read_acorn_xattrs

# Write to user.acorn.* namespace
write_acorn_xattrs(
    "myfile.bin",
    load_addr=0x1900,
    exec_addr=0x8023,
    attr=0x03,
)

# Read back (falls through to user.econet_* if user.acorn.* is absent)
meta = read_acorn_xattrs("myfile.bin")
print(meta.load_addr, meta.exec_addr, meta.attr)
```

## Public API

| Module | Exports |
|--------|---------|
| `oaknut.file.access` | `Access`, `format_access_hex`, `format_access_text` |
| `oaknut.file.meta` | `AcornMeta` |
| `oaknut.file.formats` | `MetaFormat`, `SOURCE_*` labels |
| `oaknut.file.inf` | `parse_inf_line`, `format_trad_inf_line`, `format_pieb_inf_line`, `read_inf_file`, `write_inf_file` |
| `oaknut.file.filename_encoding` | `parse_encoded_filename`, `build_filename_suffix`, `build_mos_filename_suffix` |
| `oaknut.file.xattr` | `read_acorn_xattrs`, `write_acorn_xattrs`, `read_econet_xattrs`, `write_econet_xattrs` |

All public symbols are also re-exported from the top-level `oaknut.file` package.

## License

MIT
