subextract 0.2.0__tar.gz → 0.3.0__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.
@@ -0,0 +1,18 @@
1
+ Metadata-Version: 2.4
2
+ Name: subextract
3
+ Version: 0.3.0
4
+ Summary: CLI for easy extraction of subtitles from mkv files
5
+ Keywords: subtitle,cli,media,mkv
6
+ Author: disrupted
7
+ Author-email: disrupted <hi@salomonpopp.me>
8
+ License-Expression: GPL-3.0-only
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Environment :: Console
12
+ Classifier: Typing :: Typed
13
+ Requires-Dist: langcodes>=3.5.1
14
+ Requires-Dist: pyyaml>=6.0.3
15
+ Requires-Python: >=3.15
16
+ Project-URL: Homepage, https://github.com/disrupted/subextract
17
+ Project-URL: Repository, https://github.com/disrupted/subextract
18
+ Project-URL: Issues, https://github.com/disrupted/subextract/issues
@@ -0,0 +1,106 @@
1
+ [project]
2
+ name = "subextract"
3
+ version = "0.3.0"
4
+ description = "CLI for easy extraction of subtitles from mkv files"
5
+ license = "GPL-3.0-only"
6
+ requires-python = ">=3.15"
7
+ keywords = [
8
+ "subtitle",
9
+ "cli",
10
+ "media",
11
+ "mkv",
12
+ ]
13
+ classifiers = [
14
+ "Programming Language :: Python :: 3",
15
+ "Operating System :: OS Independent",
16
+ "Environment :: Console",
17
+ "Typing :: Typed",
18
+ ]
19
+ dependencies = [
20
+ "langcodes>=3.5.1",
21
+ "pyyaml>=6.0.3",
22
+ ]
23
+
24
+ [[project.authors]]
25
+ name = "disrupted"
26
+ email = "hi@salomonpopp.me"
27
+
28
+ [project.urls]
29
+ Homepage = "https://github.com/disrupted/subextract"
30
+ Repository = "https://github.com/disrupted/subextract"
31
+ Issues = "https://github.com/disrupted/subextract/issues"
32
+
33
+ [project.scripts]
34
+ subextract = "subextract.cli:main"
35
+
36
+ [dependency-groups]
37
+ dev = [
38
+ "pytest>=9.2.0",
39
+ "ruff>=0.17.4",
40
+ "ty>=0.0.101",
41
+ ]
42
+
43
+ [build-system]
44
+ requires = ["uv_build>=0.13.7,<0.14"]
45
+ build-backend = "uv_build"
46
+
47
+ [tool.ty.src]
48
+ include = [
49
+ "subextract",
50
+ "tests",
51
+ ]
52
+
53
+ [tool.ty.environment]
54
+ python-version = "3.15"
55
+
56
+ [tool.ruff]
57
+ output-format = "grouped"
58
+ show-fixes = true
59
+ target-version = "py315"
60
+
61
+ [tool.ruff.lint]
62
+ select = [
63
+ "F",
64
+ "E",
65
+ "W",
66
+ "C90",
67
+ "I",
68
+ "UP",
69
+ "B",
70
+ "RUF",
71
+ "YTT",
72
+ "BLE",
73
+ "C4",
74
+ "T10",
75
+ "EM",
76
+ "ISC",
77
+ "ICN",
78
+ "INP",
79
+ "PIE",
80
+ "RSE",
81
+ "RET",
82
+ "SLOT",
83
+ "SIM",
84
+ "PTH",
85
+ "PGH",
86
+ "PL",
87
+ "TRY",
88
+ ]
89
+ ignore = [
90
+ "E501",
91
+ "ISC001",
92
+ "PLR09",
93
+ "PLR2004",
94
+ "TRY003",
95
+ "RET504",
96
+ "RET505",
97
+ "RUF001",
98
+ "PLW2901",
99
+ ]
100
+
101
+ [tool.uv]
102
+ package = true
103
+ trusted-publishing = "always"
104
+
105
+ [tool.uv.build-backend]
106
+ module-root = ""
@@ -0,0 +1,97 @@
1
+ [project]
2
+ name = "subextract"
3
+ version = "0.3.0"
4
+ description = "CLI for easy extraction of subtitles from mkv files"
5
+ license = "GPL-3.0-only"
6
+ requires-python = ">=3.15"
7
+ authors = [
8
+ { name = "disrupted", email = "hi@salomonpopp.me" },
9
+ ]
10
+ keywords = ["subtitle", "cli", "media", "mkv"]
11
+ classifiers = [
12
+ "Programming Language :: Python :: 3",
13
+ "Operating System :: OS Independent",
14
+ "Environment :: Console",
15
+ "Typing :: Typed",
16
+ ]
17
+ dependencies = [
18
+ "langcodes>=3.5.1",
19
+ "pyyaml>=6.0.3",
20
+ ]
21
+
22
+ [project.urls]
23
+ Homepage = "https://github.com/disrupted/subextract"
24
+ Repository = "https://github.com/disrupted/subextract"
25
+ Issues = "https://github.com/disrupted/subextract/issues"
26
+
27
+ [project.scripts]
28
+ subextract = "subextract.cli:main"
29
+
30
+ [dependency-groups]
31
+ dev = [
32
+ "pytest>=9.2.0",
33
+ "ruff>=0.17.4",
34
+ "ty>=0.0.101",
35
+ ]
36
+
37
+ [build-system]
38
+ requires = ["uv_build>=0.13.7,<0.14"]
39
+ build-backend = "uv_build"
40
+
41
+ [tool.uv.build-backend]
42
+ module-root = ""
43
+
44
+ [tool.ty]
45
+ src = { include = ["subextract", "tests"] }
46
+
47
+ [tool.ty.environment]
48
+ python-version = "3.15"
49
+
50
+ [tool.ruff]
51
+ output-format = "grouped"
52
+ show-fixes = true
53
+ target-version = "py315"
54
+
55
+ [tool.ruff.lint]
56
+ select = [
57
+ "F",
58
+ "E",
59
+ "W",
60
+ "C90",
61
+ "I",
62
+ "UP",
63
+ "B",
64
+ "RUF",
65
+ "YTT",
66
+ "BLE",
67
+ "C4",
68
+ "T10",
69
+ "EM",
70
+ "ISC",
71
+ "ICN",
72
+ "INP",
73
+ "PIE",
74
+ "RSE",
75
+ "RET",
76
+ "SLOT",
77
+ "SIM",
78
+ "PTH",
79
+ "PGH",
80
+ "PL",
81
+ "TRY",
82
+ ]
83
+ ignore = [
84
+ "E501",
85
+ "ISC001",
86
+ "PLR09",
87
+ "PLR2004",
88
+ "TRY003",
89
+ "RET504",
90
+ "RET505",
91
+ "RUF001",
92
+ "PLW2901",
93
+ ]
94
+
95
+ [tool.uv]
96
+ package = true
97
+ trusted-publishing = "always"
@@ -9,7 +9,7 @@ from pathlib import Path
9
9
  import yaml
