ffmpeg-update 3.1.0__tar.gz → 3.1.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.
@@ -1,11 +1,12 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: ffmpeg-update
3
- Version: 3.1.0
3
+ Version: 3.1.2
4
4
  Summary: Package manager for FFmpeg, FFprobe, and FFplay static binaries
5
5
  Keywords: updater,installer,downloader,program,executable,binary,command,line,cli,tool
6
6
  Author: Asadullah Shaikh
7
7
  Classifier: Development Status :: 5 - Production/Stable
8
8
  Classifier: Environment :: Console
9
+ Classifier: Framework :: AsyncIO
9
10
  Classifier: Intended Audience :: Developers
10
11
  Classifier: Intended Audience :: End Users/Desktop
11
12
  Classifier: Intended Audience :: System Administrators
@@ -33,15 +34,12 @@ FFmpeg-update is a package manager for the FFmpeg suite, available as both a CLI
33
34
 
34
35
  # Features
35
36
 
36
- - Install [pre-built static binaries of] FFmpeg, FFprobe, and/or FFplay
37
- - Fetch latest *release* or *snapshot* builds
38
- - Configure custom installation location
39
- - Update to latest version
40
- - Check for updates
41
- - Uninstall from system
42
- - Progress bar with ETA
43
- - Smart permission handling
44
- - Atomic file system operations
37
+ - Atomic installation
38
+ - Concurrent downloads
39
+ - Download progress bars
40
+ - Configurable installation directory
41
+ - Latest *release* and *snapshot* builds available
42
+ - Automatic sudo escalation for privileged installation directory
45
43
  - Automatic operating system and machine architecture detection
46
44
 
47
45
  # Installation
