Skip to main content

Parse dramatic play text into ordered dramatic events.

Project description

play-parser

play-parser parses English theatrical play text into a canonical JSON document and assembles canonical documents back into normalised play text.

Play Parser currently supports English structural headings only, such as ACT I and SCENE II.

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.
  • Use the production rule-based parser by default, with an experimental weighted FSM/Viterbi parser available for comparison and research.
  • 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()
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 PlayParser

text = "ACT I\n\nSCENE I.\n\nHAMLET: Who's there?"
play = PlayParser.create("rule").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, profile="colon_inline", source_name="Hamlet.txt")

Experimental 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 rule-based parser is the default and recommended parser. The FSM parser is experimental: it is a real separate parser entry point, not a wrapper around the rule parser, and uses a play-specific weighted finite-state model backed by a standalone Viterbi/beam decoder. Both parser implementations are tested against the same bundled 234-play English-focused regression corpus.

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 \
  --profile colon_inline \
  --json-output Hamlet.json \
  --text-output Hamlet.canonical.txt

Run the experimental 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 234 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, English act/scene numbering with digits, words and Roman numerals, 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, line-numbered dialogue, verse continuations, PDF-style wrapping artefacts, OCR noise, cast-list ambiguity, subtitle/WebVTT/SRT fragments, markdown/web extraction artefacts, and classical/verse conventions. Both the default rule-based parser and the experimental FSM parser are tested against the same English-focused corpus.

Public API

Stable top-level imports:

from play_parser import (
    Play,
    PlayIngestor,
    PlayParser,
    SimplePlayParser,
    RuleBasedPlayParser,
    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.2.2.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.2.2-py3-none-any.whl (68.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: play_parser-1.2.2.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.2.2.tar.gz
Algorithm Hash digest
SHA256 b495f8b77c71bed6a05c30d445eb47c4a559fbf0d9f3c33719c8a18e54eccc67
MD5 55fea33439d7f2e94e6b491fd5f4fcbd
BLAKE2b-256 60a99388d54dc1330af9ea71c123904855431e702c8ef90a8afb7c6c5acf6138

See more details on using hashes here.

File details

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

File metadata

  • Download URL: play_parser-1.2.2-py3-none-any.whl
  • Upload date:
  • Size: 68.0 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.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 345596aa5867eef6056093a113b98a25ac7dd7e0b855c82513658701fcc67958
MD5 3b12125881505de64209b559c4dce092
BLAKE2b-256 d16eaba340587cd00ee124376e5abbfbf70d13dc431c636db39b66c350bf4fec

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