pycaption 2.2.0__tar.gz → 2.2.2__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.0 → pycaption-2.2.2}/LICENSE +1 -1
  2. {pycaption-2.2.0/pycaption.egg-info → pycaption-2.2.2}/PKG-INFO +5 -5
  3. {pycaption-2.2.0 → pycaption-2.2.2}/README.rst +1 -1
  4. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/__init__.py +1 -1
  5. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/base.py +5 -2
  6. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/exceptions.py +6 -0
  7. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/scc/__init__.py +18 -8
  8. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/scc/constants.py +62 -0
  9. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/scc/specialized_collections.py +16 -5
  10. {pycaption-2.2.0 → pycaption-2.2.2/pycaption.egg-info}/PKG-INFO +5 -5
  11. {pycaption-2.2.0 → pycaption-2.2.2}/setup.py +4 -4
  12. {pycaption-2.2.0 → pycaption-2.2.2}/tests/conftest.py +2 -1
  13. {pycaption-2.2.0 → pycaption-2.2.2}/tests/fixtures/scc.py +21 -1
  14. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_dfxp.py +15 -15
  15. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_geometry.py +1 -1
  16. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_microdvd.py +14 -9
  17. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_sami.py +14 -9
  18. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_scc.py +29 -14
  19. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_srt.py +14 -9
  20. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_webvtt.py +14 -9
  21. {pycaption-2.2.0 → pycaption-2.2.2}/MANIFEST.in +0 -0
  22. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/dfxp/__init__.py +0 -0
  23. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/dfxp/base.py +0 -0
  24. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/dfxp/extras.py +0 -0
  25. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/english.pickle +0 -0
  26. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/geometry.py +0 -0
  27. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/microdvd.py +0 -0
  28. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/sami.py +0 -0
  29. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/scc/state_machines.py +0 -0
  30. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/scc/translator.py +0 -0
  31. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/srt.py +0 -0
  32. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/transcript.py +0 -0
  33. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/utils.py +0 -0
  34. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption/webvtt.py +0 -0
  35. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption.egg-info/SOURCES.txt +0 -0
  36. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption.egg-info/dependency_links.txt +0 -0
  37. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption.egg-info/requires.txt +0 -0
  38. {pycaption-2.2.0 → pycaption-2.2.2}/pycaption.egg-info/top_level.txt +0 -0
  39. {pycaption-2.2.0 → pycaption-2.2.2}/setup.cfg +0 -0
  40. {pycaption-2.2.0 → pycaption-2.2.2}/tests/__init__.py +0 -0
  41. {pycaption-2.2.0 → pycaption-2.2.2}/tests/fixtures/__init__.py +0 -0
  42. {pycaption-2.2.0 → pycaption-2.2.2}/tests/fixtures/dfxp.py +0 -0
  43. {pycaption-2.2.0 → pycaption-2.2.2}/tests/fixtures/microdvd.py +0 -0
  44. {pycaption-2.2.0 → pycaption-2.2.2}/tests/fixtures/sami.py +0 -0
  45. {pycaption-2.2.0 → pycaption-2.2.2}/tests/fixtures/srt.py +0 -0
  46. {pycaption-2.2.0 → pycaption-2.2.2}/tests/fixtures/translated_scc.py +0 -0
  47. {pycaption-2.2.0 → pycaption-2.2.2}/tests/fixtures/webvtt.py +0 -0
  48. {pycaption-2.2.0 → pycaption-2.2.2}/tests/mixins.py +0 -0
  49. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_base.py +0 -0
  50. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_dfxp_conversion.py +0 -0
  51. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_dfxp_extras.py +0 -0
  52. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_functions.py +0 -0
  53. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_microdvd_conversion.py +0 -0
  54. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_sami_conversion.py +0 -0
  55. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_scc_conversion.py +0 -0
  56. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_scc_translator.py +0 -0
  57. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_srt_conversion.py +0 -0
  58. {pycaption-2.2.0 → pycaption-2.2.2}/tests/test_webvtt_conversion.py +0 -0
@@ -186,7 +186,7 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright (c) 2012-2023 PBS.org
189
+ Copyright (c) 2012-2024 PBS.org
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pycaption
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: Closed caption converter
5
5
  Author: Joe Norton
6
6
  Author-email: joey@nortoncrew.com
@@ -12,15 +12,15 @@ Classifier: License :: OSI Approved :: Apache Software License
12
12
  Classifier: Operating System :: OS Independent
13
13
  Classifier: Programming Language :: Python