@@ -63,7 +61,7 @@ ffup <install|update [--dry-run]|check|uninstall> [OPTIONS] [ffmpeg] [ffprobe] [
63
61
  Alternatively, can be invoked as a module with `python -m ffmpeg_update <COMMAND>`.
64
62
 
65
63
  > [!TIP]
66
- > Multiple names can be passed, e.g. `ffup install ffmpeg ffprobe`
64
+ > Multiple names can be passed, e.g., `ffup install ffmpeg ffprobe`
67
65
 
68
66
  > [!NOTE]
69
67
  > Default is `ffmpeg`, if no name is passed
@@ -71,39 +69,39 @@ Alternatively, can be invoked as a module with `python -m ffmpeg_update <COMMAND
71
69
  ## Parameters
72
70
 
73
71
  - `--dir`: The path to the installation directory
74
- - Environment variable: `$FFUP_DIR`/`$XDG_BIN_HOME`
75
72
  - Default: `~/.local/bin`
76
- - Functions: `check`, `install`, `uninstall`, `update`
73
+ - Environment variable: `$FFUP_DIR`, `$XDG_BIN_HOME`
74
+ - Commands: `check`, `install`, `uninstall`, `update`
77
75
 
78
76
  - `--build`: The build type
77
+ - Default: `snapshot`
79
78
  - Choices: `release`, `snapshot`
80
79
  - Environment Variable: `$FFUP_BUILD`
81
- - Default: `snapshot`
82
- - Functions: `check`, `install`, `update`
80
+ - Commands: `check`, `install`, `update`
83
81
 
84
82
  - `--arch`: The machine architecture
83
+ - Default: Auto-detect using `platform.machine()`
85
84
  - Choices: `amd64`, `arm64`
86
85
  - Environment Variable: `$FFUP_ARCH`
87
- - Default: Auto-detect using `platform.machine()`
88
- - Functions: `check`, `install`, `update`
86
+ - Commands: `check`, `install`, `update`
89
87
 
90
88
  - `--os`: The operating system
89
+ - Default: Auto-detect using `platform.system()`
91
90
  - Choices: `linux`, `macos`
92
91
  - Environment Variable: `$FFUP_OS`
93
- - Default: Auto-detect using `platform.system()`
94
- - Functions: `check`, `install`, `update`
92
+ - Commands: `check`, `install`, `update`
95
93
 
96
94
  - `--dry-run`: A flag to skip download/install, and only check for updates
97
- - `ffup check` is an alias for `ffup update --dry-run`
98
95
  - Default: `False`
99
- - Functions: `update`
96
+ - Commands: `update`
97
+ - Note: `ffup check` is an alias for `ffup update --dry-run`
100
98
 
101
99
  # API Reference
102
100
 
103
101
  ## Functions
104
102
 
105
- - `update(bins = {"ffmpeg"}, /, *, dry_run = False, dir, tempdir, progress, client) -> None`
106
- - `install(bins = {"ffmpeg"}, /, *, dir, tempdir, progress, client) -> None`
103
+ - async `update(bins = {"ffmpeg"}, /, *, dry_run = False, dir, tempdir, progress, client) -> None`
104
+ - async `install(bins = {"ffmpeg"}, /, *, dir, tempdir, progress, client) -> None`
107
105
  - `uninstall(bins = {"ffmpeg"}, /, *, dir) -> None`
108
106
  - `get_arch() -> Literal["amd64", "arm64"]`
109
107
  - `get_os() -> Literal["linux", "macos"]`
@@ -120,26 +118,8 @@ Alternatively, can be invoked as a module with `python -m ffmpeg_update <COMMAND
120
118
  >
121
119
  > - `progress`: A `rich.progress.Progress` used to show progress bars in the terminal
122
120
  >
123
- > - `client`: A `niquests.Session` used to make HTTP requests
121
+ > - `client`: A `niquests.AsyncSession` used to make HTTP requests
124
122
  > - Must set parameter `base_url` to `f"https://ffmpeg.martin-riedl.de/redirect/latest/{os}/{arch}/{build}/"`
125
123
  > - `build`: `"release"`, `"snapshot"`
126
124
  > - `arch`: `"amd64"`, `"arm64"`
127
125
  > - `os`: `"linux"`, `"macos"`
128
-
129
- # Error Handling
130
-
131
- ## `FileNotFoundError`
132
-
133
- - By design, all operations will fail if the path in question does not exist
134
- - For new installations, ensure that the installation directory exists
135
- - For other operations, ensure that the path points to the installed binary
136
-
137
- ## `HTTPError`
138
-
139
- - `404 Client Error: Not Found for url: ...`
140
- - Caused by invalid values for one or more of `build`, `arch`, and `os` parameters
141
-
142
- ## `PermissionError`
143
-
144
- - Triggers automatic escalation via `sudo`
145
- - The user is prompted for a password at `stdin`
@@ -5,15 +5,12 @@ FFmpeg-update is a package manager for the FFmpeg suite, available as both a CLI
5
5
 
6
6
  # Features
7
7
 
8
- - Install [pre-built static binaries of] FFmpeg, FFprobe, and/or FFplay
9
- - Fetch latest *release* or *snapshot* builds
10
- - Configure custom installation location
11
- - Update to latest version
12
- - Check for updates
13
- - Uninstall from system
14
- - Progress bar with ETA
15
- - Smart permission handling
16
- - Atomic file system operations
8
+ - Atomic installation
9
+ - Concurrent downloads
10
+ - Download progress bars
11
+ - Configurable installation directory
12
+ - Latest *release* and *snapshot* builds available
13
+ - Automatic sudo escalation for privileged installation directory
17
14
  - Automatic operating system and machine architecture detection
18
15
 
19
16
  # Installation
@@ -35,7 +32,7 @@ ffup <install|update [--dry-run]|check|uninstall> [OPTIONS] [ffmpeg] [ffprobe] [
35
32
  Alternatively, can be invoked as a module with `python -m ffmpeg_update <COMMAND>`.
36
33
 
37
34
  > [!TIP]
38
- > Multiple names can be passed, e.g. `ffup install ffmpeg ffprobe`
35
+ > Multiple names can be passed, e.g., `ffup install ffmpeg ffprobe`
39
36
 
40
37
  > [!NOTE]
41
38
  > Default is `ffmpeg`, if no name is passed
@@ -43,39 +40,39 @@ Alternatively, can be invoked as a module with `python -m ffmpeg_update <COMMAND
43
40
  ## Parameters
44
41
 
45
42
  - `--dir`: The path to the installation directory
46
- - Environment variable: `$FFUP_DIR`/`$XDG_BIN_HOME`
47
43
  - Default: `~/.local/bin`
48
- - Functions: `check`, `install`, `uninstall`, `update`
44
+ - Environment variable: `$FFUP_DIR`, `$XDG_BIN_HOME`
45
+ - Commands: `check`, `install`, `uninstall`, `update`
49
46
 
50
47
  - `--build`: The build type
48
+ - Default: `snapshot`
51
49
  - Choices: `release`, `snapshot`
52
50
  - Environment Variable: `$FFUP_BUILD`
53
- - Default: `snapshot`
54
- - Functions: `check`, `install`, `update`
51
+ - Commands: `check`, `install`, `update`
55
52
 
56
53
  - `--arch`: The machine architecture
54
+ - Default: Auto-detect using `platform.machine()`
57
55
  - Choices: `amd64`, `arm64`
58
56
  - Environment Variable: `$FFUP_ARCH`
59
- - Default: Auto-detect using `platform.machine()`
60
- - Functions: `check`, `install`, `update`
57
+ - Commands: `check`, `install`, `update`
61
58
 
62
59
  - `--os`: The operating system
60
+ - Default: Auto-detect using `platform.system()`
63
61
  - Choices: `linux`, `macos`
64
62
  - Environment Variable: `$FFUP_OS`
65
- - Default: Auto-detect using `platform.system()`
66
- - Functions: `check`, `install`, `update`
63
+ - Commands: `check`, `install`, `update`
67
64
 
68
65
  - `--dry-run`: A flag to skip download/install, and only check for updates
69
- - `ffup check` is an alias for `ffup update --dry-run`
70
66
  - Default: `False`
71
- - Functions: `update`
67
+ - Commands: `update`
68
+ - Note: `ffup check` is an alias for `ffup update --dry-run`
72
69
 
73
70
  # API Reference
74
71
 
75
72
  ## Functions
76
73
 
77
- - `update(bins = {"ffmpeg"}, /, *, dry_run = False, dir, tempdir, progress, client) -> None`
78
- - `install(bins = {"ffmpeg"}, /, *, dir, tempdir, progress, client) -> None`
74
+ - async `update(bins = {"ffmpeg"}, /, *, dry_run = False, dir, tempdir, progress, client) -> None`
75
+ - async `install(bins = {"ffmpeg"}, /, *, dir, tempdir, progress, client) -> None`
79
76
  - `uninstall(bins = {"ffmpeg"}, /, *, dir) -> None`
80
77
  - `get_arch() -> Literal["amd64", "arm64"]`
81
78
  - `get_os() -> Literal["linux", "macos"]`
@@ -92,26 +89,8 @@ Alternatively, can be invoked as a module with `python -m ffmpeg_update <COMMAND
92
89
  >
93
90
  > - `progress`: A `rich.progress.Progress` used to show progress bars in the terminal
94
91
  >
95
- > - `client`: A `niquests.Session` used to make HTTP requests
92
+ > - `client`: A `niquests.AsyncSession` used to make HTTP requests
96
93
  > - Must set parameter `base_url` to `f"https://ffmpeg.martin-riedl.de/redirect/latest/{os}/{arch}/{build}/"`
97
94
  > - `build`: `"release"`, `"snapshot"`
98
95
  > - `arch`: `"amd64"`, `"arm64"`
99
96
  > - `os`: `"linux"`, `"macos"`
100
-
101
- # Error Handling
102
-
103
- ## `FileNotFoundError`
104
-
105
- - By design, all operations will fail if the path in question does not exist
106
- - For new installations, ensure that the installation directory exists
107
- - For other operations, ensure that the path points to the installed binary
108
-
109
- ## `HTTPError`
110
-
111
- - `404 Client Error: Not Found for url: ...`
112
- - Caused by invalid values for one or more of `build`, `arch`, and `os` parameters
113
-
114
- ## `PermissionError`
115
-
116
- - Triggers automatic escalation via `sudo`
117
- - The user is prompted for a password at `stdin`
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ffmpeg-update"
3
- version = "3.1.0"
3
+ version = "3.1.2"
4
4
  description = "Package manager for FFmpeg, FFprobe, and FFplay static binaries"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -11,6 +11,7 @@ keywords = ["updater", "installer", "downloader", "program", "executable", "bina
11
11
  classifiers = [
12
12
  "Development Status :: 5 - Production/Stable",
13
13
  "Environment :: Console",
14
+ "Framework :: AsyncIO",
14
15
  "Intended Audience :: Developers",
15
16
  "Intended Audience :: End Users/Desktop",
16
17
  "Intended Audience :: System Administrators",
@@ -73,21 +73,20 @@ async def update(
73
73
  progress: Annotated[Progress, Parameter(parse=False)],
74
74
  client: Annotated[AsyncSession, Parameter(parse=False)],
75
75
  ) -> None:
76
- with progress:
77
- for bin in bins.copy():
78
- current = _current(dir / bin)
79
- latest = await _latest(bin, client)
80
- print(f"{_fmt_FF(bin)}:\n\tCurrent: {current}\n\tLatest: {latest}")
81
- if current != latest:
82
- print(f"{_fmt_FF(bin)}: update available")
83
- else:
84
- bins.remove(bin)
85
- print(f"{_fmt_FF(bin)}: up to date")
86
-
87
- if not dry_run and bins:
88
- await install(
89
- bins, dir=dir, tempdir=tempdir, progress=progress, client=client
90
- )
76
+ bin_lst = list(bins)
77
+ latest, *current_lst = await asyncio.gather(
78
+ _latest("ffmpeg", client), *[_current(dir / bin) for bin in bin_lst]
79
+ )
80
+ print(f"Latest Version: {latest}")
81
+ for bin, current in zip(bin_lst, current_lst):
82
+ if current != latest:
83
+ print(f"{_fmt_FF(bin)}: update available")
84
+ else:
85
+ bins.remove(bin)
86
+ print(f"{_fmt_FF(bin)}: up to date")
87
+
88
+ if not dry_run and bins:
89
+ await install(bins, dir=dir, tempdir=tempdir, progress=progress, client=client)
91
90
 
92
91
 
93
92
  @app.command
@@ -159,24 +158,24 @@ def get_os() -> OSType:
159
158
  raise RuntimeError(f"unsupported operating system '{os}'")
160
159
 
161
160
 
162
- def _current(path):
163
- output = subprocess.check_output([path, "-version"], text=True)
164
- match = re.search(r"version (N-\d+-\w+|\d\.\d(\.\d)?)", output)
161
+ async def _current(path):
162
+ process = await asyncio.create_subprocess_exec(
163
+ path, "-version", stdout=asyncio.subprocess.PIPE
164
+ )
165
+ stdout, _ = await process.communicate()
166
+ match = re.search(r"version (N-\d+-\w+|\d\.\d(\.\d)?)", stdout.decode())
165
167
  if match is None:
166
- raise ValueError(f"failed to parse version from `{path} -version` output")
168
+ raise ValueError(f"failed to parse version from `{path} -version`")
167
169
  return match.group(1)
168
170
 
169
171
 
170
172
  async def _latest(bin, client):
171
- response = await client.get(f"{bin}.zip", allow_redirects=False)
173
+ response = await client.get(f"{bin}.zip", allow_redirects=False, stream=True)
172
174
  response.raise_for_status()
173
- if response.status_code == 307:
174
- match = re.search(r"_(N-\d+-\w+|\d\.\d(\.\d)?)", response.headers["location"])
175
- if match is None:
176
- raise ValueError("failed to parse version from HTTP response")
177
- return match.group(1)
178
- else:
179
- raise ValueError(f"unexpected {response}")
175
+ match = re.search(r"_(N-\d+-\w+|\d\.\d(\.\d)?)", response.headers["location"])
176
+ if match is None:
177
+ raise ValueError(f"failed to parse version from {response}")
178
+ return match.group(1)
180
179
 
181
180
 
182
181
  async def _download(bin, tempdir, progress, client):