mkv-episode-matcher 0.3.3__py3-none-any.whl → 1.0.0__py3-none-any.whl

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 (38) hide show
  1. mkv_episode_matcher/__init__.py +8 -0
  2. mkv_episode_matcher/__main__.py +2 -177
  3. mkv_episode_matcher/asr_models.py +506 -0
  4. mkv_episode_matcher/cli.py +558 -0
  5. mkv_episode_matcher/core/config_manager.py +100 -0
  6. mkv_episode_matcher/core/engine.py +577 -0
  7. mkv_episode_matcher/core/matcher.py +214 -0
  8. mkv_episode_matcher/core/models.py +91 -0
  9. mkv_episode_matcher/core/providers/asr.py +85 -0
  10. mkv_episode_matcher/core/providers/subtitles.py +341 -0
  11. mkv_episode_matcher/core/utils.py +148 -0
  12. mkv_episode_matcher/episode_identification.py +550 -118
  13. mkv_episode_matcher/subtitle_utils.py +82 -0
  14. mkv_episode_matcher/tmdb_client.py +56 -14
  15. mkv_episode_matcher/ui/flet_app.py +708 -0
  16. mkv_episode_matcher/utils.py +262 -139
  17. mkv_episode_matcher-1.0.0.dist-info/METADATA +242 -0
  18. mkv_episode_matcher-1.0.0.dist-info/RECORD +23 -0
  19. {mkv_episode_matcher-0.3.3.dist-info → mkv_episode_matcher-1.0.0.dist-info}/WHEEL +1 -1
  20. mkv_episode_matcher-1.0.0.dist-info/licenses/LICENSE +21 -0
  21. mkv_episode_matcher/config.py +0 -82
  22. mkv_episode_matcher/episode_matcher.py +0 -100
  23. mkv_episode_matcher/libraries/pgs2srt/.gitignore +0 -2
  24. mkv_episode_matcher/libraries/pgs2srt/Libraries/SubZero/SubZero.py +0 -321
  25. mkv_episode_matcher/libraries/pgs2srt/Libraries/SubZero/dictionaries/data.py +0 -16700
  26. mkv_episode_matcher/libraries/pgs2srt/Libraries/SubZero/post_processing.py +0 -260
  27. mkv_episode_matcher/libraries/pgs2srt/README.md +0 -26
  28. mkv_episode_matcher/libraries/pgs2srt/__init__.py +0 -0
  29. mkv_episode_matcher/libraries/pgs2srt/imagemaker.py +0 -89
  30. mkv_episode_matcher/libraries/pgs2srt/pgs2srt.py +0 -150
  31. mkv_episode_matcher/libraries/pgs2srt/pgsreader.py +0 -225
  32. mkv_episode_matcher/libraries/pgs2srt/requirements.txt +0 -4
  33. mkv_episode_matcher/mkv_to_srt.py +0 -302
  34. mkv_episode_matcher/speech_to_text.py +0 -90
  35. mkv_episode_matcher-0.3.3.dist-info/METADATA +0 -125
  36. mkv_episode_matcher-0.3.3.dist-info/RECORD +0 -25
  37. {mkv_episode_matcher-0.3.3.dist-info → mkv_episode_matcher-1.0.0.dist-info}/entry_points.txt +0 -0
  38. {mkv_episode_matcher-0.3.3.dist-info → mkv_episode_matcher-1.0.0.dist-info}/top_level.txt +0 -0