14
14
  Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.6
16
- Classifier: Programming Language :: Python :: 3.7
17
15
  Classifier: Programming Language :: Python :: 3.8
18
16
  Classifier: Programming Language :: Python :: 3.9
19
17
  Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Topic :: Software Development :: Libraries
21
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
22
  Classifier: Topic :: Multimedia :: Video
23
- Requires-Python: >=3.6,<4.0
23
+ Requires-Python: >=3.8,<4.0
24
24
  License-File: LICENSE
25
25
  Requires-Dist: beautifulsoup4>=4.12.1
26
26
  Requires-Dist: lxml>=4.9.1
@@ -48,7 +48,7 @@ For details, see the `documentation <http://pycaption.readthedocs.org>`__.
48
48
  License
49
49
  -------
50
50
 
51
- This module is Copyright (c) 2012-2023 PBS.org and is available under the `Apache
51
+ This module is Copyright (c) 2012-2024 PBS.org and is available under the `Apache
52
52
  License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0>`__.
53
53
 
54
54
  .. |Build Status| image:: https://github.com/pbs/pycaption/actions/workflows/unit_tests.yml/badge.svg
@@ -15,7 +15,7 @@ For details, see the `documentation <http://pycaption.readthedocs.org>`__.
15
15
  License
16
16
  -------
17
17
 
