Parse dramatic play text into ordered dramatic events.
Project description
play-parser
play-parser parses theatrical play text into a canonical JSON document and assembles canonical documents back into normalised play text.
Canonical text uses a stable output format. For example, speech labels are emitted in colon form such as Hamlet: ..., even when the source text used another supported layout.
Features
- Parse raw
.txtplay files into structured JSON. - Assemble canonical JSON documents into normalised
.txtoutput. - Read and validate existing canonical
.jsondocuments. - Keep ingestion, parsing, and domain access separate.
- Choose between the production simple parser and the weighted FSM/Viterbi parser.
- Preserve speeches, stage directions, acts, scenes, metadata, characters, and document statistics.
- Use the package from Python or through the
play-parsercommand line interface.
Supported inputs
- Raw
.txtplay files. - Canonical
.jsondocuments produced by this package.
The package does not parse PDFs, DOCX files, HTML pages, scans, images, or audio directly. Convert those sources to text first.
Installation
pip install play-parser
Python quick start
Recommended explicit pipeline:
from play_parser import PlayIngestor, PlayParser
ingestor = PlayIngestor("Hamlet.txt")
parser = PlayParser.create("simple")
play = parser.parse(ingestor.data, profile="colon_inline", source_name=ingestor.source_name)
print(play.title)
print(play.author)
print(len(play.acts))
print(len(play.scenes))
print(len(play.characters))
print(len(play.speeches))
play.save_json("Hamlet.json")
play.save_text("Hamlet.canonical.txt")
Equivalent direct parser usage:
from play_parser import SimplePlayParser
text = "ACT I\n\nSCENE I.\n\nHAMLET: Who's there?"
play = SimplePlayParser().parse(text, profile="colon_inline", source_name="Hamlet.txt")
Convenience domain usage:
from play_parser import Play
text = "ACT I\n\nSCENE I.\n\nHAMLET: Who's there?"
play = Play(text, method="simple", profile="colon_inline", source_name="Hamlet.txt")
Weighted FSM parser:
from play_parser import FSMPlayParser
play = FSMPlayParser().parse(text, profile="colon_inline", source_name="Hamlet.txt")
# The default beam is greedy; use a wider beam for delayed decisions.
play = FSMPlayParser(beam_width=2).parse(text, profile="colon_inline")
The FSM parser is a real separate parser entry point, not a wrapper around the simple parser. It uses a play-specific weighted finite-state model backed by a standalone Viterbi/beam decoder. The included simple and FSM corpus tests currently match a bundled 250-play regression corpus covering multiple stage-text formats. The scoring model remains explicit and tunable as more real-world plays are added.
Assemble a canonical document:
from play_parser import assemble_play_text
canonical_text = assemble_play_text(play.as_dict())
Command line usage
Show help and version information:
play-parser --help
play-parser --version
Parse one file with the production parser:
play-parser parse Hamlet.txt \
--method simple \
--profile colon_inline \
--json-output Hamlet.json \
--text-output Hamlet.canonical.txt
Run the weighted FSM parser:
play-parser parse Hamlet.txt --method fsm --beam-width 2 --json-output Hamlet.fsm.json
Parse a folder recursively:
play-parser parse \
--input-root data/<play name> \
--recursive \
--profile colon_inline \
--json-output-root data/<play name>/optimal.json/generated
Assemble canonical JSON files into text:
play-parser assemble \
--input-root data/<play name>/optimal.json/generated \
--recursive \
--output-root data/<play name>/canonical
Regression corpus
The repository includes 250 sample plays with checked optimal.json snapshots. The corpus covers colon-inline dialogue, dot-inline dialogue, dot-block dialogue, bare speaker blocks, screenplay sluglines, radio/SFX cues, cast-list preambles, act/scene numbering with digits, words and Roman numerals, multilingual speaker names, lowercase speaker labels, false-positive ACT/SCENE dialogue, page-header artefacts, no-dialogue physical scenes, mixed parenthetical cues, fixed-width and tabular dialogue, dash-separated dialogue, screenplay character blocks, foreign act/scene headings, line-numbered dialogue, verse continuations, PDF-style wrapping artefacts, OCR noise, cast-list ambiguity, subtitle/WebVTT/SRT fragments, markdown/web extraction artefacts, classical/verse conventions, and multilingual act/scene labels. Both the simple parser and FSM parser are tested against the same corpus.
Public API
Stable top-level imports:
from play_parser import (
Play,
PlayIngestor,
PlayParser,
SimplePlayParser,
FSMPlayParser,
assemble_play_text,
get_format_profile,
list_format_profiles,
load_format_profile_config,
load_format_profile_file,
validate_play_document,
)
Domain classes such as Act, Scene, Speech, Character, Monologue, and Dialogue are also available from the top-level package.
Format profiles
Built-in profiles are available through list_format_profiles() and can be passed to a parser or the CLI by name.
from play_parser import list_format_profiles
print(list_format_profiles())
See docs/FORMAT_PROFILES.md for the profile schema and examples.
Documentation
docs/API.md: Python API and CLI profile usage.docs/JSON_SCHEMA.md: canonical JSON document format.docs/FORMAT_PROFILES.md: built-in and custom format profiles.
Development
Install development dependencies:
python -m pip install -e .[dev]
Run local checks:
python -m ruff check .
python -m ruff format --check .
python -m pytest
python -m build
python -m twine check dist/*
Release steps are documented in RELEASE.md.
Licence
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file play_parser-1.1.1.tar.gz.
File metadata
- Download URL: play_parser-1.1.1.tar.gz
- Upload date:
- Size: 4.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d097f84d788436cd238484ed1a2f15f06e4695148650a478d7fc3ee62a9c68f2
|
|
| MD5 |
288114d2326fd30a7fe441599f0a17e6
|
|
| BLAKE2b-256 |
7fa472c57877d13672cae02397a96f35e83480e17b767050c1af8d301f6e4515
|
File details
Details for the file play_parser-1.1.1-py3-none-any.whl.
File metadata
- Download URL: play_parser-1.1.1-py3-none-any.whl
- Upload date:
- Size: 57.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a24cb71c4c74b9180397f14533b05ae186b6c2bd8ea63fa0225af1e091211647
|
|
| MD5 |
904fcb9b188985a354a455f3fe1c9b88
|
|
| BLAKE2b-256 |
68ad647f34006154d8b8a4c1a1ac3226cbe5184bf9dd28ebce48ed6668b21985
|