@@ -1,321 +0,0 @@
1
- # MIT License
2
- #
3
- # Copyright (c) 2018 Hannes Tismer
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in all
13
- # copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- # SOFTWARE.
22
- #
23
- #
24
- # Copyright for portions of project Sub-Zero are held by Bram Walet, 2014 as part of project Subliminal.bundle.
25
- # The original license is supplied below.
26
- #
27
- # The MIT License (MIT)
28
- #
29
- # Copyright (c) 2014 Bram Walet
30
- #
31
- # Permission is hereby granted, free of charge, to any person obtaining a copy
32
- # of this software and associated documentation files (the "Software"), to deal
33
- # in the Software without restriction, including without limitation the rights
34
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
- # copies of the Software, and to permit persons to whom the Software is
36
- # furnished to do so, subject to the following conditions:
37
- #
38
- # The above copyright notice and this permission notice shall be included in all
39
- # copies or substantial portions of the Software.
40
- #
41
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
44
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
47
- # SOFTWARE.
48
-
49
-
50
- class Processor:
51
- """
52
- Processor base class
53
- """
54
-
55
- name = None
56
- parent = None
57
- supported = None
58
- enabled = True
59
-
60
- def __init__(self, name=None, parent=None, supported=None, **kwargs):
61
- self.name = name
62
- self.parent = parent
63
- self.supported = supported if supported else lambda parent: True
64
-
65
- @property
66
- def info(self):
67
- return self.name
68
-
69
- def process(self, content, debug=False, **kwargs):
70
- return content
71
-
72
- def __repr__(self):
73
- return f"Processor <{self.__class__.__name__} {self.info}>"
74
-
75
- def __str__(self):
76
- return repr(self)
77
-
78
- # def __unicode__(self):
79
- # return unicode(repr(self))
80
-
81
-
82
- class ReProcessor(Processor):
83
- """
84
- Regex processor
85
- """
86
-
87
- pattern = None
88
- replace_with = None
89
-
90
- def __init__(
91
- self, pattern, replace_with, name=None, supported=None, entry=False, **kwargs
92
- ):
93
- super(ReProcessor, self).__init__(name=name, supported=supported)
94
- self.pattern = pattern
95
- self.replace_with = replace_with
96
- self.use_entry = entry
97
-
98
- def process(self, content, debug=False, entry=None, **kwargs):
99
- if not self.use_entry:
100
- return self.pattern.sub(self.replace_with, content)
101
-
102
- ret = self.pattern.sub(self.replace_with, entry)
103
- if not ret:
104
- raise EmptyEntryError
105
- elif ret != entry:
106
- return ret
107
- return content
108
-
109
-
110
- class NReProcessor(ReProcessor):
111
- pass
112
-
113
-
114
- class MultipleWordReProcessor(ReProcessor):
115
- """
116
- Expects a dictionary in the form of:
117
- dict = {
118
- "data": {"old_value": "new_value"},
119
- "pattern": compiled re object that matches data.keys()
120
- }
121
- replaces found key in pattern with the corresponding value in data
122
- """
123
-
124
- def __init__(self, snr_dict, name=None, parent=None, supported=None, **kwargs):
125
- super(ReProcessor, self).__init__(name=name, supported=supported)
126
- self.snr_dict = snr_dict
127
-
128
- def process(self, content, debug=False, **kwargs):
129
- if not self.snr_dict["data"]:
130
- return content
131
-
132
- return self.snr_dict["pattern"].sub(
133
- lambda x: self.snr_dict["data"][x.group(0)], content
134
- )
135
-
136
-
137
- class EmptyEntryError(Exception):
138
- pass
139
-
140
-
141
- class SubtitleModification:
142
- identifier = None
143
- description = None
144
- long_description = None
145
- exclusive = False
146
- advanced = False # has parameters
147
- args_mergeable = False
148
- order = None
149
- modifies_whole_file = False # operates on the whole file, not individual entries
150
- apply_last = False
151
- only_uppercase = False
152
- pre_processors = []
153
- processors = []
154
- post_processors = []
155
- last_processors = []
156
- languages = []
157
-
158
- def __init__(self):
159
- return
160
-
161
- def _process(
162
- self, content, processors, debug=False, parent=None, index=None, **kwargs
163
- ):
164
- if not content:
165
- return
166
-
167
- # processors may be a list or a callable
168
- # if callable(processors):
169
- # _processors = processors()
170
- # else:
171
- # _processors = processors
172
- _processors = processors
173
-
174
- new_content = content
175
- for processor in _processors:
176
- if not processor.supported(parent):
177
- if debug and processor.enabled:
178
- # logger.debug("Processor not supported, skipping: %s", processor.name)
179
- processor.enabled = False
180
- continue
181
-
182
- old_content = new_content
183
- new_content = processor.process(new_content, debug=debug, **kwargs)
184
- if not new_content:
185
- # if debug:
186
- # logger.debug("Processor returned empty line: %s", processor.name)
187
- break
188
- if debug:
189
- if old_content == new_content:
190
- continue
191
- # logger.debug("%d: %s: %s -> %s", index, processor.name, repr(old_content), repr(new_content))
192
-
193
- return new_content
194
-
195
- def pre_process(self, content, debug=False, parent=None, **kwargs):
196
- return self._process(
197
- content, self.pre_processors, debug=debug, parent=parent, **kwargs
198
- )
199
-
200
- def process(self, content, debug=False, parent=None, **kwargs):
201
- return self._process(
202
- content, self.processors, debug=debug, parent=parent, **kwargs
203
- )
204
-
205
- def post_process(self, content, debug=False, parent=None, **kwargs):
206
- return self._process(
207
- content, self.post_processors, debug=debug, parent=parent, **kwargs
208
- )
209
-
210
- def modify(self, content, debug=False, parent=None, procs=None, **kwargs):
211
- if not content:
212
- return
213
-
214
- new_content = content
215
- for method in procs or ("pre_process", "process", "post_process"):
216
- if not new_content:
217
- return
218
- new_content = self._process(
219
- new_content,
220
- getattr(self, f"{method}ors"),
221
- debug=debug,
222
- parent=parent,
223
- **kwargs,
224
- )
225
-
226
- return new_content
227
-
228
- @classmethod
229
- def get_signature(cls, **kwargs):
230
- string_args = ",".join([
231
- f"{key}={value}" for key, value in kwargs.items()
232
- ])
233
- return f"{cls.identifier}({string_args})"
234
-
235
- @classmethod
236
- def merge_args(cls, args1, args2):
237
- raise NotImplementedError
238
-
239
-
240
- class SubtitleTextModification(SubtitleModification):
241
- pass
242
-
243
-
244
- class StringProcessor(Processor):
245
- """
246
- String replacement processor base
247
- """
248
-
249
- def __init__(
250
- self, search, replace, name=None, parent=None, supported=None, **kwargs
251
- ):
252
- super(StringProcessor, self).__init__(name=name, supported=supported)
253
- self.search = search
254
- self.replace = replace
255
-
256
- def process(self, content, debug=False, **kwargs):
257
- return content.replace(self.search, self.replace)
258
-
259
-
260
- class MultipleLineProcessor(Processor):
261
- """
262
- replaces stuff in whole lines
263
-
264
- takes a search/replace dict as first argument
265
- Expects a dictionary in the form of:
266
- dict = {
267
- "data": {"old_value": "new_value"}
268
- }
269
- """
270
-
271
- def __init__(self, snr_dict, name=None, parent=None, supported=None, **kwargs):
272
- super(MultipleLineProcessor, self).__init__(name=name, supported=supported)
273
- self.snr_dict = snr_dict
274
-
275
- def process(self, content, debug=False, **kwargs):
276
- if not self.snr_dict["data"]:
277
- return content
278
-
279
- for key, value in self.snr_dict["data"].items():
280
- # if debug and key in content:
281
- # logger.debug(u"Replacing '%s' with '%s' in '%s'", key, value, content)
282
-
283
- content = content.replace(key, value)
284
-
285
- return content
286
-
287
-
288
- class WholeLineProcessor(MultipleLineProcessor):
289
- def process(self, content, debug=False, **kwargs):
290
- if not self.snr_dict["data"]:
291
- return content
292
- content = content.strip()
293
-
294
- for key, value in self.snr_dict["data"].items():
295
- if content == key:
296
- # if debug:
297
- # logger.debug(u"Replacing '%s' with '%s'", key, value)
298
-
299
- content = value
300
- break
301
-
302
- return content
303
-
304
-
305
- class MultipleWordProcessor(MultipleLineProcessor):
306
- """
307
- replaces words
308
- takes a search/replace dict as first argument
309
- Expects a dictionary in the form of:
310
- dict = {
311
- "data": {"old_value": "new_value"}
312
- }
313
- """
314
-
315
- def process(self, content, debug=False, **kwargs):
316
- words = content.split(" ")
317
- new_words = []
318
- for word in words:
319
- new_words.append(self.snr_dict.get(word, word))
320
-
321
- return " ".join(new_words)