18
- This module is Copyright (c) 2012-2023 PBS.org and is available under the `Apache
18
+ This module is Copyright (c) 2012-2024 PBS.org and is available under the `Apache
19
19
  License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0>`__.
20
20
 
21
21
  .. |Build Status| image:: https://github.com/pbs/pycaption/actions/workflows/unit_tests.yml/badge.svg
@@ -10,7 +10,7 @@ from .scc.translator import translate_scc
10
10
  from .transcript import TranscriptWriter
11
11
  from .webvtt import WebVTTReader, WebVTTWriter
12
12
  from .exceptions import (
13
- CaptionReadError, CaptionReadNoCaptions, CaptionReadSyntaxError,
13
+ CaptionReadError, CaptionReadNoCaptions, CaptionReadSyntaxError, CaptionLineLengthError
14
14
  )
15
15
 
16
16
 
@@ -212,7 +212,7 @@ class Caption:
212
212
  f'{self.format_start()} --> {self.format_end()}\n{self.get_text()}'
213
213
  )
214
214
 
215
- def get_text(self):
215
+ def get_text_nodes(self):
216
216
  """
217
217
  Get the text of the caption.
218
218
  """
@@ -224,7 +224,10 @@ class Caption:
224
224
  return '\n'
225
225
  return ''
226
226
 
227
- text_nodes = [get_text_for_node(node) for node in self.nodes]
227
+ return [get_text_for_node(node) for node in self.nodes]
228
+
229
+ def get_text(self):
230
+ text_nodes = self.get_text_nodes()
228
231
  return ''.join(text_nodes).strip()
229
232
 
230
233
  def _format_timestamp(self, microseconds, msec_separator=None):
@@ -35,3 +35,9 @@ class RelativizationError(Exception):
35
35
 
36
36
  class InvalidInputError(RuntimeError):
37
37
  """Error raised when the input is invalid (i.e. a unicode string)"""
38
+
39
+
40
+ class CaptionLineLengthError(CaptionReadError):
41
+ """
42
+ Error raised when a Caption has a line longer than 32 characters.
43
+ """
@@ -88,7 +88,7 @@ from pycaption.base import (
88
88
  BaseReader, BaseWriter, CaptionSet, CaptionNode,
89
89
  )
90
90
  from pycaption.exceptions import CaptionReadNoCaptions, InvalidInputError, \
91
- CaptionReadTimingError
91
+ CaptionReadTimingError, CaptionLineLengthError
92
92
  from .constants import (
93
93
  HEADER, COMMANDS, SPECIAL_CHARS, EXTENDED_CHARS, CHARACTERS,
94
94
  MICROSECONDS_PER_CODEWORD, CHARACTER_TO_CODE,
@@ -232,6 +232,22 @@ class SCCReader(BaseReader):
232
232
  captions = CaptionSet({lang: self.caption_stash.get_all()})
233
233
 
234
234
  # check captions for incorrect lengths
235
+ lines = []
236
+ for caption in self.caption_stash._collection:
237
+ caption_text = "".join(caption.to_real_caption().get_text_nodes())
238
+ lines.extend(caption_text.split("\n"))
239
+ lines_too_long = [line for line in lines if len(line) > 32]
240
+
241
+ if bool(lines_too_long):
242
+ msg = ""
243
+ for line in lines_too_long:
244
+ msg += line + f" - Length { len(line)}" + "\n"
245
+ raise CaptionLineLengthError(
246
+ f"32 character limit for caption cue in scc file.\n"
247
+ f"Lines longer than 32:\n"
248
+ f"{msg}"
249
+ )
250
+
235
251
  for cap in captions.get_captions(lang):
236
252
  # if there's an end time on a caption and the difference is
237
253
  # less than .05s kill it (this is likely caused by a standalone
@@ -526,13 +542,7 @@ class SCCWriter(BaseWriter):
526
542
  # Wrap lines at 32 chars
527
543
  @staticmethod
528
544
  def _layout_line(caption):
529
- def caption_node_to_text(caption_node):
530
- if caption_node.type_ == CaptionNode.TEXT:
531
- return caption_node.content
532
- elif caption_node.type_ == CaptionNode.BREAK:
533
- return '\n'
534
- caption_text = ''.join(
535
- [caption_node_to_text(node) for node in caption.nodes])
545
+ caption_text = "".join(caption.get_text_nodes())
536
546
  inner_lines = caption_text.split('\n')
537
547
  inner_lines_laid_out = [textwrap.fill(x, 32) for x in inner_lines]
538
548
  return '\n'.join(inner_lines_laid_out)
@@ -1,4 +1,5 @@
1
1
  from itertools import product
2
+ from collections import defaultdict
2
3
 
3
4
  COMMANDS = {
4
5
  '9420': '',
@@ -985,3 +986,64 @@ MICROSECONDS_PER_CODEWORD = 1000.0 * 1000.0 / (30.0 * 1000.0 / 1001.0)
985
986
 
986
987
 
987
988
  HEADER = 'Scenarist_SCC V1.0'
989
+
990
+ # taken from
991
+ # http://www.theneitherworld.com/mcpoodle/SCC_TOOLS/DOCS/CC_CHARS.HTML
992
+ INCONVERTIBLE_TO_ASCII_EXTENDED_CHARS_ASSOCIATION = {
993
+ '¡': "!", # inverted exclamation mark
994
+ '¤': "C", # currency
995
+ '¥': "Y", # yen
996
+ '¦': "-", # broken bar
997
+ '©': "c", # copyright sign
998
+ '«': '"', # left pointing double angle quotation mark
999
+ '»': '"', # right pointing double angle quotation mark
1000
+ 'À': "A",
1001
+ 'Á': "A",
1002
+ 'Â': "A",
1003
+ 'Ã': "A",
1004
+ 'Ä': "A",
1005
+ 'Å': "A",
1006
+ 'Ç': "C",
1007
+ 'È': "E",
1008
+ 'É': "E",
1009
+ 'Ê': "E",
1010
+ 'Ë': "E",
1011
+ 'Ì': "I",
1012
+ 'Í': "I",
1013
+ 'Î': "I",
1014
+ 'Ï': "I",
1015
+ 'Ò': "O",
1016
+ 'Ó': "O",
1017
+ 'Ô': ")",
1018
+ 'Õ': "O",
1019
+ 'Ö': "O",
1020
+ 'Ø': "O",
1021
+ 'Ù': "U",
1022
+ 'Ú': "U",
1023
+ 'Û': "U",
1024
+ 'Ü': "U",
1025
+ 'ß': "s",
1026
+ 'ã': "a",
1027
+ 'ä': "a",
1028
+ 'å': "a",
1029
+ 'ë': "e",
1030
+ 'ì': "i",
1031
+ 'ï': "i",
1032
+ 'ò': "o",
1033
+ 'õ': "o",
1034
+ 'ö': "o",
1035
+ 'ø': "o",
1036
+ 'ù': "u",
1037
+ 'ü': "u",
1038
+ '—': "-", # em dash
1039
+ '‘': "'",
1040
+ '’': "'",
1041
+ '“': '"',
1042
+ '”': '"',
1043
+ '•': ".",
1044
+ '℠': "s",
1045
+ '┌': "+",
1046
+ '┐': "+",
1047
+ '└': "+",
1048
+ '┘': "+"
1049
+ }
@@ -8,7 +8,7 @@ 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,
11
+ MICROSECONDS_PER_CODEWORD, INCONVERTIBLE_TO_ASCII_EXTENDED_CHARS_ASSOCIATION
12
12
  )
13
13
 
14
14
  PopOnCue = collections.namedtuple("PopOnCue", "buffer, start, end")
@@ -423,14 +423,25 @@ class InstructionNodeCreator:
423
423
 
424
424
  :type accented_character: str
425
425
  """
426
- if self._collection and self._collection[-1].is_text_node() and \
427
- self._collection[-1].text:
428
- ascii_char = unicodedata.normalize('NFD', accented_character)\
429
- .encode('ascii', 'ignore').decode("utf-8")
426
+ is_text_node = (
427
+ self._collection and
428
+ self._collection[-1].is_text_node() and
429
+ self._collection[-1].text
430
+ )
431
+ if is_text_node:
432
+ try:
433
+ ascii_char = unicodedata.normalize('NFD', accented_character) \
434
+ .encode('ascii', 'strict').decode("utf-8")
435
+ except (UnicodeEncodeError, UnicodeDecodeError):
436
+ ascii_char = INCONVERTIBLE_TO_ASCII_EXTENDED_CHARS_ASSOCIATION[
437
+ accented_character
438
+ ]
439
+
430
440
  if ascii_char and self._collection[-1].text[-1] == ascii_char:
431
441
  self._collection[-1].text = self._collection[-1].text[:-1]
432
442
 
433
443
 
444
+
434
445
  def _get_layout_from_tuple(position_tuple):
435
446
  """Create a Layout object from the positioning information given
436
447
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pycaption
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: Closed caption converter
5
5
  Author: Joe Norton
6
6
  Author-email: joey@nortoncrew.com
@@ -12,15 +12,15 @@ Classifier: License :: OSI Approved :: Apache Software License
12
12
  Classifier: Operating System :: OS Independent
13
13
  Classifier: Programming Language :: Python
14
14
  Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.6
16
- Classifier: Programming Language :: Python :: 3.7
17
15
  Classifier: Programming Language :: Python :: 3.8
18
16
  Classifier: Programming Language :: Python :: 3.9
19
17
  Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Topic :: Software Development :: Libraries
21
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
22
  Classifier: Topic :: Multimedia :: Video
23
- Requires-Python: >=3.6,<4.0
23
+ Requires-Python: >=3.8,<4.0
24
24
  License-File: LICENSE
25
25
  Requires-Dist: beautifulsoup4>=4.12.1
26
26
  Requires-Dist: lxml>=4.9.1
@@ -48,7 +48,7 @@ For details, see the `documentation <http://pycaption.readthedocs.org>`__.
48
48
  License
