pycaption 2.2.7__tar.gz → 2.2.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. {pycaption-2.2.7/pycaption.egg-info → pycaption-2.2.9}/PKG-INFO +1 -1
  2. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/scc/__init__.py +44 -24
  3. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/scc/constants.py +6 -0
  4. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/scc/specialized_collections.py +56 -33
  5. {pycaption-2.2.7 → pycaption-2.2.9/pycaption.egg-info}/PKG-INFO +1 -1
  6. {pycaption-2.2.7 → pycaption-2.2.9}/setup.py +1 -1
  7. {pycaption-2.2.7 → pycaption-2.2.9}/tests/fixtures/dfxp.py +2 -2
  8. {pycaption-2.2.7 → pycaption-2.2.9}/tests/fixtures/scc.py +4 -2
  9. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_scc.py +37 -31
  10. {pycaption-2.2.7 → pycaption-2.2.9}/LICENSE +0 -0
  11. {pycaption-2.2.7 → pycaption-2.2.9}/MANIFEST.in +0 -0
  12. {pycaption-2.2.7 → pycaption-2.2.9}/README.rst +0 -0
  13. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/__init__.py +0 -0
  14. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/base.py +0 -0
  15. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/dfxp/__init__.py +0 -0
  16. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/dfxp/base.py +0 -0
  17. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/dfxp/extras.py +0 -0
  18. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/english.pickle +0 -0
  19. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/exceptions.py +0 -0
  20. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/geometry.py +0 -0
  21. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/microdvd.py +0 -0
  22. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/sami.py +0 -0
  23. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/scc/state_machines.py +0 -0
  24. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/scc/translator.py +0 -0
  25. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/srt.py +0 -0
  26. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/transcript.py +0 -0
  27. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/utils.py +0 -0
  28. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption/webvtt.py +0 -0
  29. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption.egg-info/SOURCES.txt +0 -0
  30. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption.egg-info/dependency_links.txt +0 -0
  31. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption.egg-info/requires.txt +0 -0
  32. {pycaption-2.2.7 → pycaption-2.2.9}/pycaption.egg-info/top_level.txt +0 -0
  33. {pycaption-2.2.7 → pycaption-2.2.9}/setup.cfg +0 -0
  34. {pycaption-2.2.7 → pycaption-2.2.9}/tests/__init__.py +0 -0
  35. {pycaption-2.2.7 → pycaption-2.2.9}/tests/conftest.py +0 -0
  36. {pycaption-2.2.7 → pycaption-2.2.9}/tests/fixtures/__init__.py +0 -0
  37. {pycaption-2.2.7 → pycaption-2.2.9}/tests/fixtures/microdvd.py +0 -0
  38. {pycaption-2.2.7 → pycaption-2.2.9}/tests/fixtures/sami.py +0 -0
  39. {pycaption-2.2.7 → pycaption-2.2.9}/tests/fixtures/srt.py +0 -0
  40. {pycaption-2.2.7 → pycaption-2.2.9}/tests/fixtures/translated_scc.py +0 -0
  41. {pycaption-2.2.7 → pycaption-2.2.9}/tests/fixtures/webvtt.py +0 -0
  42. {pycaption-2.2.7 → pycaption-2.2.9}/tests/mixins.py +0 -0
  43. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_base.py +0 -0
  44. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_dfxp.py +0 -0
  45. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_dfxp_conversion.py +0 -0
  46. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_dfxp_extras.py +0 -0
  47. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_functions.py +0 -0
  48. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_geometry.py +0 -0
  49. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_microdvd.py +0 -0
  50. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_microdvd_conversion.py +0 -0
  51. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_sami.py +0 -0
  52. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_sami_conversion.py +0 -0
  53. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_scc_conversion.py +0 -0
  54. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_scc_translator.py +0 -0
  55. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_srt.py +0 -0
  56. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_srt_conversion.py +0 -0
  57. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_webvtt.py +0 -0
  58. {pycaption-2.2.7 → pycaption-2.2.9}/tests/test_webvtt_conversion.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pycaption
3
- Version: 2.2.7
3
+ Version: 2.2.9
4
4
  Summary: Closed caption converter
5
5
  Author: Joe Norton
6
6
  Author-email: joey@nortoncrew.com
@@ -308,15 +308,23 @@ class SCCReader(BaseReader):
308
308
 
309
309
  self.time_translator.start_at(parts[0][0])
310
310
 
