easyrip 4.11.0__tar.gz → 4.11.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 (37) hide show
  1. {easyrip-4.11.0 → easyrip-4.11.2}/PKG-INFO +1 -1
  2. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_command.py +56 -9
  3. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_config/config.py +2 -2
  4. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_main.py +6 -7
  5. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_mlang/translator.py +9 -9
  6. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_prompt.py +2 -2
  7. easyrip-4.11.2/easyrip/global_val.py +29 -0
  8. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/ripper/param.py +1 -1
  9. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/ripper/ripper.py +41 -38
  10. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip.egg-info/PKG-INFO +1 -1
  11. easyrip-4.11.0/easyrip/global_val.py +0 -25
  12. {easyrip-4.11.0 → easyrip-4.11.2}/LICENSE +0 -0
  13. {easyrip-4.11.0 → easyrip-4.11.2}/README.md +0 -0
  14. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/__init__.py +0 -0
  15. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/__main__.py +0 -0
  16. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_config/config_key.py +0 -0
  17. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_log.py +0 -0
  18. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_mlang/__init__.py +0 -0
  19. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_mlang/global_lang_val.py +0 -0
  20. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_mlang/lang_en.py +0 -0
  21. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_mlang/lang_zh_Hans_CN.py +0 -0
  22. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_web/__init__.py +0 -0
  23. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_web/http_server.py +0 -0
  24. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/easyrip_web/third_party_api.py +0 -0
  25. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/ripper/media_info.py +0 -0
  26. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/ripper/sub_and_font/__init__.py +0 -0
  27. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/ripper/sub_and_font/ass.py +0 -0
  28. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/ripper/sub_and_font/font.py +0 -0
  29. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/ripper/sub_and_font/subset.py +0 -0
  30. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip/utils.py +0 -0
  31. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip.egg-info/SOURCES.txt +0 -0
  32. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip.egg-info/dependency_links.txt +0 -0
  33. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip.egg-info/entry_points.txt +0 -0
  34. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip.egg-info/requires.txt +0 -0
  35. {easyrip-4.11.0 → easyrip-4.11.2}/easyrip.egg-info/top_level.txt +0 -0
  36. {easyrip-4.11.0 → easyrip-4.11.2}/pyproject.toml +0 -0
  37. {easyrip-4.11.0 → easyrip-4.11.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: easyrip
3
- Version: 4.11.0
3
+ Version: 4.11.2
4
4
  Author: op200
5
5
  License-Expression: AGPL-3.0-or-later
6
6
  Project-URL: Homepage, https://github.com/op200/EasyRip
@@ -19,7 +19,7 @@ from prompt_toolkit.document import Document
19
19
 
20
20
  from . import global_val
21
21
  from .easyrip_config.config_key import Config_key
22
- from .ripper.param import Audio_codec, Preset_name
22
+ from .ripper.param import PRESET_OPT_NAME, Audio_codec, Preset_name
23
23
 
24
24
 
25
25
  @final
@@ -595,6 +595,21 @@ class Opt_type(enum.Enum):
595
595
  ("-hwaccel",),
596
596
  param="<string>",
597
597
  description="Use FFmpeg hwaccel (See 'ffmpeg -hwaccels' for details)",
598
+ childs=(
599
+ Cmd_type_val(
600
+ names=(
601
+ "cuda",
602
+ "vaapi",
603
+ "dxva2",
604
+ "qsv",
605
+ "d3d11va",
606
+ "opencl",
607
+ "vulkan",
608
+ "d3d12va",
609
+ "amf",
610
+ )
611
+ ),
612
+ ),
598
613
  )
