Migrate from Poetry and pyenv to uv
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
# `src/core/pool_index.py`
|
||||
|
||||
Unified metadata index for the Curator pool.
|
||||
|
||||
Instead of one sidecar file per movie, the whole pool keeps a single JSON index
|
||||
at `<pool>/.Curator.!index`. Curator owns the pool (it inserts/removes files
|
||||
itself), so files never move behind its back and a central index is safe.
|
||||
|
||||
The index also carries **library-level settings** (`tag_schema`,
|
||||
`copyasis_folders`) under a `settings` section, so everything describing a
|
||||
particular pool travels with the pool. The global config keeps only app data
|
||||
(window state, MRU) and the pointers to where the pool/output live.
|
||||
|
||||
On-disk shape (**v2**)::
|
||||
|
||||
{"version": 2,
|
||||
"settings": {...},
|
||||
"movies": {"tmdb-603": {"title": …, "media": [{"role", "label", "file"}, …]}}}
|
||||
|
||||
Records are keyed by the movie's **identity** (`tmdb-<id>`, or a title/year
|
||||
slug when there's no id) and own their files — see `src.core.movie`. The
|
||||
original **v1** shape keyed a record by one file's pool-relative path, which
|
||||
made metadata a passenger on that file; `PoolIndex.load` migrates such an
|
||||
index in place (backing the old file up first). Migration only rewrites
|
||||
metadata — no file on disk is moved, because a one-video movie is already in
|
||||
its v2 position.
|
||||
|
||||
Source: [`src/core/pool_index.py`](../../src/core/pool_index.py)
|
||||
|
||||
## Classes
|
||||
|
||||
### `PoolIndex`
|
||||
|
||||
*class · line 35*
|
||||
|
||||
```python
|
||||
class PoolIndex:
|
||||
```
|
||||
|
||||
Single-file JSON metadata store for all files in a pool.
|
||||
|
||||
#### `PoolIndex.__init__`
|
||||
|
||||
*method · line 38*
|
||||
|
||||
```python
|
||||
__init__(pool_dir: Path) -> None
|
||||
```
|
||||
|
||||
Open the index of the pool at `pool_dir` (loads it, migrating an older version if needed).
|
||||
|
||||
#### `PoolIndex._key`
|
||||
|
||||
*method · line 45*
|
||||
|
||||
```python
|
||||
_key(file_path: Path) -> str
|
||||
```
|
||||
|
||||
Pool-relative POSIX key for a file path.
|
||||
|
||||
#### `PoolIndex.load`
|
||||
|
||||
*method · line 53*
|
||||
|
||||
```python
|
||||
load() -> None
|
||||
```
|
||||
|
||||
Load the index from disk (missing/corrupt index = empty).
|
||||
|
||||
A v1 (path-keyed) index is migrated to v2 in place — the old file is
|
||||
copied to `.Curator.!index.v1.bak` first.
|
||||
|
||||
#### `PoolIndex._migrate_v1_to_v2`
|
||||
|
||||
*method · line 76*
|
||||
|
||||
```python
|
||||
_migrate_v1_to_v2() -> None
|
||||
```
|
||||
|
||||
Re-key path-keyed records into identity-keyed movie records.
|
||||
|
||||
Each v1 record described one file; several of them can describe one
|
||||
movie (the interim multi-version layout put them in a shared folder),
|
||||
so they are merged by identity. Metadata only — nothing is moved on
|
||||
disk, since a v1 movie's files already sit where v2 wants them.
|
||||
|
||||
#### `PoolIndex.save`
|
||||
|
||||
*method · line 139*
|
||||
|
||||
```python
|
||||
save() -> None
|
||||
```
|
||||
|
||||
Persist the index to disk.
|
||||
|
||||
#### `PoolIndex.get_setting`
|
||||
|
||||
*method · line 150*
|
||||
|
||||
```python
|
||||
get_setting(key: str, default=None)
|
||||
```
|
||||
|
||||
Return a library-level setting stored in the index.
|
||||
|
||||
#### `PoolIndex.set_setting`
|
||||
|
||||
*method · line 154*
|
||||
|
||||
```python
|
||||
set_setting(key: str, value) -> None
|
||||
```
|
||||
|
||||
Upsert a library-level setting and persist the index.
|
||||
|
||||
#### `PoolIndex.get_movie`
|
||||
|
||||
*method · line 163*
|
||||
|
||||
```python
|
||||
get_movie(key: str) -> dict | None
|
||||
```
|
||||
|
||||
Return the movie record under `key`, or None.
|
||||
|
||||
#### `PoolIndex.set_movie`
|
||||
|
||||
*method · line 167*
|
||||
|
||||
```python
|
||||
set_movie(key: str, data: dict) -> None
|
||||
```
|
||||
|
||||
Upsert a movie record and persist the index.
|
||||
|
||||
#### `PoolIndex.delete_movie`
|
||||
|
||||
*method · line 172*
|
||||
|
||||
```python
|
||||
delete_movie(key: str) -> None
|
||||
```
|
||||
|
||||
Remove a movie record (if present) and persist the index.
|
||||
|
||||
#### `PoolIndex.rekey_movie`
|
||||
|
||||
*method · line 177*
|
||||
|
||||
```python
|
||||
rekey_movie(old_key: str, new_key: str) -> None
|
||||
```
|
||||
|
||||
Move a record to a new identity key (e.g. its TMDb id was set/fixed).
|
||||
|
||||
#### `PoolIndex.all_movies`
|
||||
|
||||
*method · line 184*
|
||||
|
||||
```python
|
||||
all_movies() -> dict[str, dict]
|
||||
```
|
||||
|
||||
Every movie record, keyed by identity.
|
||||
|
||||
#### `PoolIndex.record_for`
|
||||
|
||||
*method · line 188*
|
||||
|
||||
```python
|
||||
record_for(file_path: Path) -> dict | None
|
||||
```
|
||||
|
||||
The movie record that owns `file_path`, or None if untracked.
|
||||
|
||||
#### `PoolIndex.find_movie_by_media`
|
||||
|
||||
*method · line 193*
|
||||
|
||||
```python
|
||||
find_movie_by_media(file_path: Path) -> tuple[str, dict] | None
|
||||
```
|
||||
|
||||
`(key, record)` of the movie owning `file_path`, or None.
|
||||
|
||||
The reverse lookup a file needs now that records are keyed by identity
|
||||
rather than by path.
|
||||
Reference in New Issue
Block a user