311
- # loop through each word
312
- for word in parts[0][2].split(' '):
311
+ word_list = parts[0][2].split(' ')
312
+ pacs_are_doubled = len(word_list) > 1 and word_list[0] == word_list[1]
313
+ for idx, word in enumerate(word_list):
313
314
  # ignore empty results or invalid commands
314
315
  word = word.strip()
316
+ previous_is_pac_or_tab = idx > 0 and (
317
+ _is_pac_command(word_list[idx-1]) or word_list[idx-1] in PAC_TAB_OFFSET_COMMANDS
318
+ )
315
319
  if len(word) == 4:
316
- self._translate_word(word)
320
+ self._translate_word(
321
+ word=word,
322
+ previous_is_pac_or_tab=previous_is_pac_or_tab,
323
+ pacs_are_doubled=pacs_are_doubled
324
+ )
317
325
 
318
- def _translate_word(self, word):
319
- if self._handle_double_command(word):
326
+ def _translate_word(self, word, previous_is_pac_or_tab, pacs_are_doubled):
327
+ if self._handle_double_command(word, pacs_are_doubled):
320
328
  # count frames for timing
321
329
  self.time_translator.increment_frames()
322
330
  return
@@ -324,7 +332,7 @@ class SCCReader(BaseReader):
324
332
  # TODO - check that all the positioning commands are here, or use
325
333
  # some other strategy to determine if the word is a command.
326
334
  if word in COMMANDS or _is_pac_command(word):
327
- self._translate_command(word)
335
+ self._translate_command(word=word, previous_is_pac_or_tab=previous_is_pac_or_tab)
328
336
 
329
337
  # second, check if word is a special character
330
338
  elif word in SPECIAL_CHARS:
@@ -340,28 +348,31 @@ class SCCReader(BaseReader):
340
348
  # count frames for timing only after processing a command
341
349
  self.time_translator.increment_frames()
342
350
 
343
- def _handle_double_command(self, word):
351
+ def _handle_double_command(self, word, pacs_are_doubled):
344
352
  # If the caption is to be broadcast, each of the commands are doubled
345
353
  # up for redundancy in case the signal is garbled in transmission.
346
354
  # The decoder is programmed to ignore a second command when it is the
347
355
  # same as the first.
348
- # Also like codes, Special Characters are always doubled up,
356
+ # If we have doubled commands we're skipping also
357
+ # doubled special characters and doubled extended characters
349
358
  # with only one member of each pair being displayed.
350
- if word in COMMANDS or _is_pac_command(word) or word in SPECIAL_CHARS or word in EXTENDED_CHARS:
351
- if word == self.last_command:
352
- self.last_command = ''
353
- return True
359
+ doubled_types = word in COMMANDS or _is_pac_command(word)
360
+ if pacs_are_doubled:
361
+ doubled_types = doubled_types or word in SPECIAL_CHARS or word in EXTENDED_CHARS
362
+
363
+ if doubled_types and word == self.last_command:
364
+ return True
354
365
  # Fix for the <position> <tab offset> <position> <tab offset>
355
366
  # repetition
356
- elif _is_pac_command(word) and word in self.last_command:
357
- self.last_command = ''
367
+ elif _is_pac_command(word) and word in self.last_command:
368
+ self.last_command = ''
369
+ return True
370
+ elif word in PAC_TAB_OFFSET_COMMANDS:
371
+ if _is_pac_command(self.last_command):
372
+ self.last_command += f" {word}"
373
+ return False
374
+ else:
358
375
  return True
359
- elif word in PAC_TAB_OFFSET_COMMANDS:
360
- if _is_pac_command(self.last_command):
361
- self.last_command += f" {word}"
362
- return False
363
- else:
364
- return True
365
376
 
366
377
  self.last_command = word
367
378
  return False
@@ -370,12 +381,18 @@ class SCCReader(BaseReader):
370
381
  self.buffer.add_chars(SPECIAL_CHARS[word])
371
382
 
372
383
  def _translate_extended_char(self, word):
373
- self.buffer.remove_ascii_duplicate(EXTENDED_CHARS[word])
374
-
384
+ """
385
+ Each of the 64 Extended Characters incorporates an automatic BS.
386
+ When an Extended Character is received, the cursor moves to the
387
+ left one column position (unless the Extended Character is the first
388
+ character on a row), erasing any character which may be in that location,
389
+ then displays the Extended Character.
390
+ """
391
+ self.buffer.handle_backspace(word)
375
392
  # add to buffer