10
10
 
11
11
  from . import __version__
12
- from .language import Language
12
+ from .language import DEFAULT_LANGUAGE, Language
13
13
 
14
14
  parser = argparse.ArgumentParser(description="Extract subtitles from MKV files")
15
15
  parser.add_argument(
@@ -34,9 +34,9 @@ parser.add_argument(
34
34
  )
35
35
  parser.add_argument(
36
36
  "--lang",
37
- type=Language,
38
37
  help="Language to extract (default: en)",
39
- default=Language("en"),
38
+ type=Language.from_str,
39
+ default=DEFAULT_LANGUAGE,
40
40
  )
41
41
  parser.add_argument(
42
42
  "--sdh",
@@ -50,7 +50,7 @@ parser.add_argument(
50
50
  "file",
51
51
  nargs="+",
52
52
  metavar="FILE",
53
- type=argparse.FileType("r"),
53
+ type=Path,
54
54
  help="the .mkv video file",
55
55
  )
56
56
 
@@ -62,13 +62,13 @@ def mkvextract(track_id: int, path: Path, out_filename: str):
62
62
  "tracks",
63
63
  f"{track_id}:{path.with_name(out_filename)}",
64
64
  ]
65
- proc = subprocess.run(mkvextract_args)
65
+ proc = subprocess.run(mkvextract_args, check=True)
66
66
  return proc
67
67
 
68
68
 
69
69
  def identify(path: Path) -> dict:
70
70
  mkvmerge_args = ["mkvmerge", "-F", "json", "-i", path]
71
- proc = subprocess.run(mkvmerge_args, stdout=subprocess.PIPE)
71
+ proc = subprocess.run(mkvmerge_args, stdout=subprocess.PIPE, check=True)
72
72
  return json.loads(proc.stdout)
73
73
 
74
74
 
@@ -87,7 +87,7 @@ def is_sdh(track: dict, sdh: bool) -> bool:
87
87
 
88
88
 
89
89
  def get_out_name(path: Path, track: dict) -> str:
90
- lang = Language(track["properties"]["language"]).alpha1
90
+ lang = Language.from_str(track["properties"]["language"]).alpha1
91
91
  return f"{path.stem}.{lang}.srt"
92
92
 
93
93
 
@@ -100,7 +100,7 @@ def extract(path: Path, track: dict):
100
100
 
101
101
  def main():
102
102
  args = parser.parse_args()
103
- if args.id and (args.lang or args.sdh):
103
+ if args.id and (args.lang != DEFAULT_LANGUAGE or args.sdh):
104
104
  parser.error("--id and --lang|--sdh are mutually exclusive")
105
105
 
106
106
  logging.basicConfig(
@@ -108,9 +108,8 @@ def main():
108
108
  format="%(levelname)s | %(message)s",
109
109
  )
110
110
 
111
- for f in args.file:
112
- path = Path(f.name)
113
- if path.suffix not in ".mkv":
111
+ for path in args.file:
112
+ if path.suffix != ".mkv":
114
113
  logging.error(f"wrong file extension {path.suffix}")
115
114
  sys.exit(1)
116
115
 
@@ -120,7 +119,7 @@ def main():
120
119
  try:
121
120
  tracks = [data["tracks"][args.id]]
122
121
  except IndexError:
123
- logging.error(f"subtitle with id {args.id} doesn't exist")
122
+ logging.exception(f"subtitle with id {args.id} doesn't exist")
124
123
  sys.exit(1)
125
124
  else:
126
125
  tracks = [
@@ -0,0 +1,27 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ import langcodes
6
+
7
+
8
+ @dataclass(frozen=True)
9
+ class Language:
10
+ _lang: langcodes.Language
11
+
12
+ @staticmethod
13
+ def from_str(lang: str) -> Language:
14
+ return Language(langcodes.Language.get(lang))
15
+
16
+ @property
17
+ def alpha1(self):
18
+ """en"""
19
+ return self._lang.to_tag()
20
+
21
+ @property
22
+ def alpha2(self):
23
+ """eng"""
24
+ return self._lang.to_alpha3(variant="B")
25
+
26
+
27
+ DEFAULT_LANGUAGE = Language.from_str(langcodes.DEFAULT_LANGUAGE)
subextract-0.2.0/PKG-INFO DELETED
@@ -1,14 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: subextract
3
- Version: 0.2.0
4
- Summary: CLI for easy extraction of subtitles from mkv files
5
- License: GPL-3.0
6
- Author: disrupted
7
- Author-email: hi@salomonpopp.me
8
- Requires-Python: >=3.9,<4.0
9
- Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.9
13
- Requires-Dist: PyYAML (>=6.0,<7.0)
14
- Requires-Dist: langcodes (>=3.3.0,<4.0.0)
@@ -1,20 +0,0 @@
1
- [tool.poetry]
2
- name = "subextract"
3
- version = "0.2.0"
4
- description = "CLI for easy extraction of subtitles from mkv files"
5
- authors = ["disrupted <hi@salomonpopp.me>"]
6
- license = "GPL-3.0"
7
-
8
- [tool.poetry.scripts]
9
- subextract = 'subextract.cli:main'
10
-
11
- [tool.poetry.dependencies]
12
- python = "^3.9"
13
- PyYAML = "^6.0"
14
- langcodes = "^3.3.0"
15
-
16
- [tool.poetry.dev-dependencies]
17
-
18
- [build-system]
19
- requires = ["poetry-core>=1.0.0"]
20
- build-backend = "poetry.core.masonry.api"
subextract-0.2.0/setup.py DELETED
@@ -1,34 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- from setuptools import setup
3
-
4
- packages = \
5
- ['subextract']
6
-
7
- package_data = \
8
- {'': ['*']}
9
-
10
- install_requires = \
11
- ['PyYAML>=6.0,<7.0', 'langcodes>=3.3.0,<4.0.0']
12
-
13
- entry_points = \
14
- {'console_scripts': ['subextract = subextract.cli:main']}
15
-
16
- setup_kwargs = {
17
- 'name': 'subextract',
18
- 'version': '0.2.0',
19
- 'description': 'CLI for easy extraction of subtitles from mkv files',
20
- 'long_description': None,
21
- 'author': 'disrupted',
22
- 'author_email': 'hi@salomonpopp.me',
23
- 'maintainer': None,
24
- 'maintainer_email': None,
25
- 'url': None,
26
- 'packages': packages,
27
- 'package_data': package_data,
28
- 'install_requires': install_requires,
29
- 'entry_points': entry_points,
30
- 'python_requires': '>=3.9,<4.0',
31
- }
32
-
33
-
34
- setup(**setup_kwargs)
@@ -1,16 +0,0 @@
1
- import langcodes
2
-
3
-
4
- class Language:
5
- def __init__(self, lang: str):
6
- self._lang = langcodes.Language.get(lang)
7
-
8
- @property
9
- def alpha1(self):
10
- """en"""
11
- return self._lang.to_tag()
12
-
13
- @property
14
- def alpha2(self):
15
- """eng"""
16
- return self._lang.to_alpha3(variant="B")