Metadata-Version: 2.4
Name: jellyplex-gen
Version: 0.1.1
Summary: Generate plausible test media libraries in Plex or Jellyfin format
Author: Stefan Schönberger
Author-email: Stefan Schönberger <stefan@sniner.dev>
License-Expression: BSD-3-Clause
License-File: LICENSE
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.11
Description-Content-Type: text/markdown

# jellyplex-gen

Generate plausible test media libraries in Plex or Jellyfin format.

A sibling project to [jellyplex-sync](https://github.com/sniner/jellyplex-sync):
where `jellyplex-sync` converts between media library formats, `jellyplex-gen`
produces realistic-looking source material to test it (or anything else that
operates on Plex/Jellyfin libraries) against.

Generated libraries consist of placeholder files (0-byte by default, or
pseudorandom bytes up to a configurable per-file maximum) arranged according
to the chosen format's naming conventions. A format-neutral JSON manifest is
written alongside, describing the logical content of the library.

## Status

Early. Plex format only, flat hierarchy, single resolution variant per movie.
Designed so other formats and structures can be added without touching the
existing code paths.

## Quick start

```bash
uv run jellyplex-gen plex --seed=hello --movies=50 --out=./testlib
```

The same `--seed` always produces the same library. Seeds are arbitrary
alphanumeric strings — they get hashed to an integer internally, so
reproducibility doesn't depend on Python's `PYTHONHASHSEED`.

To get just the manifest (no files written):

```bash
uv run jellyplex-gen manifest --seed=hello --movies=50
```

For copy-semantics or content-aware testing, fill files with up to N bytes
of pseudorandom content (default is 0, i.e. empty files):

```bash
uv run jellyplex-gen plex --seed=hello --movies=20 --max-content-size=4096 --out=./testlib
```

File contents are seeded per-file from the manifest seed and the file's
relative path, so the same `--seed` + same `--max-content-size` always
yield byte-identical libraries.

## Architecture

The generator is built around three swappable abstractions:

- **`TitleSource`** — supplies movie titles. The default
  `CuratedTitleSource` mixes word pools and hand-crafted titles. The
  protocol leaves room for other sources without touching anything else.
- **`NamingConvention`** — format-specific: turns a logical movie into
  directory and file names. Currently only `PlexNamingConvention`.
- **`LibraryStructure`** — orthogonal to format: decides the parent path
  of each movie directory. Currently only `FlatLibraryStructure`.

Generation is two-phase: `build_manifest()` produces a format-neutral
description, `materialize()` writes the actual filesystem layout. The
manifest can be saved, loaded, and diffed independently of any concrete
layout.

## License

BSD-3-Clause. See `LICENSE`.