376
393
  self.buffer.add_chars(EXTENDED_CHARS[word])
377
394
 
378
- def _translate_command(self, word):
395
+ def _translate_command(self, word, previous_is_pac_or_tab):
379
396
  # if command is pop_up
380
397
  if word == '9420':
381
398
  self.buffer_dict.set_active('pop')
@@ -444,7 +461,10 @@ class SCCReader(BaseReader):
444
461
 
445
462
  # If command is not one of the aforementioned, add it to buffer
446
463
  else:
447
- self.buffer.interpret_command(word)
464
+ self.buffer.interpret_command(
465
+ command=word,
466
+ previous_is_pac_or_tab=previous_is_pac_or_tab
467
+ )
448
468
 
449
469
  def _translate_characters(self, word):
450
470
  # split word into the 2 bytes
@@ -1052,3 +1052,9 @@ MID_ROW_CODES = [
1052
1052
  "91a7", "91a8", "9129", "912a", "91ab", "912c", "91ad",
1053
1053
  "97ae", "972f", "91ae", "912f", "94a8"
1054
1054
  ]
1055
+
1056
+ BACKGROUND_COLOR_CODES = [
1057
+ "1020", "10a1", "10a2", "1023", "10a4", "1025", "1026",
1058
+ "10a7", "10a8", "1029", "102a", "10ab", "102c", "10ad",
1059
+ "10ae", "102f", "97ad"
1060
+ ]
@@ -8,8 +8,8 @@ from ..geometry import (
8
8
  )
9
9
  from .constants import (
10
10
  PAC_BYTES_TO_POSITIONING_MAP, COMMANDS, PAC_TAB_OFFSET_COMMANDS,
11
- MICROSECONDS_PER_CODEWORD, INCONVERTIBLE_TO_ASCII_EXTENDED_CHARS_ASSOCIATION,
12
- MID_ROW_CODES
11
+ MICROSECONDS_PER_CODEWORD, BACKGROUND_COLOR_CODES,
12
+ MID_ROW_CODES, EXTENDED_CHARS, SPECIAL_CHARS
13
13
  )
14
14
 
15
15
  PopOnCue = collections.namedtuple("PopOnCue", "buffer, start, end")
@@ -288,6 +288,8 @@ class InstructionNodeCreator:
288
288
  else:
289
289
  self._collection = collection
290
290
 
291
+ self.last_style = None
292
+
291
293
  self._position_tracer = position_tracker
292
294
 
293
295
  def is_empty(self):
@@ -335,23 +337,33 @@ class InstructionNodeCreator:
335
337
 
336
338
  node.add_chars(*chars)
337
339
 
338
- def interpret_command(self, command):
340
+ def interpret_command(self, command, previous_is_pac_or_tab=False):
339
341
  """Given a command determines whether to turn italics on or off,
340
342
  or to set the positioning
341
343
 
342
344
  This is mostly used to convert from the legacy-style commands
343
345
 
344
346
  :type command: str
347
+ :type previous_is_pac_or_tab: previous command code is for a PAC command
348
+ or a PAC_TAB_OFFSET_COMMANDS
345
349
  """
346
350
  self._update_positioning(command)
347
351
 
348
352
  text = COMMANDS.get(command, '')
349
353
 
350
- if command in MID_ROW_CODES:
351
- for node in self._collection[::-1]:
352
- if node.is_text_node():
353
- node.text += ' '
354
- break
354
+ if command == "94a1":
355
+ self.handle_backspace("94a1")
356
+
357
+ if command in BACKGROUND_COLOR_CODES:
358
+ # Since these codes are optional, they must be preceded
359
+ # with the space character (20h),
360
+ # which will be deleted when the code is applied.
361
+ # ex: 2080 97ad 94a1
362
+ if (
363
+ self._collection[-1].is_text_node() and
364
+ self._collection[-1].text[-1].isspace()
365
+ ):
366
+ self._collection[-1].text = self._collection[-1].text[:-1]
355
367
 
356
368
  if 'italic' in text:
357
369
  if 'end' not in text:
@@ -359,6 +371,7 @@ class InstructionNodeCreator:
359
371
  _InstructionNode.create_italics_style(
360
372
  self._position_tracer.get_current_position())
361
373
  )
374
+ self.last_style = "italics on"
362
375
  else:
363
376
  self._collection.append(
364
377
  _InstructionNode.create_italics_style(
@@ -366,6 +379,18 @@ class InstructionNodeCreator:
366
379
  turn_on=False
367
380
  )
368
381
  )