49
49
  -------
50
50
 
51
- This module is Copyright (c) 2012-2023 PBS.org and is available under the `Apache
51
+ This module is Copyright (c) 2012-2024 PBS.org and is available under the `Apache
52
52
  License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0>`__.
53
53
 
54
54
  .. |Build Status| image:: https://github.com/pbs/pycaption/actions/workflows/unit_tests.yml/badge.svg
@@ -24,7 +24,7 @@ transcript_dependencies = [
24
24
 
25
25
  setup(
26
26
  name='pycaption',
27
- version='2.2.0',
27
+ version='2.2.2',
28
28
  description='Closed caption converter',
29
29
  long_description=open(README_PATH).read(),
30
30
  author='Joe Norton',
@@ -35,7 +35,7 @@ setup(
35
35
  'Release notes': 'https://pycaption.readthedocs.io'
36
36
  '/en/stable/changelog.html',
37
37
  },
38
- python_requires='>=3.6,<4.0',
38
+ python_requires='>=3.8,<4.0',
39
39
  install_requires=dependencies,
40
40
  extras_require={
41
41
  'dev': dev_dependencies,
@@ -49,11 +49,11 @@ setup(
49
49
  'Operating System :: OS Independent',
50
50
  'Programming Language :: Python',
51
51
  'Programming Language :: Python :: 3',
52
- 'Programming Language :: Python :: 3.6',
53
- 'Programming Language :: Python :: 3.7',
54
52
  'Programming Language :: Python :: 3.8',
55
53
  'Programming Language :: Python :: 3.9',
56
54
  'Programming Language :: Python :: 3.10',
55
+ 'Programming Language :: Python :: 3.11',
56
+ 'Programming Language :: Python :: 3.12',
57
57
  'Topic :: Software Development :: Libraries',
58
58
  'Topic :: Software Development :: Libraries :: Python Modules',
59
59
  'Topic :: Multimedia :: Video',
@@ -60,7 +60,8 @@ from tests.fixtures.scc import ( # noqa: F401
60
60
  sample_scc_with_ampersand_character, sample_scc_multiple_formats,
61
61
  sample_scc_duplicate_tab_offset, sample_scc_duplicate_special_characters,
62
62
  sample_scc_tab_offset, sample_scc_with_unknown_commands,
63
- sample_scc_special_and_extended_characters
63
+ sample_scc_special_and_extended_characters,
64
+ sample_scc_with_line_too_long
64
65
  )
65
66
  from tests.fixtures.srt import ( # noqa: F401
66
67
  sample_srt, sample_srt_ascii, sample_srt_numeric, sample_srt_empty,
@@ -314,6 +314,9 @@ def sample_scc_with_extended_characters():
314
314
  Scenarist_SCC V1.0
315
315
 
316
316
  00:04:36;06 9420 942c 942f 9420 91d6 cdc1 13b0 5254 c8c1 ba80 942f
317
+ 00:22:32:18 9420 942c 942f 9420 9454 97a1 4ad5 ce49 4f52 ba20 a180 92a7 d975 6da1 9470 9723 d961 206d e520 73e9
318
+
319
+ 00:22:34:28 942c e56e f4ef 206d 75e3 68ef 206d e5ea eff2 ae80 9420 942c 942f 9420 94f2 9723 4ad5 ce49 4f52 ba20 4f79 e52c 20c1 ec6d 612c
317
320
  """
318
321
 
319
322
 
@@ -422,4 +425,21 @@ Scenarist_SCC V1.0
422
425
  00:20:19;12 1326 13a7 13a8 1329 132a 13ab 132c 13ad 13ae 132f 13b0 1331 1332
423
426
 
424
427
  00:24:39;28 13b3 1334 13b5 13b6 1337 1338 13b9 13ba 133b 13bc 133d 133e 13bf
425
- """
428
+ """
429
+
430
+
431
+ @pytest.fixture(scope="session")
432
+ def sample_scc_with_line_too_long():
433
+ return """\
434
+ Scenarist_SCC V1.0
435
+
436
+ 00:00:00;03 942c
437
+
438
+ 00:00:01;45 9420 91f4 cb45 4c4c d920 4ac1 cd45 d3ba 20c8 eff7 9254 f468 e520 7368 eff7 2073 f461 f2f4 e564 942c 8080 8080 942f
439
+
440
+ 00:00:02;55 9420 91e0 9723 f761 7320 4361 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 ec20 c4e5 6ee9 73ef 6e2c 2061 20e6 f2e9 e56e 6480 9240 9723 efe6 20ef 75f2 732c 20f7 6173 2064 efe9 6e67 206d 7920 43c4 73ae 942c 8080 8080 942f
441
+
442
+ 00:00:06;57 9420 94e0 c16e 6420 68e5 2073 61e9 642c 2049 20e3 616e 2064 ef20 6120 54d6 2073 68ef f7ae 942c 8080 8080 942f
443
+
444
+ 00:00:08;58 9420 9452 4920 ea75 73f4 20f7 616e f4e5 6420 ef6e e520 7368 eff7 2c80 94f2 ea75 73f4 20f4 ef20 6861 76e5 2061 7320 6120 ece9 f4f4 ece5 942c 8080 8080 942f
445
+ """
@@ -2,14 +2,12 @@ import pytest
2
2
 
3
3
  from pycaption import DFXPReader, CaptionReadNoCaptions
4
4
  from pycaption.exceptions import (
5
- CaptionReadSyntaxError, InvalidInputError, CaptionReadError,
6
- CaptionReadTimingError,
5
+ CaptionReadSyntaxError, CaptionReadError, CaptionReadTimingError,
7
6
  )
8
7
  from pycaption.geometry import (
9
8
  UnitEnum, HorizontalAlignmentEnum, VerticalAlignmentEnum,
10
9
  )
11
10
  from tests.mixins import ReaderTestingMixIn
12
- from pytest_lazyfixture import lazy_fixture
13
11
 
14
12
 
15
13
  class TestDFXPReader(ReaderTestingMixIn):
@@ -19,15 +17,20 @@ class TestDFXPReader(ReaderTestingMixIn):
19
17
  def test_positive_answer_for_detection(self, sample_dfxp):
20
18
  super().assert_positive_answer_for_detection(sample_dfxp)
21
19
 
22
- @pytest.mark.parametrize('different_sample', [
23
- pytest.lazy_fixture('sample_microdvd'),
24
- pytest.lazy_fixture('sample_sami'),
25
- pytest.lazy_fixture('sample_scc_pop_on'),
26
- pytest.lazy_fixture('sample_srt'),
27
- pytest.lazy_fixture('sample_webvtt')
28
- ])
29
- def test_negative_answer_for_detection(self, different_sample):
30
- super().assert_negative_answer_for_detection(different_sample)
20
+ def test_negative_answer_for_microdvd(self, sample_microdvd):
21
+ super().assert_negative_answer_for_detection(sample_microdvd)
22
+
23
+ def test_negative_answer_for_sami(self, sample_sami):
24
+ super().assert_negative_answer_for_detection(sample_sami)
25
+
26
+ def test_negative_answer_for_scc_on_pop_on(self, sample_scc_pop_on):
27
+ super().assert_negative_answer_for_detection(sample_scc_pop_on)
28
+
29
+ def test_negative_answer_for_srt(self, sample_srt):
30
+ super().assert_negative_answer_for_detection(sample_srt)
31
+
32
+ def test_negative_answer_for_webvtt(self, sample_webvtt):
33
+ super().assert_negative_answer_for_detection(sample_webvtt)
31
34
 
32
35
  def test_caption_length(self, sample_dfxp):
33
36
  captions = DFXPReader().read(sample_dfxp)
@@ -87,9 +90,6 @@ class TestDFXPReader(ReaderTestingMixIn):
87
90
  with pytest.raises(CaptionReadTimingError) as exc_info:
88
91
  DFXPReader()._convert_timestamp_to_microseconds(timestamp)
89
92
 
90
- assert exc_info.value.args[0].startswith(
91
- f'Invalid timestamp: {timestamp}.')
92
-
93
93
  def test_empty_file(self, sample_dfxp_empty):
94
94
  with pytest.raises(CaptionReadNoCaptions):
95
95
  DFXPReader().read(sample_dfxp_empty)
@@ -140,4 +140,4 @@ class TestSize:
140
140
  with pytest.raises(CaptionReadSyntaxError) as exc_info:
141
141
  Size.from_string(string)
142
142
 
143
- assert exc_info.value.args[0].startswith(f"Invalid size: {string}.")
143
+ assert exc_info.value.args[0].startswith(f"Invalid size: {string}.")
@@ -13,15 +13,20 @@ class TestMicroDVDReader(ReaderTestingMixIn):
13
13
  def test_positive_answer_for_detection(self, sample_microdvd):
14
14
  super().assert_positive_answer_for_detection(sample_microdvd)
15
15
 
16
- @pytest.mark.parametrize('different_sample', [
17
- pytest.lazy_fixture('sample_dfxp'),
18
- pytest.lazy_fixture('sample_sami'),
19
- pytest.lazy_fixture('sample_scc_pop_on'),
20
- pytest.lazy_fixture('sample_srt'),
21
- pytest.lazy_fixture('sample_webvtt')
22
- ])
23
- def test_negative_answer_for_detection(self, different_sample):
24
- super().assert_negative_answer_for_detection(different_sample)
16
+ def test_negative_answer_for_detection_dfxp(self, sample_dfxp):
17
+ super().assert_negative_answer_for_detection(sample_dfxp)
18
+
19
+ def test_negative_answer_for_detection_sami(self, sample_sami):
20
+ super().assert_negative_answer_for_detection(sample_sami)
21
+
22
+ def test_negative_answer_for_detection_scc_pop_on(self, sample_scc_pop_on):
23
+ super().assert_negative_answer_for_detection(sample_scc_pop_on)
24
+
25
+ def test_negative_answer_for_detection_srt(self, sample_srt):
26
+ super().assert_negative_answer_for_detection(sample_srt)
27
+
28
+ def test_negative_answer_for_detection_webvtt(self, sample_webvtt):
29
+ super().assert_negative_answer_for_detection(sample_webvtt)
25
30
 
26
31
  def test_caption_length(self, sample_microdvd):
27
32
  captions = MicroDVDReader().read(sample_microdvd)
@@ -15,15 +15,20 @@ class TestSAMIReader(ReaderTestingMixIn):
15
15
  def test_positive_answer_for_detection(self, sample_sami):
16
16
  super().assert_positive_answer_for_detection(sample_sami)
17
17
 
18
- @pytest.mark.parametrize('different_sample', [
19
- pytest.lazy_fixture('sample_dfxp'),
20
- pytest.lazy_fixture('sample_microdvd'),
21
- pytest.lazy_fixture('sample_scc_pop_on'),
22
- pytest.lazy_fixture('sample_srt'),
23
- pytest.lazy_fixture('sample_webvtt')
24
- ])
25
- def test_negative_answer_for_detection(self, different_sample):
26
- super().assert_negative_answer_for_detection(different_sample)
18
+ def test_negative_answer_for_detection_dfxp(self, sample_dfxp):
19
+ super().assert_negative_answer_for_detection(sample_dfxp)
20
+
21
+ def test_negative_answer_for_detection_microdvd(self, sample_microdvd):
22
+ super().assert_negative_answer_for_detection(sample_microdvd)
23
+
24
+ def test_negative_answer_for_detection_scc_pop_on(self, sample_scc_pop_on):
25
+ super().assert_negative_answer_for_detection(sample_scc_pop_on)
26
+
27
+ def test_negative_answer_for_detection_srt(self, sample_srt):
28
+ super().assert_negative_answer_for_detection(sample_srt)
29
+
30
+ def test_negative_answer_for_detection_webvtt(self, sample_webvtt):
31
+ super().assert_negative_answer_for_detection(sample_webvtt)
27
32
 
28
33
  def test_caption_length(self, sample_sami):
29
34
  caption_set = self.reader.read(sample_sami)
@@ -1,7 +1,7 @@
1
1
  import pytest
2
2
 
3
3
  from pycaption import SCCReader, CaptionReadNoCaptions, CaptionNode
4
- from pycaption.exceptions import CaptionReadTimingError
4
+ from pycaption.exceptions import CaptionReadTimingError, CaptionLineLengthError
5
5
  from pycaption.geometry import (
6
6
  UnitEnum, HorizontalAlignmentEnum, VerticalAlignmentEnum,
7
7
  )
@@ -22,15 +22,20 @@ class TestSCCReader(ReaderTestingMixIn):
22
22
  def test_positive_answer_for_detection(self, sample_scc_pop_on):
23
23
  super().assert_positive_answer_for_detection(sample_scc_pop_on)
24
24
 
25
- @pytest.mark.parametrize('different_sample', [
26
- pytest.lazy_fixture('sample_dfxp'),
27
- pytest.lazy_fixture('sample_microdvd'),
28
- pytest.lazy_fixture('sample_sami'),
29
- pytest.lazy_fixture('sample_srt'),
30
- pytest.lazy_fixture('sample_webvtt')
31
- ])
32
- def test_negative_answer_for_detection(self, different_sample):
33
- super().assert_negative_answer_for_detection(different_sample)
25
+ def test_negative_answer_for_detection_dfxp(self, sample_dfxp):
26
+ super().assert_negative_answer_for_detection(sample_dfxp)
27
+
28
+ def test_negative_answer_for_detection_microdvd(self, sample_microdvd):
29
+ super().assert_negative_answer_for_detection(sample_microdvd)
30
+
31
+ def test_negative_answer_for_detection_sami(self, sample_sami):
32
+ super().assert_negative_answer_for_detection(sample_sami)
33
+
34
+ def test_negative_answer_for_detection_srt(self, sample_srt):
35
+ super().assert_negative_answer_for_detection(sample_srt)
36
+
37
+ def test_negative_answer_for_detection_webvtt(self, sample_webvtt):
38
+ super().assert_negative_answer_for_detection(sample_webvtt)
34
39
 
35
40
  def test_caption_length(self, sample_scc_pop_on):
36
41
  captions = SCCReader().read(sample_scc_pop_on)
@@ -193,9 +198,11 @@ class TestSCCReader(ReaderTestingMixIn):
193
198
  def test_skip_extended_characters_ascii_duplicate(
194
199
  self, sample_scc_with_extended_characters):
195
200
  caption_set = SCCReader().read(sample_scc_with_extended_characters)
196
- nodes = caption_set.get_captions('en-US')[0].nodes
197
-
198
- assert nodes[0].content == 'MÄRTHA:'
201
+ captions = caption_set.get_captions('en-US')
202
+ assert captions[0].nodes[0].content == 'MÄRTHA:'
203
+ expected_result = ['JUNIOR: ¡Yum!', None, 'Ya me siento mucho mejor.']
204
+ content = [node.content for node in captions[1].nodes]
205
+ assert all(result in expected_result for result in content)
199
206
 
200
207
  def test_skip_duplicate_tab_offset(self, sample_scc_duplicate_tab_offset):
201
208
  expected_lines = [
@@ -237,6 +244,15 @@ class TestSCCReader(ReaderTestingMixIn):
237
244
  assert exc_info.value.args[0].startswith(
238
245
  "Unsupported cue duration around 00:00:20.433")
239
246
 
247
+ def test_line_too_long(self, sample_scc_with_line_too_long):
248
+ with pytest.raises(CaptionLineLengthError) as exc_info:
249
+ SCCReader().read(sample_scc_with_line_too_long)
250
+
251
+ assert exc_info.value.args[0].startswith(
252
+ "32 character limit for caption cue in scc file.")
253
+ assert ("was Cal l l l l l l l l l l l l l l l l l l l l l l l l l l l l Denison, a friend - Length 81"
254
+ in exc_info.value.args[0].split("\n"))
255
+
240
256
 
241
257
  class TestCoverageOnly:
242
258
  """In order to refactor safely, we need coverage of 95% or more.
@@ -272,7 +288,6 @@ class TestCoverageOnly:
272
288
  'And wildlife.',
273
289
  '>> Bike Iowa, your source for',
274
290
  ]
275
-
276
291
  assert expected_texts == actual_texts
277
292
 
278
293
  def test_multiple_formats(self, sample_scc_multiple_formats):
@@ -11,15 +11,20 @@ class TestSRTReader(ReaderTestingMixIn):
11
11
  def test_positive_answer_for_detection(self, sample_srt):
12
12
  super().assert_positive_answer_for_detection(sample_srt)
13
13
 
14
- @pytest.mark.parametrize('different_sample', [
15
- pytest.lazy_fixture('sample_dfxp'),
16
- pytest.lazy_fixture('sample_microdvd'),
17
- pytest.lazy_fixture('sample_sami'),
18
- pytest.lazy_fixture('sample_scc_pop_on'),
19
- pytest.lazy_fixture('sample_webvtt')
20
- ])
21
- def test_negative_answer_for_detection(self, different_sample):
22
- super().assert_negative_answer_for_detection(different_sample)
14
+ def test_negative_answer_for_detection_dfxp(self, sample_dfxp):
15
+ super().assert_negative_answer_for_detection(sample_dfxp)
16
+
17
+ def test_negative_answer_for_detection_microdvd(self, sample_microdvd):
18
+ super().assert_negative_answer_for_detection(sample_microdvd)
19
+
20
+ def test_negative_answer_for_detection_sami(self, sample_sami):
21
+ super().assert_negative_answer_for_detection(sample_sami)
22
+
23
+ def test_negative_answer_for_detection_scc_pop_on(self, sample_scc_pop_on):
24
+ super().assert_negative_answer_for_detection(sample_scc_pop_on)
25
+
26
+ def test_negative_answer_for_detection_webvtt(self, sample_webvtt):
27
+ super().assert_negative_answer_for_detection(sample_webvtt)
23
28
 
24
29
  def test_caption_length(self, sample_srt):
25
30
  captions = self.reader.read(sample_srt)
@@ -14,15 +14,20 @@ class TestWebVTTReader(ReaderTestingMixIn):
14
14
  def test_positive_answer_for_detection(self, sample_webvtt):
15
15
  super().assert_positive_answer_for_detection(sample_webvtt)
16
16
 
17
- @pytest.mark.parametrize('different_sample', [
18
- pytest.lazy_fixture('sample_dfxp'),
19
- pytest.lazy_fixture('sample_microdvd'),
20
- pytest.lazy_fixture('sample_sami'),
21
- pytest.lazy_fixture('sample_scc_pop_on'),
22
- pytest.lazy_fixture('sample_srt')
23
- ])
24
- def test_negative_answer_for_detection(self, different_sample):
25
- super().assert_negative_answer_for_detection(different_sample)
17
+ def test_negative_answer_for_detection_dfxp(self, sample_dfxp):
18
+ super().assert_negative_answer_for_detection(sample_dfxp)
19
+
20
+ def test_negative_answer_for_detection_microdvd(self, sample_microdvd):
21
+ super().assert_negative_answer_for_detection(sample_microdvd)
22
+
23
+ def test_negative_answer_for_detection_sami(self, sample_sami):
24
+ super().assert_negative_answer_for_detection(sample_sami)
25
+
26
+ def test_negative_answer_for_detection_scc_pop_on(self, sample_scc_pop_on):
27
+ super().assert_negative_answer_for_detection(sample_scc_pop_on)
28
+
29
+ def test_negative_answer_for_detection_srt(self, sample_srt):
30
+ super().assert_negative_answer_for_detection(sample_srt)
26
31
 
27
32
  def test_caption_length(self, sample_webvtt_2):
28
33
  captions = self.reader.read(sample_webvtt_2)
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