599
614
  _ss = Cmd_type_val(
600
615
  ("-ss",),
@@ -763,8 +778,24 @@ class OptCompleter(Completer):
763
778
  if len(words) >= 1 and not text.startswith("-"):
764
779
  return
765
780
 
766
- opt_tree_pos_list: list[nested_dict | Completer] = [self.opt_tree]
781
+ add_comp_words: set[str] = set()
782
+ add_comp_meta_dict: dict[str, str] = {}
783
+ if _preset := tuple(
784
+ words[i + 1]
785
+ for i, word in enumerate(words[:-1])
786
+ for opt_p_name in Opt_type._preset.value.names
787
+ if word == opt_p_name
788
+ ):
789
+ _preset = _preset[-1]
790
+ _preset_name = None
791
+ if _preset in Preset_name._member_map_:
792
+ _preset_name = Preset_name[_preset]
793
+ if _preset_name is not None and _preset_name in PRESET_OPT_NAME:
794
+ add_set: set[str] = {f"-{n}" for n in PRESET_OPT_NAME[_preset_name]}
795
+ add_comp_words |= add_set
796
+ add_comp_meta_dict |= dict.fromkeys(add_set, f"{_preset} param")
767
797
 
798
+ opt_tree_pos_list: list[nested_dict | Completer] = [self.opt_tree]
768
799
  for word in words:
769
800
  if isinstance(opt_tree_pos_list[-1], Completer):
770
801
  opt_tree_pos_list.append(self.opt_tree.get(word, self.opt_tree))
@@ -775,7 +806,14 @@ class OptCompleter(Completer):
775
806
  )
776
807
  )
777
808
 
778
- if opt_tree_pos_list[-1] is not self.opt_tree and not text.endswith(" "):
809
+ if (
810
+ (opt_tree_pos_list[-1] is not self.opt_tree)
811
+ or (words and words[-1] in add_comp_words)
812
+ ) and not text.endswith(" "):
813
+ # 不在根(上个单词没让这个单词回退到根) or 匹配额外提示
814
+ # 且尾部不是空格
815
+ # 即当前单词完全匹配,输出匹配成功提示
816
+
779
817
  yield from (
780
818
  Completion(
781
819
  text=words[-1],
@@ -786,8 +824,10 @@ class OptCompleter(Completer):
786
824
  text="",
787
825
  display="✔",
788
826
  display_meta=(
789
- ""
790
- if (_opt := Opt_type.from_str(text)) is None
827
+ add_comp_meta_dict[words[-1]]
828
+ if words[-1] in add_comp_meta_dict
829
+ else ""
830
+ if (_opt := Opt_type.from_str(words[-1])) is None
791
831
  else f"{_desc_list[0]}..."
792
832
  if len(_desc_list := _opt.value.description.split("\n")) > 1
793
833
  else _desc_list[0]
@@ -796,6 +836,8 @@ class OptCompleter(Completer):
796
836
  )
797
837
 
798
838
  elif isinstance(opt_tree_pos_list[-1], Completer):
839
+ # 上个单词进入独立提示,意味着当前的提示可能会是路径提示
840
+
799
841
  # 直接使用 PathCompleter 会因为上下文问题失效,所以将上文套进 NestedCompleter
800
842
  new_nd: nested_dict = {}
801
843
  new_nd_pos: nested_dict = new_nd
@@ -808,6 +850,8 @@ class OptCompleter(Completer):
808
850
  )
809
851
 
810
852
  elif len(words) >= 2 and isinstance(opt_tree_pos_list[-2], Completer):
853
+ # 上上个单词进入独立提示
854
+
811
855
  new_nd: nested_dict = {}
812
856
  new_nd_pos: nested_dict = new_nd
813
857
  for word in words[:-2]:
@@ -837,19 +881,22 @@ class OptCompleter(Completer):
837
881
  ).get_completions(document=document, complete_event=complete_event)
838
882
 
839
883
  else:
