3
0
Просмотр исходного кода

Update README and DESIGN to reflect recent fixes

README:
- Fix dependency name xattrs -> xattr
- Lead installation with `uv sync` (lock file now present)

DESIGN:
- __init__.py exports now include FileInfo and ProcResult
- Data flow references list[FileInfo] instead of "info dicts"
- File info dict section replaced with FileInfo TypedDict definition
- Subprocess runner section updated to reference ProcResult TypedDict
- Remove resolved items from known limitations (type hints, Python
  version floor, broken hatchling build config)
ZiB 4 месяцев назад
Родитель
Сommit
e4d3047895
2 измененных файлов с 21 добавлено и 22 удалено
  1. 18 19
      zz_remux/DESIGN.md
  2. 3 3
      zz_remux/README.md

+ 18 - 19
zz_remux/DESIGN.md

@@ -15,7 +15,7 @@ It is designed to run repeatedly over a media library. State is persisted via xa
 
 ```
 zz_remux/
-├── __init__.py     — Public re-exports: Consts, Tag, Scan, Mux, Lang, Proc
+├── __init__.py     — Public re-exports: Consts, FileInfo, Tag, Scan, Mux, Lang, Proc, ProcResult
 ├── __main__.py     — Package entry (delegates to cli.main)
 ├── cli.py          — Argument parsing, logging setup, directory walk, orchestration
 ├── consts.py       — Shared constants: extensions, tag names/versions, defaults
@@ -37,7 +37,7 @@ cli.py: root.walk()
     ▼
 scan.Scan.scan(files, parent)
     │  Parses each filename against the media regex.
-    │  Returns a list of "info" dicts (see File info dict below).
+    │  Returns a list[FileInfo] (see FileInfo below).
     │  Reads mux_vers and lang_vers xattrs from each file.
     │
     ├─▶ mux.Mux.mux(media)
@@ -62,21 +62,20 @@ scan.Scan.scan(files, parent)
 
 ---
 
-## File info dict
+## FileInfo
 
-`Scan.scan()` returns a list of dicts. `Mux.mux()` mutates this list in-place (removing merged sources, appending the new output file). `Lang.lang()` reads from it and updates `lang_vers`.
+`FileInfo` is a `TypedDict` defined in `consts.py` and re-exported from `__init__.py`. `Scan.scan()` returns `list[FileInfo]`. `Mux.mux()` mutates this list in-place (removing merged sources, appending the new output file). `Lang.lang()` reads from it and updates `lang_vers`.
 
 ```python
-{
-  'path':      pathlib.Path,   # absolute path to the file
-  'name':      str,            # filename only (no directory)
-  'ext':       str,            # lowercased extension: 'mkv', 'mp4', 'm4v', 'srt'
-  'group':     str,            # base name shared by the file group
-  'lang':      str | None,     # ISO 639-2/T alpha-3 code, or None
-  'sdh':       bool,           # True if filename contains the 'sdh' segment
-  'mux_vers':  int | None,     # value of zib.mux xattr, or None if not set
-  'lang_vers': int | None,     # value of zib.lang xattr, or None if not set
-}
+class FileInfo(TypedDict):
+  path:      pathlib.Path | None  # absolute path to the file
+  name:      str                  # filename only (no directory)
+  ext:       str                  # lowercased extension: 'mkv', 'mp4', 'm4v', 'srt'
+  group:     str                  # base name shared by the file group
+  lang:      str | None           # ISO 639-2/T alpha-3 code, or None
+  sdh:       bool                 # True if filename contains the 'sdh' segment
+  mux_vers:  int | None           # value of zib.mux xattr, or None if not set
+  lang_vers: int | None           # value of zib.lang xattr, or None if not set
 ```
 
 ---
@@ -149,10 +148,13 @@ Returns JSON; `Probe.probe()` parses and returns the `streams` list. Each stream
 
 ## Subprocess runner
 
-`Proc.run(cmd)` is a thin wrapper around `subprocess.run`. It captures stdout and stderr, decodes them as UTF-8, and returns:
+`Proc.run(cmd)` is a thin wrapper around `subprocess.run`. It captures stdout and stderr, decodes them as UTF-8, and returns a `ProcResult` (a `TypedDict` defined in `proc.py` and re-exported from `__init__.py`):
 
 ```python
-{ 'out': str | None, 'err': str | None, 'code': int }
+class ProcResult(TypedDict):
+  out:  str | None
+  err:  str | None
+  code: int
 ```
 
 A sentinel exit code of `-111` is used if `returncode` cannot be read. Non-zero exit codes are logged as errors.
@@ -166,6 +168,3 @@ A sentinel exit code of `-111` is used if `returncode` cannot be read. Non-zero
 - **Single video per group.** Groups with zero or more than one video file are skipped with an error log. There is no mechanism to resolve ambiguity.
 - **xattrs are filesystem-dependent.** Tags are silently lost when files cross filesystem boundaries (e.g., moving from a staging share to final storage). This causes files to be reprocessed, which is safe but redundant.
 - **No tests.** There is no test suite. External tools make unit testing awkward; integration tests against a fixture directory would be the natural approach.
-- **No type hints.** All public APIs take and return untyped dicts. A typed `FileInfo` dataclass or `TypedDict` would clarify contracts.
-- **Python version floor is understated.** `pyproject.toml` declares `requires-python = ">= 3.8"` but the codebase uses `int.from_bytes(x)` / `int.to_bytes()` without the `byteorder` argument (requires 3.11+) and f-strings with nested quotes (requires 3.12+). The floor should be `>= 3.12`.
-- **Build config is broken.** `pyproject.toml` sets `[tool.hatch.build] source = "src"` but no `src/` directory exists. The package lives at the project root and would not build correctly with hatchling without correction.

+ 3 - 3
zz_remux/README.md

@@ -22,16 +22,16 @@ Processing state is tracked via filesystem extended attributes (xattrs) so files
 ### Python
 
 - Python 3.12+
-- [`xattrs`](https://pypi.org/project/xattrs/) — filesystem extended attribute access
+- [`xattr`](https://pypi.org/project/xattr/) — filesystem extended attribute access
 - [`langcodes`](https://pypi.org/project/langcodes/) — language code normalization
 
 ## Installation
 
 ```sh
-pip install .
+uv sync
 ```
 
-Or with `uv`:
+Or to install into an existing environment:
 
 ```sh
 uv pip install .