From b1d2d958eebfb5cb13cfbeae2d66a8ef977ed249 Mon Sep 17 00:00:00 2001 From: OlteanuRares Date: Wed, 22 Jul 2026 10:13:07 +0300 Subject: [PATCH] OCTO-11510 Split monolithic pycaption/sami.py into pycaption/sami/ package (constants, parser, reader, writer). Emit VTT as class attribute instead of leaking into inline CSS, add text-align from Layout alignment, produce valid stylesheet rules for VTT class styles, filter non-CSS keys, silently drop writing direction. Fix rules-dict mutation in _recreate_style_block, inline dead hooks, add docstrings. --- docs/changelog.rst | 8 + pycaption/sami.py | 809 ---------------------------------- pycaption/sami/__init__.py | 4 + pycaption/sami/constants.py | 23 + pycaption/sami/parser.py | 179 ++++++++ pycaption/sami/reader.py | 314 +++++++++++++ pycaption/sami/writer.py | 267 +++++++++++ tests/test_sami_conversion.py | 98 +++- 8 files changed, 889 insertions(+), 813 deletions(-) delete mode 100644 pycaption/sami.py create mode 100644 pycaption/sami/__init__.py create mode 100644 pycaption/sami/constants.py create mode 100644 pycaption/sami/parser.py create mode 100644 pycaption/sami/reader.py create mode 100644 pycaption/sami/writer.py diff --git a/docs/changelog.rst b/docs/changelog.rst index a2f5de41..ff2013d9 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -22,6 +22,14 @@ Changelog - Split pycaption/dfxp/ into constants.py, reader.py, writer.py (same pattern as scc/ and webvtt/). Public API unchanged — ``__init__.py`` re-exports all symbols. + - SAMI writer: align with WebVTT reader's structured output — emit + ``classes`` as ``class=`` attribute (not inline CSS), emit text-align + from Layout, produce valid CSS in stylesheet for VTT class styles, + filter non-CSS keys (webvtt_positioning, writing_direction), silently + drop writing direction (SAMI has no writing-mode). + - Split pycaption/sami.py into pycaption/sami/ package. Public API + unchanged. Reader: inline dead hooks, extract helpers, add docstrings. + Writer: fix rules-dict mutation, remove dead ``_encode``, staticmethods. 2.2.28 ^^^^^^ diff --git a/pycaption/sami.py b/pycaption/sami.py deleted file mode 100644 index 078acb71..00000000 --- a/pycaption/sami.py +++ /dev/null @@ -1,809 +0,0 @@ -""" -The classes in this module handle SAMI reading and writing. It supports several -CSS attributes, some of which are handled as positioning settings (and applied -to Layout objects) and others as simple styling (applied to legacy style nodes). - -The following attributes are handled as positioning: - - 'text-align' # Converted to Alignment - 'margin-top' - 'margin-right' - 'margin-bottom' - 'margin-left' - -OBS: - * Margins are converted to Padding - * Margins defined inline are not supported - TODO: Add support for inline margins - -Any other CSS the BeautifulSoup library manages to parse is handled as simple -styling and applied to style nodes. However, apparently only these are actually -used by writers on conversion: - - 'font-family' - 'font-size' - 'font-style' - 'color' -OBS: - * Other parameters are preserved, but not if they're specified inline. - TODO: - Make this less confusing. Confirm whether these really are the only - supported styling attributes and make it more clear, perhaps by listing - them in constants in the beginning of the file and using them to filter - out unneeded attributes either everywhere in the code or not at all, but - most importantly regardless of whether they're defined inline or not, - because this is irrelevant. - -""" -import re -from collections import deque -from copy import deepcopy -from html.entities import name2codepoint -from html.parser import HTMLParser -from logging import FATAL -from xml.dom import SyntaxErr -from xml.sax.saxutils import escape - -from bs4 import BeautifulSoup, NavigableString -from cssutils import css as cssutils_css -from cssutils import log, parseString - -from .base import ( - DEFAULT_LANGUAGE_CODE, - BaseReader, - BaseWriter, - Caption, - CaptionList, - CaptionNode, - CaptionSet, -) -from .exceptions import ( - CaptionReadNoCaptions, - CaptionReadSyntaxError, - CaptionReadTimingError, - InvalidInputError, -) -from .geometry import Alignment, Layout, Padding, Size - -# change cssutils default logging -log.setLevel(FATAL) - -SAMI_BASE_MARKUP = """ - - -