382
+ self.last_style = "italics off"
383
+
384
+ # mid row code that is not first code on the line
385
+ # (previous node is not a break node)
386
+ if command in MID_ROW_CODES and not previous_is_pac_or_tab:
387
+ if self.last_style == "italics off":
388
+ self.add_chars(' ')
389
+ else:
390
+ for node in self._collection[::-1]:
391
+ if node.is_text_node() and node.text:
392
+ node.text += ' '
393
+ break
369
394
 
370
395
  def _update_positioning(self, command):
371
396
  """Sets the positioning information to use for the next nodes
@@ -419,33 +444,31 @@ class InstructionNodeCreator:
419
444
 
420
445
  return instance
421
446
 
422
- def remove_ascii_duplicate(self, accented_character):
447
+ def handle_backspace(self, word):
423
448
  """
424
- Characters from the Extended Characters list are usually preceded by
425
- their ASCII substitute, in case the decoder is not able to display
426
- the special character.
427
-
428
- This is used to remove the substitute character in order to avoid
429
- displaying both.
430
-
431
- :type accented_character: str
449
+ Move cursor back one position and delete that character
432
450
  """
433
- is_text_node = (
434
- self._collection and
435
- self._collection[-1].is_text_node() and
436
- self._collection[-1].text
437
- )
438
- if is_text_node:
439
- try:
440
- ascii_char = [
441
- unicodedata.normalize('NFD', accented_character)
442
- .encode('ascii', 'strict').decode("utf-8")
443
- ]
444
- except (UnicodeEncodeError, UnicodeDecodeError):
445
- ascii_char = INCONVERTIBLE_TO_ASCII_EXTENDED_CHARS_ASSOCIATION.get(accented_character)
446
-
447
- if ascii_char and self._collection[-1].text[-1] in ascii_char:
448
- self._collection[-1].text = self._collection[-1].text[:-1]
451
+ node = self.get_previous_text_node()
452
+ # in case of no previous text nodes or
453
+ # if the backspace is required while no character
454
+ # do nothing
455
+ if node is None:
456
+ return
457
+ last_char = node.text[-1]
458
+ delete_previous_condition = (
459
+ (word in EXTENDED_CHARS and last_char not in EXTENDED_CHARS.values()) or
460
+ word == "94a1"
461
+ )
462
+ # in case extended char, perform backspace
463
+ # only if the previous character in not also extended
464
+ if delete_previous_condition:
465
+ node.text = node.text[:-1]
466
+
467
+ def get_previous_text_node(self):
468
+ for node in self._collection[::-1]:
469
+ if node.is_text_node() and node.text:
470
+ return node
471
+ return None
449
472
 
450
473
 
451
474
  def _get_layout_from_tuple(position_tuple):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pycaption
3
- Version: 2.2.7
3
+ Version: 2.2.9
4
4
  Summary: Closed caption converter
5
5
  Author: Joe Norton
6
6
  Author-email: joey@nortoncrew.com
@@ -24,7 +24,7 @@ transcript_dependencies = [
24
24
 
25
25
  setup(
26
26
  name='pycaption',
27
- version='2.2.7',
27
+ version='2.2.9',
28
28
  description='Closed caption converter',
29
29
  long_description=open(README_PATH).read(),
30
30
  author='Joe Norton',
@@ -920,10 +920,10 @@ def sample_dfxp_from_scc_output():
920
920
  <region tts:displayAlign="before" tts:origin="40% 53%" tts:textAlign="left" xml:id="r5"/>
921
921
  <region tts:displayAlign="before" tts:origin="70% 17%" tts:textAlign="left" xml:id="r6"/>
922
922
  <region tts:displayAlign="before" tts:origin="20% 35%" tts:textAlign="left" xml:id="r7"/>
923
- <region tts:displayAlign="before" tts:origin="20% 83%" tts:textAlign="left" xml:id="r8"/>
923
+ <region tts:displayAlign="before" tts:origin="25% 83%" tts:textAlign="left" xml:id="r8"/>
924
924
  <region tts:displayAlign="before" tts:origin="70% 11%" tts:textAlign="left" xml:id="r9"/>
925
925
  <region tts:displayAlign="before" tts:origin="40% 41%" tts:textAlign="left" xml:id="r10"/>
926
- <region tts:displayAlign="before" tts:origin="20% 71%" tts:textAlign="left" xml:id="r11"/>
926
+ <region tts:displayAlign="before" tts:origin="25% 71%" tts:textAlign="left" xml:id="r11"/>
927
927
  </layout>
928
928
  </head>
929
929
  <body>
@@ -367,9 +367,11 @@ def sample_scc_duplicate_special_characters():
367
367
  return """\
