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.1.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.1-py3-none-any.whl (57.1 kB view details)

Uploaded Python 3

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

Hashes for play_parser-1.1.1.tar.gz
Algorithm Hash digest
SHA256 d097f84d788436cd238484ed1a2f15f06e4695148650a478d7fc3ee62a9c68f2
MD5 288114d2326fd30a7fe441599f0a17e6
BLAKE2b-256 7fa472c57877d13672cae02397a96f35e83480e17b767050c1af8d301f6e4515

See more details on using hashes here.

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

Hashes for play_parser-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a24cb71c4c74b9180397f14533b05ae186b6c2bd8ea63fa0225af1e091211647
MD5 904fcb9b188985a354a455f3fe1c9b88
BLAKE2b-256 68ad647f34006154d8b8a4c1a1ac3226cbe5184bf9dd28ebce48ed6668b21985

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