884
+ # 没有独立提示
885
+
840
886
  yield from FuzzyCompleter(
841
887
  WordCompleter(
842
888
  words=tuple(
843
- opt_tree_pos_list[-1]
889
+ set(opt_tree_pos_list[-1])
844
890
  | (
845
- {}
891
+ set()
846
892
  if text.endswith(" ")
847
893
  or len(words) <= 1
848
894
  or isinstance(opt_tree_pos_list[-2], Completer)
849
- else opt_tree_pos_list[-2]
895
+ else set(opt_tree_pos_list[-2])
850
896
  )
897
+ | add_comp_words
851
898
  ),
852
- meta_dict=META_DICT_OPT_TYPE,
899
+ meta_dict=META_DICT_OPT_TYPE | add_comp_meta_dict,
853
900
  WORD=True, # 匹配标点
854
901
  match_middle=True,
855
902
  ),
@@ -5,7 +5,7 @@ from typing import Literal, get_origin, overload
5
5
 
6
6
  from ..easyrip_log import log
7
7
  from ..easyrip_mlang import all_supported_lang_map, gettext
8
- from ..global_val import CONFIG_DIR
8
+ from ..global_val import get_CONFIG_DIR
9
9
  from ..utils import type_match
10
10
  from .config_key import CONFIG_TYPE_DICT, CONFIG_VERSION, Config_key
11
11
 
@@ -33,7 +33,7 @@ class config:
33
33
 
34
34
  @classmethod
35
35
  def init(cls) -> None:
36
- cls._config_dir = CONFIG_DIR
36
+ cls._config_dir = get_CONFIG_DIR()
37
37
  cls._config_file = cls._config_dir / "config.json"
38
38
 
39
39
  if not cls._config_file.is_file():
@@ -221,13 +221,6 @@ def get_input_prompt(is_color: bool = False) -> str:
221
221
  return f"{os.path.realpath(os.getcwd())}> {cmd_prompt}"
222
222
 
223
223
 
224
- if os.name == "nt":
225
- try:
226
- ctypes.windll.user32.SetProcessDPIAware()
227
- except Exception:
228
- log.warning("Windows DPI Aware failed")
229
-
230
-
231
224
  def file_dialog(
232
225
  *,
233
226
  is_askdir: bool = False,
@@ -1086,6 +1079,12 @@ def run_command(command: Iterable[str] | str) -> bool:
1086
1079
 
1087
1080
 
1088
1081
  def init(is_first_run: bool = False) -> None:
1082
+ if os.name == "nt":
1083
+ try:
1084
+ ctypes.windll.user32.SetProcessDPIAware()
1085
+ except Exception:
1086
+ log.warning("Windows DPI Aware failed")
1087
+
1089
1088
  if is_first_run:
1090
1089
  # 当前路径添加到环境变量
1091
1090
  new_path = os.path.realpath(os.getcwd())
@@ -42,20 +42,20 @@ def translate_subtitles(
42
42
 
43
43
  file_list: Final[list[tuple[Path, str]]] = []
44
44
  for f in directory.iterdir():
45
- if f.suffix not in {".ass", ".ssa", ".srt"} or (
46
- file_intersection_selector is not None
47
- and f not in file_intersection_selector
45
+ if (
46
+ not f.is_file()
47
+ or f.suffix not in {".ass", ".ssa", ".srt"}
48
+ or (
49
+ file_intersection_selector is not None
50
+ and not all(map(f.samefile, file_intersection_selector))
51
+ )
48
52
  ):
49
53
  continue
50
54
 
51
- if len(_stems := f.stem.split(".")) < 1:
52
- continue
53
- if infix == _stems[-1]:
55
+ if (_stems := f.stem.split(".")) and (infix == _stems[-1]):
54
56
  file_list.append(
55
57
  (
56
- f.with_name(
57
- f"{'.'.join(f.stem.split('.')[:-1])}.{target_lang_tag}{f.suffix}"
58
- ),
58
+ f.with_name(f"{'.'.join(_stems[:-1])}.{target_lang_tag}{f.suffix}"),
59
59
  read_text(f),
60
60
  )
61
61
  )
@@ -5,11 +5,11 @@ from prompt_toolkit.completion import CompleteEvent, Completer, Completion
5
5
  from prompt_toolkit.document import Document
6
6
  from prompt_toolkit.history import FileHistory
7
7
 
8
- from .global_val import C_Z, CONFIG_DIR
8
+ from .global_val import C_Z, get_CONFIG_DIR
9
9
 
10
10
 
11
11
  class easyrip_prompt:
12
- PROMPT_HISTORY_FILE = CONFIG_DIR / "prompt_history.txt"
12
+ PROMPT_HISTORY_FILE = get_CONFIG_DIR() / "prompt_history.txt"
13
13
 
14
14
  @classmethod
15
15
  def clear(cls) -> None:
@@ -0,0 +1,29 @@
1
+ import os
2
+ import sys
3
+ from functools import cache
4
+ from pathlib import Path
5
+
6
+ PROJECT_NAME = "Easy Rip"
7
+ PROJECT_VERSION = "4.11.2"
8
+ PROJECT_TITLE = f"{PROJECT_NAME} v{PROJECT_VERSION}"
9
+ PROJECT_URL = "https://github.com/op200/EasyRip"
10
+ PROJECT_RELEASE_API = "https://api.github.com/repos/op200/EasyRip/releases/latest"
11
+
12
+
13
+ @cache
14
+ def get_CONFIG_DIR():
15
+ if sys.platform == "win32":
16
+ # Windows: C:\Users\<用户名>\AppData\Roaming\<app_name>
17
+ __config_dir = Path(os.getenv("APPDATA", ""))
18
+ elif sys.platform == "darwin":
19
+ # macOS: ~/Library/Application Support/<app_name>
20
+ __config_dir = Path(os.path.expanduser("~")) / "Library" / "Application Support"
21
+ else:
22
+ # Linux: ~/.config/<app_name>
23
+ __config_dir = Path(os.path.expanduser("~")) / ".config"
24
+
25
+ return Path(__config_dir) / PROJECT_NAME
26
+
27
+
28
+ C_D = "\x04"
29
+ C_Z = "\x1a"
@@ -434,7 +434,7 @@ DEFAULT_PRESET_PARAMS: Final[dict[Preset_name, dict[LiteralString, LiteralString
434
434
  {
435
435
  "crf": "17",
436
436
  "qpmin": "3",
437
- "qpmax": "21.5",
437
+ "qpmax": "23",
438
438
  "psy-rd": "2.2",
439
439
  "rd": "5",
440
440
  "rdoq-level": "2",
@@ -802,11 +802,42 @@ class Ripper:
802
802
  )
803
803
 
804
804
  case Ripper.Preset_name.subset:
805
+ # 临时翻译
806
+ add_tr_file_list: Final[list[Path]] = []
807
+ if translate_sub := self.option_map.get("translate-sub"):
808
+ _tr = translate_sub.split(":")
809
+ if len(_tr) != 2:
810
+ log.error("{} param illegal", "-translate-sub")
811
+ else:
812
+ try:
813
+ _file_list = translate_subtitles(
814
+ Path(self.output_dir),
815
+ _tr[0],
816
+ _tr[1],
817
+ file_intersection_selector=self.input_path_list,
818
+ )
819
+ except Exception as e:
820
+ log.error(e, is_format=False)
821
+ else:
822
+ for f_and_s in _file_list:
823
+ if f_and_s[0].is_file():
824
+ log.warning(
825
+ 'The file "{}" already exists, skip translating it',
826
+ f_and_s[0],
827
+ )
828
+ continue
829
+
830
+ with f_and_s[0].open(
831
+ "wt", encoding="utf-8-sig", newline="\n"
832
+ ) as f:
833
+ f.write(f_and_s[1])
834
+ add_tr_file_list.append(f_and_s[0])
835
+
805
836
  _output_dir = Path(self.output_dir) / basename
806
837
  _output_dir.mkdir(parents=True, exist_ok=True)
807
838
 
808
- _ass_list: list[Path] = []
809
- _other_sub_list: list[Path] = []
839
+ _ass_list: Final[list[Path]] = add_tr_file_list.copy()
840
+ _other_sub_list: Final[list[Path]] = []
810
841
 
811
842
  for path in self.input_path_list:
812
843
  if path.suffix == ".ass":
@@ -861,6 +892,13 @@ class Ripper:
861
892
  for path in _other_sub_list:
862
893
  shutil.copy2(path, _output_dir / path.name)
863
894
 
895
+ # 清理临时文件
896
+ for f in add_tr_file_list:
897
+ try:
898
+ f.unlink()
899
+ except Exception as e:
900
+ log.error(f"{e!r} {e}", deep=True, is_format=False)
901
+
864
902
  if subset_res is False:
865
903
  log.error("Run {} failed", "subset")
866
904
  return subset_res
@@ -1085,39 +1123,9 @@ class Ripper:
1085
1123
  log.warning("-soft-sub is empty")
1086
1124
  log.info("-soft-sub list = {}", soft_sub_list)
1087
1125
 
1088
- # 临时翻译
1089
- add_tr_files: Final[list[Path]] = []
1090
- if translate_sub := self.option_map.get("translate-sub"):
1091
- _tr = translate_sub.split(":")
1092
- if len(_tr) != 2:
1093
- log.error("{} param illegal", "-translate-sub")
1094
- else:
1095
- try:
1096
- _file_list = translate_subtitles(
1097
- Path(self.output_dir),
1098
- _tr[0],
1099
- _tr[1],
1100
- file_intersection_selector=soft_sub_list,
1101
- )
1102
- except Exception as e:
1103
- log.error(e, is_format=False)
1104
- else:
1105
- for f_and_s in _file_list:
1106
- if f_and_s[0].is_file():
1107
- log.warning(
1108
- 'The file "{}" already exists, skip translating it',
1109
- f_and_s[0],
1110
- )
1111
- continue
1112
- with f_and_s[0].open(
1113
- "wt", encoding="utf-8-sig", newline="\n"
1114
- ) as f:
1115
- f.write(f_and_s[1])
1116
- add_tr_files.append(f_and_s[0])
1117
-
1118
1126
  # 子集化
1119
1127
  if Ripper(
1120
- soft_sub_list + add_tr_files,
1128
+ soft_sub_list,
1121
1129
  (subset_folder.name,),
1122
1130
  self.output_dir,
1123
1131
  Ripper.Preset_name.subset,
@@ -1161,11 +1169,6 @@ class Ripper:
1161
1169
 
1162
1170
  # 清理临时文件
1163
1171
  shutil.rmtree(subset_folder)
1164
- for f in add_tr_files:
1165
- try:
1166
- f.unlink()
1167
- except Exception as e:
1168
- log.error(f"{e!r} {e}", deep=True, is_format=False)
1169
1172
 
1170
1173
  # 获取 ffmpeg report 中的报错
1171
1174
  if FF_REPORT_LOG_FILE.is_file():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: easyrip
3
- Version: 4.11.0
3
+ Version: 4.11.2
4
4
  Author: op200
5
5
  License-Expression: AGPL-3.0-or-later
6
6
  Project-URL: Homepage, https://github.com/op200/EasyRip
@@ -1,25 +0,0 @@
1
- import os
2
- import sys
3
- from pathlib import Path
4
-
5
- PROJECT_NAME = "Easy Rip"
6
- PROJECT_VERSION = "4.11.0"
7
- PROJECT_TITLE = f"{PROJECT_NAME} v{PROJECT_VERSION}"
8
- PROJECT_URL = "https://github.com/op200/EasyRip"
9
- PROJECT_RELEASE_API = "https://api.github.com/repos/op200/EasyRip/releases/latest"
10
-
11
-
12
- if sys.platform == "win32":
13
- # Windows: C:\Users\<用户名>\AppData\Roaming\<app_name>
14
- __config_dir = Path(os.getenv("APPDATA", ""))
15
- elif sys.platform == "darwin":
16
- # macOS: ~/Library/Application Support/<app_name>
17
- __config_dir = Path(os.path.expanduser("~")) / "Library" / "Application Support"
18
- else:
19
- # Linux: ~/.config/<app_name>
20
- __config_dir = Path(os.path.expanduser("~")) / ".config"
21
- CONFIG_DIR = Path(__config_dir) / PROJECT_NAME
22
-
23
-
24
- C_D = "\x04"
25
- C_Z = "\x1a"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes