aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Vilcans <martin@librador.com>2011-11-10 23:33:02 +0100
committerMartin Vilcans <martin@librador.com>2011-11-10 23:53:34 +0100
commit083800d933041f7a35cb19011d68d1e51c7f8b9f (patch)
treed2c81877c8c31c1b985ddf9e1ff5ff16a31ee998
parenta7f8938b10877ff207688b3ff02f62c55e6c1266 (diff)
downloadscreenplain-083800d933041f7a35cb19011d68d1e51c7f8b9f.tar.gz
Made RichString non-hierarchical (simpler).
Also: FDX output should have correct line breaks now.
-rw-r--r--screenplain/export/fdx.py61
-rw-r--r--screenplain/richstring.py281
-rw-r--r--tests/fdx_test.py43
-rw-r--r--tests/richstring_test.py96
-rw-r--r--tests/spmd_test.py63
5 files changed, 338 insertions, 206 deletions
diff --git a/screenplain/export/fdx.py b/screenplain/export/fdx.py
index 618d91c..937963d 100644
--- a/screenplain/export/fdx.py
+++ b/screenplain/export/fdx.py
@@ -1,7 +1,8 @@
from xml.sax.saxutils import escape
from screenplain.types import *
-from screenplain.richstring import RichString, Bold, Italic, Underline
+from screenplain.richstring import RichString
+from screenplain.richstring import Bold, Italic, Underline
paragraph_types = {
Slug: 'Scene Heading',
@@ -13,38 +14,34 @@ style_names = {
Bold: 'Bold',
Italic: 'Italic',
Underline: 'Underline',
- RichString: None,
}
def _write_text_element(out, styles, text):
style_value = '+'.join(str(s) for s in styles)
if style_value == '':
- out.write('<Text>%s</Text>' % (escape(text)))
+ out.write(' <Text>%s</Text>\n' % (escape(text)))
else:
- out.write('<Text style="%s">%s</Text>' % (style_value, escape(text)))
+ out.write(' <Text style="%s">%s</Text>\n' %
+ (style_value, escape(text))
+ )
-def write_text(out, rich, parent_styles=None):
- parent_styles = parent_styles or set()
- style_name = style_names[type(rich)]
- if style_name:
- styles = parent_styles | set((style_name,))
- else:
- styles = parent_styles
-
- for segment in rich.segments:
- if isinstance(segment, basestring):
- _write_text_element(out, styles, segment)
+def write_text(out, rich, trailing_linebreak):
+ """Writes <Text style="..."> elements."""
+ for seg_no, segment in enumerate(rich.segments):
+ fdx_styles = set(style_names[n] for n in segment.styles)
+ if trailing_linebreak and seg_no == len(rich.segments) - 1:
+ _write_text_element(out, fdx_styles, segment.text + '\n')
else:
- write_text(out, segment, styles)
-
+ _write_text_element(out, fdx_styles, segment.text)
def write_paragraph(out, para_type, lines):
- out.write('<Paragraph Type="%s">' % para_type)
- for line in lines:
- write_text(out, line)
- out.write('</Paragraph>')
+ out.write(' <Paragraph Type="%s">\n' % para_type)
+ last_line_no = len(lines) - 1
+ for line_no, line in enumerate(lines):
+ write_text(out, line, line_no != last_line_no)
+ out.write(' </Paragraph>\n')
def write_dialog(out, dialog):
@@ -57,18 +54,25 @@ def write_dialog(out, dialog):
def write_dual_dialog(out, dual):
- out.write('<Paragraph><DualDialogue>')
+ out.write(
+ ' <Paragraph>\n'
+ ' <DualDialogue>\n'
+ )
write_dialog(out, dual.left)
write_dialog(out, dual.right)
- out.write('</DualDialogue></Paragraph>')
+ out.write(
+ ' </DualDialogue>\n'
+ ' </Paragraph>\n'
+ )
def to_fdx(screenplay, out):
out.write(
- '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>'
- '<FinalDraft DocumentType="Script" Template="No" Version="1">'
- '<Content>'
+ '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n'
+ '<FinalDraft DocumentType="Script" Template="No" Version="1">\n'
+ '\n'
+ ' <Content>\n'
)
for para in screenplay:
@@ -79,4 +83,7 @@ def to_fdx(screenplay, out):
else:
para_type = paragraph_types[type(para)]
write_paragraph(out, para_type, para.lines)
- out.write('</Content></FinalDraft>\n')
+ out.write(
+ ' </Content>\n'
+ '</FinalDraft>\n'
+ )
diff --git a/screenplain/richstring.py b/screenplain/richstring.py
index 54b5794..ee8332a 100644
--- a/screenplain/richstring.py
+++ b/screenplain/richstring.py
@@ -1,122 +1,174 @@
import re
import cgi
-_emphasis = re.compile(
- r'(?:'
- r'(\*\*)' # two stars
- r'(?=\S)' # must not be followed by space
- r'(.+?[*_]*)' # inside text
- r'(?<=\S)\*\*' # finishing with two stars
- r'|'
- r'(\*)' # one star
- r'(?=\S)' # must not be followed by space
- r'(.+)' # inside text
- r'(?<=\S)\*' # finishing with one star
- r'(?!\*)' # must not be followed by star
- r'|'
- r'(_)' # underline
- r'(?=\S)' # must not be followed by space
- r'([^_]+)' # inside text
- r'(?<=\S)_' # finishing with underline
- r')'
-)
+_magic_re = re.compile(u'[\ue700-\ue705]')
class RichString(object):
- def __init__(self, *segments):
- self.segments = segments
+ """A sequence of segments where each segment can have its own style."""
- def to_html(self):
- result = ''
- for segment in self.segments:
- if isinstance(segment, basestring):
- result += cgi.escape(segment)
- else:
- result += segment.to_html()
- return result
-
- def to_plain(self):
- result = ''
- for segment in self.segments:
- if isinstance(segment, basestring):
- result += segment
- else:
- result += segment.to_plain()
- return result
-
- def startswith(self, prefix):
- return self.to_plain().startswith(prefix)
-
- def endswith(self, prefix):
- return self.to_plain().endswith(prefix)
-
- def __unicode__(self):
- return self.to_html()
+ def __init__(self, *segments):
+ self.segments = tuple(segments)
def __repr__(self):
- return '%s(%s)' % (
- self.__class__.__name__,
- ', '.join(repr(s) for s in self.segments)
- )
+ return ' + '.join(repr(s) for s in self.segments)
+
+ def startswith(self, string):
+ """Checks if the first segment in this string starts with a
+ specific string.
+
+ """
+ if '' == string:
+ return True
+ if not self.segments:
+ return False
+ return self.segments[0].text.startswith(string)
+
+ def endswith(self, string):
+ """Checks if the last segment in this string starts with a
+ specific string.
+
+ """
+ if '' == string:
+ return True
+ if not self.segments:
+ return False
+ return self.segments[-1].text.endswith(string)
+
+ def to_html(self):
+ return ''.join(seg.to_html() for seg in self.segments)
def __eq__(self, other):
- if isinstance(other, basestring):
- return self.to_plain() == other
return (
- self.__class__ == other.__class__ and
+ type(self) == type(other) and
self.segments == other.segments
)
def __ne__(self, other):
return (
- self.__class__ != other.__class__ or
+ type(self) != type(other) or
self.segments != other.segments
)
+ def __add__(self, other):
+ if hasattr(other, 'segments'):
+ return RichString(*(self.segments + other.segments))
+ else:
+ raise ValueError('Concatenating requires RichString')
-class Italic(RichString):
- def to_html(self):
- return '<em>' + super(Italic, self).to_html() + '</em>'
+class Segment(object):
+ """A piece of a rich string. Has a set of styles."""
+ def __init__(self, text, styles):
+ """
+ Creates a segment with a set of styles.
+ text is the raw text string, and
+ styles is a set of Style subclasses"""
+ self.styles = set(styles)
+ self.text = text
-class Bold(RichString):
- def to_html(self):
- return '<strong>' + super(Bold, self).to_html() + '</strong>'
+ def __repr__(self):
+ return '(%s)(%r)' % (
+ '+'.join(
+ style.name() for style in self.styles
+ ) or 'plain',
+ self.text
+ )
+ def __eq__(self, other):
+ return self.text == other.text and self.styles == other.styles
+
+ def __ne__(self, other):
+ return self.text != other.text or self.styles != other.styles
-class Underline(RichString):
def to_html(self):
- return '<u>' + super(Underline, self).to_html() + '</u>'
+ ordered_styles = list(self.styles)
+ return (
+ ''.join(style.start_html for style in ordered_styles) +
+ cgi.escape(self.text) +
+ ''.join(style.end_html for style in reversed(ordered_styles))
+ )
-def _parse(source):
- segments = []
+class Style(object):
+ """Abstract base class for styles"""
- scanner = _emphasis.scanner(source)
- pos = 0
- while pos != len(source):
- match = scanner.search()
- if not match:
- segments.append(source[pos:])
- break
- if match.start() != pos:
- segments.append(source[pos:match.start()])
-
- (
- two_stars, two_stars_text,
- one_star, one_star_text,
- underline, underline_text
- ) = match.groups()
-
- if two_stars:
- segments.append(Bold(*_parse(two_stars_text)))
- elif one_star:
- segments.append(Italic(*_parse(one_star_text)))
- else:
- segments.append(Underline(*_parse(underline_text)))
- pos = match.end()
+ start_magic = ''
+ end_magic = ''
+ start_html = ''
+ end_html = ''
+
+ @classmethod
+ def name(cls):
+ return cls.__name__.lower()
+
+
+class Italic(Style):
- return segments
+ parse_re = re.compile(
+ r'\*' # one star
+ r'(?=\S)' # must not be followed by space
+ r'(.+)' # inside text
+ r'(?<=\S)\*' # finishing with one star
+ r'(?!\*)' # must not be followed by star
+ )
+
+ start_magic = u'\ue700'
+ end_magic = u'\ue701'
+
+ start_html = '<em>'
+ end_html = '</em>'
+
+
+class Bold(Style):
+
+ parse_re = re.compile(
+ r'\*\*' # two stars
+ r'(?=\S)' # must not be followed by space
+ r'(.+?[*_]*)' # inside text
+ r'(?<=\S)\*\*' # finishing with two stars
+ )
+
+ start_magic = u'\ue702'
+ end_magic = u'\ue703'
+
+ start_html = '<strong>'
+ end_html = '</strong>'
+
+
+class Underline(Style):
+
+ parse_re = re.compile(
+ r'_' # underline
+ r'(?=\S)' # must not be followed by space
+ r'([^_]+)' # inside text
+ r'(?<=\S)_' # finishing with underline
+ )
+
+ start_magic = u'\ue704'
+ end_magic = u'\ue705'
+
+ start_html = '<u>' # TODO: use an actual html5 tag
+ end_html = '</u>'
+
+
+class _CreateStyledString(object):
+ """Function object that creates a RichString object
+ with a single segment with a specified style.
+ """
+ def __init__(self, styles):
+ self.styles = styles
+
+ def __call__(self, text):
+ return RichString(Segment(text, self.styles))
+
+ def __add__(self, other):
+ return _CreateStyledString(self.styles.union(other.styles))
+
+plain = _CreateStyledString(set())
+bold = _CreateStyledString(set((Bold,)))
+italic = _CreateStyledString(set((Italic,)))
+underline = _CreateStyledString((Underline,))
def parse_emphasis(source):
@@ -124,12 +176,49 @@ def parse_emphasis(source):
and returns a RichString object.
>>> parse_emphasis(u'**hello**')
- Bold(u'hello')
+ (bold)(u'hello')
>>> parse_emphasis(u'plain')
- RichString(u'plain')
+ (plain)(u'plain')
+ >>> parse_emphasis(u'**hello** there')
+ (bold)(u'hello') + (plain)(u' there')
"""
- segments = _parse(source)
- if len(segments) == 1 and isinstance(segments[0], RichString):
- return segments[0]
- else:
- return RichString(*segments)
+ source = Bold.parse_re.sub(
+ Bold.start_magic + r'\1' + Bold.end_magic, source
+ )
+ source = Italic.parse_re.sub(
+ Italic.start_magic + r'\1' + Italic.end_magic, source
+ )
+ source = Underline.parse_re.sub(
+ Underline.start_magic + r'\1' + Underline.end_magic, source
+ )
+
+ styles = set()
+ segments = []
+ pos = 0
+
+ def append(pos, end):
+ if(pos == end):
+ return
+ text = source[pos:end]
+ segments.append(Segment(text, styles))
+
+ for match in _magic_re.finditer(source):
+ end = match.start()
+ append(pos, end)
+ pos = end + 1
+ magic = match.group(0)
+ if magic == Bold.start_magic:
+ styles.add(Bold)
+ elif magic == Bold.end_magic:
+ styles.remove(Bold)
+ elif magic == Italic.start_magic:
+ styles.add(Italic)
+ elif magic == Italic.end_magic:
+ styles.remove(Italic)
+ elif magic == Underline.start_magic:
+ styles.add(Underline)
+ elif magic == Underline.end_magic:
+ styles.remove(Underline)
+ append(pos, len(source))
+
+ return RichString(*segments)
diff --git a/tests/fdx_test.py b/tests/fdx_test.py
index 153a0cf..d97782f 100644
--- a/tests/fdx_test.py
+++ b/tests/fdx_test.py
@@ -2,8 +2,7 @@ import unittest2
from StringIO import StringIO
from screenplain.export.fdx import write_text
-
-from screenplain.richstring import RichString, Bold, Italic
+from screenplain.richstring import plain, bold, italic
class OutputTests(unittest2.TestCase):
@@ -12,35 +11,45 @@ class OutputTests(unittest2.TestCase):
self.out = StringIO()
def test_plain_text_should_have_no_style(self):
- write_text(self.out, RichString('hello'))
+ write_text(self.out, plain('hello'), False)
self.assertEqual(
self.out.getvalue(),
- '<Text>hello</Text>'
+ ' <Text>hello</Text>\n'
)
def test_bold_text_should_have_bold_style(self):
- write_text(self.out, Bold('hello'))
+ write_text(self.out, bold('hello'), False)
self.assertEqual(
self.out.getvalue(),
- '<Text style="Bold">hello</Text>'
+ ' <Text style="Bold">hello</Text>\n'
)
def test_sequential_styles(self):
- rich = RichString('plain', Bold('b'), Italic('i'))
- write_text(self.out, rich)
+ rich = plain('plain') + bold('b') + italic('i')
+ write_text(self.out, rich, False)
+ self.assertEqual(
+ self.out.getvalue(),
+ ' <Text>plain</Text>\n'
+ ' <Text style="Bold">b</Text>\n'
+ ' <Text style="Italic">i</Text>\n'
+ )
+
+ def test_several_styles(self):
+ rich = bold('outer') + (bold + italic)('inner') + bold('outer')
+ write_text(self.out, rich, False)
self.assertEqual(
self.out.getvalue(),
- '<Text>plain</Text>'
- '<Text style="Bold">b</Text>'
- '<Text style="Italic">i</Text>'
+ ' <Text style="Bold">outer</Text>\n'
+ ' <Text style="Bold+Italic">inner</Text>\n'
+ ' <Text style="Bold">outer</Text>\n'
)
- def test_nested_styles(self):
- rich = Bold('outer', Italic('inner'), 'outer')
- write_text(self.out, rich)
+ def test_write_text_adds_line_break_if_requested(self):
+ rich = bold('outer') + (bold + italic)('inner') + bold('outer')
+ write_text(self.out, rich, True)
self.assertEqual(
self.out.getvalue(),
- '<Text style="Bold">outer</Text>'
- '<Text style="Bold+Italic">inner</Text>'
- '<Text style="Bold">outer</Text>'
+ ' <Text style="Bold">outer</Text>\n'
+ ' <Text style="Bold+Italic">inner</Text>\n'
+ ' <Text style="Bold">outer\n</Text>\n' # note newline
)
diff --git a/tests/richstring_test.py b/tests/richstring_test.py
index b442f90..c79981d 100644
--- a/tests/richstring_test.py
+++ b/tests/richstring_test.py
@@ -1,128 +1,154 @@
import unittest2
-from screenplain.richstring import RichString, Bold, Italic, Underline
+from screenplain.richstring import (
+ RichString, Segment,
+ Bold, Italic,
+ plain, bold, italic, underline
+)
from screenplain.richstring import parse_emphasis
from screenplain.types import Slug, Action, Dialog, DualDialog, Transition
+class LowLevelRichStringTests(unittest2.TestCase):
+
+ def test_plain_string_has_one_single_segment(self):
+ s = RichString(plain('hello'))
+ self.assertEqual((plain('hello'),), s.segments)
+
+
class RichStringOperatorTests(unittest2.TestCase):
def test_repr(self):
- s = RichString(Bold('Hello'), ' there ', Bold('folks'))
+ s = bold('Hello') + plain(' there ') + bold('folks')
self.assertEquals(
- "RichString(Bold('Hello'), ' there ', Bold('folks'))",
+ "(bold)('Hello') + (plain)(' there ') + (bold)('folks')",
repr(s)
)
def test_eq(self):
- self.assertEquals(Bold('Hello'), Bold('Hello'))
- self.assertNotEquals(Bold('Hello'), Bold('Foo'))
- self.assertNotEquals('Hello', Bold('Hello'))
+ self.assertEquals(bold('Hello'), bold('Hello'))
+ self.assertNotEquals(bold('Hello'), bold('Foo'))
+ self.assertNotEquals(plain('Hello'), bold('Hello'))
+
+ def test_ne(self):
+ self.assertFalse(bold('Hello') != bold('Hello'))
+
+ def test_concatenating_two_richstrings(self):
+ expected = RichString(Segment('hello', ()), Segment(' there', (Bold,)))
+ s1 = plain('hello')
+ s2 = bold(' there')
+ result = s1 + s2
+ self.assertEquals(expected, result)
+
+
+class StyleGeneratorTests(unittest2.TestCase):
+
+ def test_bold_function_creates_bold_richstring(self):
self.assertEquals(
- Bold('a', Italic('b'), 'c'),
- Bold('a', Italic('b'), 'c')
- )
- self.assertNotEquals(
- Bold('a', Italic('b'), 'c'),
- Bold('a', Italic('b'), 'd')
+ RichString(Segment('a', (Bold,))),
+ bold('a')
)
- def test_ne(self):
- self.assertFalse(Bold('Hello') != Bold('Hello'))
+ def test_adding_functions(self):
+ self.assertEquals(
+ RichString(Segment('a', (Bold, Italic))),
+ (bold + italic)('a')
+ )
class RichStringTests(unittest2.TestCase):
def test_plain_to_html(self):
- self.assertEquals('hello', RichString('hello').to_html())
+ self.assertEquals('hello', RichString(plain('hello')).to_html())
def test_to_html(self):
s = RichString(
- Bold('bold'),
- ' normal ',
- Italic('italic'),
- Underline('wonderline')
+ bold('bold'),
+ plain(' normal '),
+ italic('italic'),
+ underline('wonderline')
)
self.assertEquals(
'<strong>bold</strong> normal <em>italic</em><u>wonderline</u>',
s.to_html()
)
-
class ParseEmphasisTests(unittest2.TestCase):
def test_parse_without_emphasis(self):
- self.assertEquals(RichString('Hello'), parse_emphasis('Hello'),
- 'Expected parse_emphasis to return a string')
+ self.assertEquals(plain('Hello'), parse_emphasis('Hello'),
+ 'Expected parse_emphasis to return a plain string')
def test_parse_bold(self):
self.assertEquals(
parse_emphasis('**Hello**'),
- Bold('Hello')
+ bold('Hello')
)
def test_parse_pre_and_postfix_and_bold(self):
self.assertEquals(
parse_emphasis('pre**Hello**post'),
- RichString('pre', Bold('Hello'), 'post'),
+ plain('pre') + bold('Hello') + plain('post')
)
def test_parse_multiple_bold(self):
self.assertEquals(
parse_emphasis('x**Hello** **there**'),
- RichString('x', Bold('Hello'), ' ', Bold('there'))
+ plain('x') + bold('Hello') + plain(' ') + bold('there')
)
def test_parse_adjacent_bold(self):
self.assertEquals(
- parse_emphasis('**123****456**'),
- RichString(Bold('123**'), '456**')
+ parse_emphasis('**123**456**'),
+ bold('123') + plain('456**')
)
def test_italic(self):
self.assertEquals(
parse_emphasis('*Italian style*'),
- Italic('Italian style')
+ italic('Italian style')
)
def test_bold_inside_italic(self):
self.assertEquals(
parse_emphasis('*Swedish **style** rules*'),
- Italic('Swedish ', Bold('style'), ' rules')
+ italic('Swedish ') + (bold + italic)('style') + italic(' rules')
)
def test_italic_inside_bold(self):
self.assertEquals(
parse_emphasis('**Swedish *style* rules**'),
- Bold('Swedish ', Italic('style'), ' rules')
+ bold('Swedish ') + (bold + italic)('style') + bold(' rules')
)
def test_italic_and_bold(self):
self.assertEquals(
parse_emphasis('***really strong***'),
- Bold(Italic('really strong'))
+ (bold + italic)('really strong')
)
@unittest2.expectedFailure
def test_additional_star(self):
self.assertEquals(
parse_emphasis('*foo* bar* baz'),
- RichString(Italic('foo'), ' bar* baz')
+ italic('foo') + plain(' bar* baz')
)
def test_underline(self):
self.assertEquals(
parse_emphasis('_hello_'),
- Underline('hello')
+ underline('hello')
)
def test_bold_inside_underline(self):
self.assertEquals(
parse_emphasis('_**hello**_'),
- Underline(Bold('hello'))
+ (bold + underline)('hello')
)
def test_overlapping_underscore_and_italic(self):
+ # It's unclear what result to expect in this case.
+ # This is one way of interpreting it
self.assertEquals(
parse_emphasis('_*he_llo*'),
- RichString(Underline('*he'), 'llo*')
+ (italic + underline)('he') + italic('llo')
)
diff --git a/tests/spmd_test.py b/tests/spmd_test.py
index 1f5c0f5..fbc7867 100644
--- a/tests/spmd_test.py
+++ b/tests/spmd_test.py
@@ -1,7 +1,7 @@
import unittest2
from screenplain.parsers.spmd import parse
from screenplain.types import Slug, Action, Dialog, DualDialog, Transition
-
+from screenplain.richstring import plain
class ParseTests(unittest2.TestCase):
@@ -28,8 +28,8 @@ class ParseTests(unittest2.TestCase):
self.assertEquals([Dialog, Action], [type(p) for p in paras])
# What looks like a scene headingis parsed as a character name.
# Unexpected perhaps, but that's how I interpreted the spec.
- self.assertEquals('INT. SOMEWHERE - DAY', paras[0].character)
- self.assertEquals(['Some action'], paras[1].lines)
+ self.assertEquals(plain('INT. SOMEWHERE - DAY'), paras[0].character)
+ self.assertEquals([plain('Some action')], paras[1].lines)
def test_action_is_not_a_slug(self):
paras = list(parse([
@@ -57,7 +57,7 @@ class ParseTests(unittest2.TestCase):
self.assertEquals(1, len(paras))
dialog = paras[0]
self.assertEquals(Dialog, type(dialog))
- self.assertEquals('SOME GUY', dialog.character)
+ self.assertEquals(plain('SOME GUY'), dialog.character)
# SPMD would not be able to support a character named "23". We
# might need a syntax to force a character element.
@@ -86,8 +86,14 @@ class ParseTests(unittest2.TestCase):
self.assertEquals(1, len(paras))
dialog = paras[0]
self.assertEqual(2, len(dialog.blocks))
- self.assertEqual((True, '(starting the engine)'), dialog.blocks[0])
- self.assertEqual((False, 'So much for retirement!'), dialog.blocks[1])
+ self.assertEqual(
+ (True, plain('(starting the engine)')),
+ dialog.blocks[0]
+ )
+ self.assertEqual(
+ (False, plain('So much for retirement!')),
+ dialog.blocks[1]
+ )
def test_dual_dialog(self):
paras = list(parse([
@@ -99,10 +105,16 @@ class ParseTests(unittest2.TestCase):
]))
self.assertEquals([DualDialog], [type(p) for p in paras])
dual = paras[0]
- self.assertEquals('BRICK', dual.left.character)
- self.assertEquals([(False, 'Fuck retirement.')], dual.left.blocks)
- self.assertEquals('STEEL', dual.right.character)
- self.assertEquals([(False, 'Fuck retirement!')], dual.right.blocks)
+ self.assertEquals(plain('BRICK'), dual.left.character)
+ self.assertEquals(
+ [(False, plain('Fuck retirement.'))],
+ dual.left.blocks
+ )
+ self.assertEquals(plain('STEEL'), dual.right.character)
+ self.assertEquals(
+ [(False, plain('Fuck retirement!'))],
+ dual.right.blocks
+ )
def test_dual_dialog_with_empty_right_dialog_is_ordinary_dialog(self):
paras = list(parse([
@@ -112,10 +124,10 @@ class ParseTests(unittest2.TestCase):
]))
self.assertEquals([Dialog], [type(p) for p in paras])
dialog = paras[0]
- self.assertEqual('BRICK', dialog.character)
+ self.assertEqual(plain('BRICK'), dialog.character)
self.assertEqual([
- (False, 'Nice retirement.'),
- (False, '||')
+ (False, plain('Nice retirement.')),
+ (False, plain('||'))
], dialog.blocks)
def test_standard_transition(self):
@@ -129,17 +141,6 @@ class ParseTests(unittest2.TestCase):
]))
self.assertEquals([Action, Transition, Slug], [type(p) for p in paras])
- def test_standard_transition(self):
-
- paras = list(parse([
- 'Jack begins to argue vociferously in Vietnamese (?)',
- '',
- 'CUT TO:',
- '',
- "EXT. BRICK'S POOL - DAY",
- ]))
- self.assertEquals([Action, Transition, Slug], [type(p) for p in paras])
-
def test_transition_needs_to_be_upper_case(self):
paras = list(parse([
'Jack begins to argue vociferously in Vietnamese (?)',
@@ -185,9 +186,9 @@ class ParseTests(unittest2.TestCase):
self.assertEquals([Action, Action, Action], [type(p) for p in paras])
self.assertEquals(
[
- "And then there's a long beat.",
- "Longer than is funny.",
- "Long enough to be depressing.",
+ plain("And then there's a long beat."),
+ plain("Longer than is funny."),
+ plain("Long enough to be depressing."),
], paras[1].lines
)
@@ -201,10 +202,10 @@ class ParseTests(unittest2.TestCase):
]))
self.assertEquals([Dialog], [type(p) for p in paras])
self.assertEquals([
- (False, 'O Romeo, Romeo! wherefore art thou Romeo?'),
- (False, 'Deny thy father and refuse thy name;'),
- (False, 'Or, if thou wilt not, be but sworn my love,'),
- (False, "And I'll no longer be a Capulet."),
+ (False, plain('O Romeo, Romeo! wherefore art thou Romeo?')),
+ (False, plain('Deny thy father and refuse thy name;')),
+ (False, plain('Or, if thou wilt not, be but sworn my love,')),
+ (False, plain("And I'll no longer be a Capulet.")),
], paras[0].blocks)
if __name__ == '__main__':