368
368
  Scenarist_SCC V1.0
369
369
 
370
- 00:23:28;01 9420 91b0 91b0 9131 9131 9132 9132 91b3 91b3 9134 9134 91b5 91b5 91b6 91b6 9137 9137 9138 9138 91b9 91b9 91ba 91ba 913b 913b 91bc 91bc 913d 913d 913e 913e 91bf 91bf 942f
370
+ 00:23:28;01 9420 9420 91b0 91b0 9131 9131 9132 9132 91b3 91b3 9134 9134 91b5 91b5 91b6 91b6 9137 9137 9138 9138 91b9 91b9 91ba 91ba 913b 913b 91bc 91bc 913d 913d 913e 913e 91bf 91bf 942f
371
371
 
372
- 00:53:28;01 9420 91b0 9131 9132 91b3 9134 91b5 91b6 9137 9138 91b9 91ba 913b 91bc 913d 913e 91bf 942f
372
+ 00:33:28;01 9420 91b0 9131 9132 91b3 9134 91b5 91b6 9137 9138 91b9 91ba 913b 91bc 913d 913e 91bf 942f
373
+
374
+ 00:53:28;01 9420 91b0 9131 c1c1 9132 91b3 9134 91b5 91b6 9137 9138 91b9 91ba 913b 91bc c1c1 913d 913e 91bf 942f
373
375
 
