Skip to main content

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 .txt play files into structured JSON.
  • Assemble canonical JSON documents into normalised .txt output.
  • Read and validate existing canonical .json documents.
  • 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-parser command line interface.

Supported inputs

  • Raw .txt play files.
  • Canonical .json documents 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

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

play_parser-1.1.0.tar.gz (4.4 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

play_parser-1.1.0-py3-none-any.whl (57.2 kB view details)

Uploaded Python 3

File details

Details for the file play_parser-1.1.0.tar.gz.

File metadata

  • Download URL: play_parser-1.1.0.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

Hashes for play_parser-1.1.0.tar.gz
Algorithm Hash digest
SHA256 1fed83434e24f79b71911648956bc679303eaf2b7dd9f462ca05c3d95d8d444e
MD5 c15955e9d0ac7ef47cd1a680c8b12354
BLAKE2b-256 9d69158da2f41de1c3e5c3b4824bbbe7161ec2529358a94fe2c9bfa7e5d622c1

See more details on using hashes here.

File details

Details for the file play_parser-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: play_parser-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 57.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for play_parser-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1617668a6fb6fc6a1c72c2361a6efc818a8eef1473fb6c581088f870a9c720a6
MD5 cf64e4819e6ec500c3ca8aff5563997f
BLAKE2b-256 afcd7ed6812cf1ed02215ac1740a5c73d7fe1adf1b77bc772406c4bc906fb1d5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page