374
376
  """
375
377
 
@@ -77,17 +77,15 @@ class TestSCCReader(ReaderTestingMixIn):
77
77
  ((40.0, UnitEnum.PERCENT), (53.0, UnitEnum.PERCENT)),
78
78
  ((70.0, UnitEnum.PERCENT), (17.0, UnitEnum.PERCENT)),
79
79
  ((20.0, UnitEnum.PERCENT), (35.0, UnitEnum.PERCENT)),
80
- ((20.0, UnitEnum.PERCENT), (83.0, UnitEnum.PERCENT)),
80
+ ((25.0, UnitEnum.PERCENT), (83.0, UnitEnum.PERCENT)),
81
81
  ((70.0, UnitEnum.PERCENT), (11.0, UnitEnum.PERCENT)),
82
82
  ((40.0, UnitEnum.PERCENT), (41.0, UnitEnum.PERCENT)),
83
- ((20.0, UnitEnum.PERCENT), (71.0, UnitEnum.PERCENT))
83
+ ((25.0, UnitEnum.PERCENT), (71.0, UnitEnum.PERCENT))
84
84
  ]
85
-
86
85
  actual_positioning = [
87
86
  caption_.layout_info.origin.serialized()
88
87
  for caption_ in captions.get_captions('en-US')
89
88
  ]
90
-
91
89
  assert expected_positioning == actual_positioning
92
90
 
93
91
  def test_tab_offset(self, sample_scc_tab_offset):
@@ -206,11 +204,11 @@ class TestSCCReader(ReaderTestingMixIn):
206
204
 
207
205
  def test_skip_duplicate_tab_offset(self, sample_scc_duplicate_tab_offset):
208
206
  expected_lines = [
209
- '[Radio reporter] ',
210
- 'The I-10 Santa Monica Freeway ',
207
+ '[Radio reporter]',
208
+ 'The I-10 Santa Monica Freeway',
211
209
  'westbound is jammed,',
212
- 'due to a three-car accident ',
213
- 'blocking lanes 1 and 2',
210
+ 'due to a three-car accident',
211
+ 'blocking lanes 1 and 2'
214
212
  ]
215
213
 
216
214
  caption_set = SCCReader().read(sample_scc_duplicate_tab_offset)
@@ -220,12 +218,15 @@ class TestSCCReader(ReaderTestingMixIn):
220
218
  for node in cap_.nodes
221
219
  if node.type_ == CaptionNode.TEXT
222
220
  ]
223
-
224
221
  assert expected_lines == actual_lines
225
222
 
226
223
  def test_skip_duplicate_special_characters(
227
224
  self, sample_scc_duplicate_special_characters):
228
- expected_lines = ['®°½¿™¢£♪à èâêîôû', '®°½¿™¢£♪à èâêîôû']
225
+ expected_lines = [
226
+ '®°½¿™¢£♪à èâêîôû',
227
+ '®°½¿™¢£♪à èâêîôû',
228
+ '®°AA½¿™¢£♪à èâêAAîôû'
229
+ ]
229
230
 
230
231
  caption_set = SCCReader().read(sample_scc_duplicate_special_characters)
231
232
  actual_lines = [
@@ -234,7 +235,6 @@ class TestSCCReader(ReaderTestingMixIn):
234
235
  for node in cap_.nodes
235
236
  if node.type_ == CaptionNode.TEXT
236
237
  ]
237
-
238
238
  assert expected_lines == actual_lines
239
239
 
240
240
  def test_flashing_cue(self, sample_scc_flashing_cue):
@@ -287,7 +287,7 @@ class TestCoverageOnly:
287
287
  '>> IT WAS GOOD TO BE IN TH',
288
288
  "And restore Iowa's land, water",
289
289
  'And wildlife.',
290
- '>> Bike Iowa, your source for',
290
+ '>> Bike Iowa, your source for'
291
291
  ]
292
292
  assert expected_texts == actual_texts
293
293
 
@@ -383,6 +383,9 @@ class TestInterpretableNodeCreator:
383
383
  # 4. to get new opening italic nodes after changing position, if 3
384
384
  # happened
385
385
  # 5. to get a final italic closing node, if one is needed
386
+ # 9120 and 91ae are mid row codes and will add a space
387
+ # 9120 at the start of the following text node
388
+ # 91ae to the end of the previous text node
386
389
  node_creator.interpret_command('9470') # row 15, col 0
387
390
  node_creator.interpret_command('9120') # italics off
388
391
  node_creator.interpret_command('9120') # italics off
@@ -401,7 +404,7 @@ class TestInterpretableNodeCreator:
401
404
  node_creator.add_chars('b')
402
405
  node_creator.interpret_command('91ae') # italics ON again
403
406
  node_creator.add_chars('b')
404
- node_creator.interpret_command('9120') # italics OFF
407
+ node_creator.interpret_command('9120') # italics OFF adds space
405
408
  node_creator.interpret_command('9120') # italics OFF
406
409
 
407
410
  node_creator.interpret_command('1570') # row 6 col 0
@@ -420,32 +423,35 @@ class TestInterpretableNodeCreator:
420
423
  result = list(node_creator)
421
424
 
422
425
  assert result[0].is_text_node()
423
- assert result[1].requires_repositioning()
424
- assert result[2].is_italics_node()
425
- assert result[2].sets_italics_on()
426
+ assert result[1].is_text_node()
427
+ assert result[2].requires_repositioning()
426
428
 
427
- assert result[3].is_text_node()
429
+ assert result[3].is_italics_node()
430
+ assert result[3].sets_italics_on()
428
431
  assert result[4].is_text_node()
429
- assert result[5].is_text_node()
430
-
431
- assert result[6].is_italics_node()
432
- assert result[6].sets_italics_off()
432
+ assert result[5].sets_italics_off()
433
+ assert result[6].is_text_node()
433
434
 
434
- assert result[7].requires_repositioning()
435
- assert result[8].is_text_node()
435
+ assert result[7].is_text_node()
436
+ assert result[8].sets_italics_on()
436
437
 
437
- assert result[9].requires_repositioning()
438
- assert result[10].is_italics_node()
439
- assert result[10].sets_italics_on()
438
+ assert result[9].is_text_node()
439
+ assert result[10].is_text_node()
440
440
 
441
- assert result[11].is_text_node()
442
- assert result[12].is_explicit_break()
441
+ assert result[11].sets_italics_off()
442
+ assert result[12].is_text_node()
443
443
  assert result[13].is_text_node()
444
- assert result[14].is_explicit_break()
444
+ assert result[14].requires_repositioning()
445
445
  assert result[15].is_text_node()
446
446
 
447
- assert result[16].is_italics_node()
448
- assert result[16].sets_italics_off()
447
+ assert result[16].requires_repositioning()
448
+ assert result[17].sets_italics_on()
449
+ assert result[18].is_text_node()
450
+ assert result[19].is_explicit_break()
451
+ assert result[20].is_text_node()
452
+ assert result[21].is_explicit_break()
453
+ assert result[22].is_text_node()
454
+ assert result[23].sets_italics_off()
449
455
 
450
456
 
451
457
  class CaptionDummy:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes