pystand 2.32__tar.gz → 2.34__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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pystand
3
- Version: 2.32
3
+ Version: 2.34
4
4
  Summary: Install Python versions from python-build-standalone project
5
5
  Author-email: Mark Blakeney <mark.blakeney@bullet-systems.net>
6
6
  License-Expression: GPL-3.0-or-later
@@ -15,7 +15,7 @@ Requires-Dist: argparse-from-file
15
15
  Requires-Dist: pygithub
16
16
  Requires-Dist: certifi
17
17
  Requires-Dist: filelock
18
- Requires-Dist: zstandard; python_version < "3.14"
18
+ Requires-Dist: backports.zstd; python_version < "3.14"
19
19
 
20
20
  ## PYSTAND - Install Python Versions From The Python-Build-Standalone Project
21
21
  [![PyPi](https://img.shields.io/pypi/v/pystand)](https://pypi.org/project/pystand/)
@@ -172,7 +172,7 @@ options:
172
172
  --purge-days PURGE_DAYS
173
173
  cache YYYYMMDD release file lists and downloads for
174
174
  this number of days after last version referencing
175
- that release is removed. Default is 90 days.
175
+ that release is removed. Default is 30 days.
176
176
  --github-access-token GITHUB_ACCESS_TOKEN
177
177
  optional Github access token. Can specify to reduce
178
178
  rate limiting.
@@ -215,13 +215,13 @@ usage: pystand install [-h] [-r RELEASE] [-a] [-A] [--skip] [-f] [-s]
215
215
  Install one, more, or all versions from a python-build-standalone release.
216
216
 
217
217
  positional arguments:
218
- version version to install. E.g. 3.12 or 3.12.3
218
+ version version to install. E.g. 3.14 or 3.14.1
219
219
 
220
220
  options:
221
221
  -h, --help show this help message and exit
222
222
  -r, --release RELEASE
223
223
  install from specified python-build-standalone
224
- YYYYMMDD release (e.g. 20240415), default is latest
224
+ YYYYMMDD release (e.g. 20260807), default is latest
225
225
  release
226
226
  -a, --all install ALL versions from release
227
227
  -A, --all-prerelease install ALL versions from release, including pre-
@@ -238,7 +238,8 @@ aliases: i
238
238
  ### Command `update`
239
239
 
240
240
  ```
241
- usage: pystand update [-h] [-r RELEASE] [-a] [--skip] [-k] [version ...]
241
+ usage: pystand update [-h] [-r RELEASE] [-a] [--pre-release] [--skip] [-k]
242
+ [version ...]
242
243
 
243
244
  Update one, more, or all versions to another release.
244
245
 
@@ -248,9 +249,11 @@ positional arguments:
248
249
  options:
249
250
  -h, --help show this help message and exit
250
251
  -r, --release RELEASE
251
- update to specified YYYMMDD release (e.g. 20240415),
252
+ update to specified YYYMMDD release (e.g. 20260807),
252
253
  default is latest release
253
254
  -a, --all update ALL versions
255
+ --pre-release update release version to a later superceding pre-
256
+ release
254
257
  --skip skip the specified versions when updating all (only
255
258
  can be specified with --all)
256
259
  -k, --keep keep old version after updating (but only if different
@@ -276,7 +279,7 @@ options:
276
279
  can be specified with --all)
277
280
  -r, --release RELEASE
278
281
  only remove versions if from specified YYYMMDD release
279
- (e.g. 20240415)
282
+ (e.g. 20260807)
280
283
 
281
284
  aliases: r, rm
282
285
  ```
@@ -296,7 +299,7 @@ options:
296
299
  -v, --verbose explicitly report why a version is not eligible for
297
300
  update
298
301
  -r, --release RELEASE
299
- use specified YYYYMMDD release (e.g. 20240415) for
302
+ use specified YYYYMMDD release (e.g. 20260807) for
300
303
  verbose compare, default is latest release
301
304
 
302
305
  aliases: l
@@ -320,7 +323,7 @@ options:
320
323
  -l, --list just list recent releases
321
324
  -r, --release RELEASE
322
325
  python-build-standalone YYYYMMDD release to show (e.g.
323
- 20240415), default is latest release
326
+ 20260807), default is latest release
324
327
  -a, --all show all available distributions for each version from
325
328
  the release
326
329
 
@@ -387,7 +390,7 @@ positional arguments:
387
390
 
388
391
  options:
389
392
  -h, --help show this help message and exit
390
- -p, --python PYTHON version of python to use, e.g. "3.12", default is
393
+ -p, --python PYTHON version of python to use, e.g. "3.14", default is
391
394
  latest release version
392
395
  ```
393
396
 
@@ -405,7 +408,7 @@ positional arguments:
405
408
 
406
409
  options:
407
410
  -h, --help show this help message and exit
408
- -p, --python PYTHON version of python to use, e.g. "3.12", default is
411
+ -p, --python PYTHON version of python to use, e.g. "3.14", default is
409
412
  latest release version
410
413
  ```
411
414
 
@@ -153,7 +153,7 @@ options:
153
153
  --purge-days PURGE_DAYS
154
154
  cache YYYYMMDD release file lists and downloads for
155
155
  this number of days after last version referencing
156
- that release is removed. Default is 90 days.
156
+ that release is removed. Default is 30 days.
157
157
  --github-access-token GITHUB_ACCESS_TOKEN
158
158
  optional Github access token. Can specify to reduce
159
159
  rate limiting.
@@ -196,13 +196,13 @@ usage: pystand install [-h] [-r RELEASE] [-a] [-A] [--skip] [-f] [-s]
196
196
  Install one, more, or all versions from a python-build-standalone release.
197
197
 
198
198
  positional arguments:
199
- version version to install. E.g. 3.12 or 3.12.3
199
+ version version to install. E.g. 3.14 or 3.14.1
200
200
 
201
201
  options:
202
202
  -h, --help show this help message and exit
203
203
  -r, --release RELEASE
204
204
  install from specified python-build-standalone
205
- YYYYMMDD release (e.g. 20240415), default is latest
205
+ YYYYMMDD release (e.g. 20260807), default is latest
206
206
  release
207
207
  -a, --all install ALL versions from release
208
208
  -A, --all-prerelease install ALL versions from release, including pre-
@@ -219,7 +219,8 @@ aliases: i
219
219
  ### Command `update`
220
220
 
221
221
  ```
222
- usage: pystand update [-h] [-r RELEASE] [-a] [--skip] [-k] [version ...]
222
+ usage: pystand update [-h] [-r RELEASE] [-a] [--pre-release] [--skip] [-k]
223
+ [version ...]
223
224
 
224
225
  Update one, more, or all versions to another release.
225
226
 
@@ -229,9 +230,11 @@ positional arguments:
229
230
  options:
230
231
  -h, --help show this help message and exit
231
232
  -r, --release RELEASE
232
- update to specified YYYMMDD release (e.g. 20240415),
233
+ update to specified YYYMMDD release (e.g. 20260807),
233
234
  default is latest release
234
235
  -a, --all update ALL versions
236
+ --pre-release update release version to a later superceding pre-
237
+ release
235
238
  --skip skip the specified versions when updating all (only
236
239
  can be specified with --all)
237
240
  -k, --keep keep old version after updating (but only if different
@@ -257,7 +260,7 @@ options:
257
260
  can be specified with --all)
258
261
  -r, --release RELEASE
259
262
  only remove versions if from specified YYYMMDD release
260
- (e.g. 20240415)
263
+ (e.g. 20260807)
261
264
 
262
265
  aliases: r, rm
263
266
  ```
@@ -277,7 +280,7 @@ options:
277
280
  -v, --verbose explicitly report why a version is not eligible for
278
281
  update
279
282
  -r, --release RELEASE
280
- use specified YYYYMMDD release (e.g. 20240415) for
283
+ use specified YYYYMMDD release (e.g. 20260807) for
281
284
  verbose compare, default is latest release
282
285
 
283
286
  aliases: l
@@ -301,7 +304,7 @@ options:
301
304
  -l, --list just list recent releases
302
305
  -r, --release RELEASE
303
306
  python-build-standalone YYYYMMDD release to show (e.g.
304
- 20240415), default is latest release
307
+ 20260807), default is latest release
305
308
  -a, --all show all available distributions for each version from
306
309
  the release
307
310
 
@@ -368,7 +371,7 @@ positional arguments:
368
371
 
369
372
  options:
370
373
  -h, --help show this help message and exit
371
- -p, --python PYTHON version of python to use, e.g. "3.12", default is
374
+ -p, --python PYTHON version of python to use, e.g. "3.14", default is
372
375
  latest release version
373
376
  ```
374
377
 
@@ -386,7 +389,7 @@ positional arguments:
386
389
 
387
390
  options:
388
391
  -h, --help show this help message and exit
389
- -p, --python PYTHON version of python to use, e.g. "3.12", default is
392
+ -p, --python PYTHON version of python to use, e.g. "3.14", default is
390
393
  latest release version
391
394
  ```
392
395
 
@@ -1,13 +1,12 @@
1
- #!/usr/bin/python
2
1
  import re
3
2
  import subprocess
4
3
  import sys
5
4
 
6
5
  import pystand
7
6
 
8
- cmd = 'pystand show -a'.split()
7
+ cmd = 'pystand show --all'.split()
9
8
  out = subprocess.run(cmd, capture_output=True, text=True).stdout
10
- alldists = set(re.sub(r'.+"(.+)".*', r'\1', ln) for ln in out.splitlines())
9
+ alldists = {re.sub(r'.+"(.+)".*', r'\1', ln) for ln in out.splitlines()}
11
10
 
12
11
  error = 0
13
12
  for mach, dist in pystand.DISTRIBUTIONS.items():
@@ -20,7 +20,7 @@ dependencies = [
20
20
  "pygithub",
21
21
  "certifi",
22
22
  "filelock",
23
- "zstandard; python_version < '3.14'",
23
+ "backports.zstd; python_version < '3.14'",
24
24
  ]
25
25
 
26
26
  [[project.authors]]
@@ -45,13 +45,8 @@ ignore_missing_imports = true
45
45
 
46
46
  [tool.ruff.format]
47
47
  quote-style = "single"
48
- skip-magic-trailing-comma = true
49
48
 
50
- [tool.edit-lint]
51
- linters = [
52
- "ruff check",
53
- "mypy",
54
- "pyright",
55
- ]
49
+ [tool.ruff.lint]
50
+ ignore = ["SIM115", "SIM905", "BLE001", "PLW1510", "S110"]
56
51
 
57
52
  # vim:se sw=2:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pystand
3
- Version: 2.32
3
+ Version: 2.34
4
4
  Summary: Install Python versions from python-build-standalone project
5
5
  Author-email: Mark Blakeney <mark.blakeney@bullet-systems.net>
6
6
  License-Expression: GPL-3.0-or-later
@@ -15,7 +15,7 @@ Requires-Dist: argparse-from-file
15
15
  Requires-Dist: pygithub
16
16
  Requires-Dist: certifi
17
17
  Requires-Dist: filelock
18
- Requires-Dist: zstandard; python_version < "3.14"
18
+ Requires-Dist: backports.zstd; python_version < "3.14"
19
19
 
20
20
  ## PYSTAND - Install Python Versions From The Python-Build-Standalone Project
21
21
  [![PyPi](https://img.shields.io/pypi/v/pystand)](https://pypi.org/project/pystand/)
@@ -172,7 +172,7 @@ options:
172
172
  --purge-days PURGE_DAYS
173
173
  cache YYYYMMDD release file lists and downloads for
174
174
  this number of days after last version referencing
175
- that release is removed. Default is 90 days.
175
+ that release is removed. Default is 30 days.
176
176
  --github-access-token GITHUB_ACCESS_TOKEN
177
177
  optional Github access token. Can specify to reduce
178
178
  rate limiting.
@@ -215,13 +215,13 @@ usage: pystand install [-h] [-r RELEASE] [-a] [-A] [--skip] [-f] [-s]
215
215
  Install one, more, or all versions from a python-build-standalone release.
216
216
 
217
217
  positional arguments:
218
- version version to install. E.g. 3.12 or 3.12.3
218
+ version version to install. E.g. 3.14 or 3.14.1
219
219
 
220
220
  options:
221
221
  -h, --help show this help message and exit
222
222
  -r, --release RELEASE
223
223
  install from specified python-build-standalone
224
- YYYYMMDD release (e.g. 20240415), default is latest
224
+ YYYYMMDD release (e.g. 20260807), default is latest
225
225
  release
226
226
  -a, --all install ALL versions from release
227
227
  -A, --all-prerelease install ALL versions from release, including pre-
@@ -238,7 +238,8 @@ aliases: i
238
238
  ### Command `update`
239
239
 
240
240
  ```
241
- usage: pystand update [-h] [-r RELEASE] [-a] [--skip] [-k] [version ...]
241
+ usage: pystand update [-h] [-r RELEASE] [-a] [--pre-release] [--skip] [-k]
242
+ [version ...]
242
243
 
243
244
  Update one, more, or all versions to another release.
244
245
 
@@ -248,9 +249,11 @@ positional arguments:
248
249
  options:
249
250
  -h, --help show this help message and exit
250
251
  -r, --release RELEASE
251
- update to specified YYYMMDD release (e.g. 20240415),
252
+ update to specified YYYMMDD release (e.g. 20260807),
252
253
  default is latest release
253
254
  -a, --all update ALL versions
255
+ --pre-release update release version to a later superceding pre-
256
+ release
254
257
  --skip skip the specified versions when updating all (only
255
258
  can be specified with --all)
256
259
  -k, --keep keep old version after updating (but only if different
@@ -276,7 +279,7 @@ options:
276
279
  can be specified with --all)
277
280
  -r, --release RELEASE
278
281
  only remove versions if from specified YYYMMDD release
279
- (e.g. 20240415)
282
+ (e.g. 20260807)
280
283
 
281
284
  aliases: r, rm
282
285
  ```
@@ -296,7 +299,7 @@ options:
296
299
  -v, --verbose explicitly report why a version is not eligible for
297
300
  update
298
301
  -r, --release RELEASE
299
- use specified YYYYMMDD release (e.g. 20240415) for
302
+ use specified YYYYMMDD release (e.g. 20260807) for
300
303
  verbose compare, default is latest release
301
304
 
302
305
  aliases: l
@@ -320,7 +323,7 @@ options:
320
323
  -l, --list just list recent releases
321
324
  -r, --release RELEASE
322
325
  python-build-standalone YYYYMMDD release to show (e.g.
323
- 20240415), default is latest release
326
+ 20260807), default is latest release
324
327
  -a, --all show all available distributions for each version from
325
328
  the release
326
329
 
@@ -387,7 +390,7 @@ positional arguments:
387
390
 
388
391
  options:
389
392
  -h, --help show this help message and exit
390
- -p, --python PYTHON version of python to use, e.g. "3.12", default is
393
+ -p, --python PYTHON version of python to use, e.g. "3.14", default is
391
394
  latest release version
392
395
  ```
393
396
 
@@ -405,7 +408,7 @@ positional arguments:
405
408
 
406
409
  options:
407
410
  -h, --help show this help message and exit
408
- -p, --python PYTHON version of python to use, e.g. "3.12", default is
411
+ -p, --python PYTHON version of python to use, e.g. "3.14", default is
409
412
  latest release version
410
413
  ```
411
414
 
@@ -9,4 +9,6 @@ pystand.egg-info/SOURCES.txt
9
9
  pystand.egg-info/dependency_links.txt
10
10
  pystand.egg-info/entry_points.txt
11
11
  pystand.egg-info/requires.txt
12
+ pystand.egg-info/scm_file_list.json
13
+ pystand.egg-info/scm_version.json
12
14
  pystand.egg-info/top_level.txt
@@ -6,4 +6,4 @@ certifi
6
6
  filelock
7
7
 
8
8
  [:python_version < "3.14"]
9
- zstandard
9
+ backports.zstd
@@ -0,0 +1,10 @@
1
+ {
2
+ "files": [
3
+ ".gitignore",
4
+ "README.md",
5
+ "check-dist.py",
6
+ "justfile",
7
+ "pyproject.toml",
8
+ "pystand.py"
9
+ ]
10
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "2.34",
3
+ "distance": 0,
4
+ "node": "ge147d95a4c421da907727e05ae933d512bcd48fb",
5
+ "dirty": false,
6
+ "branch": "main",
7
+ "node_date": "2026-08-10"
8
+ }
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  """
3
2
  Command line tool to download, install, and update pre-built Python
4
3
  versions from the python-build-standalone project at
@@ -35,11 +34,13 @@ GITHUB_SITE = f'https://github.com/{GITHUB_REPO}'
35
34
  LATEST_RELEASES = f'{GITHUB_SITE}/releases.atom'
36
35
  LATEST_RELEASE_TAG = f'{GITHUB_SITE}/releases/latest'
37
36
  DOC = 'https://gregoryszorc.com/docs/python-build-standalone/main/'
37
+ VER = f'{sys.version_info.major}.{sys.version_info.minor}'
38
38
 
39
39
  # Sample release tag for documentation/usage examples
40
- SAMPL_RELEASE = '20240415'
40
+ SAMPL_RELEASE = '20260807'
41
41
 
42
42
  PROG = Path(__file__).stem
43
+ HOME = Path.home()
43
44
 
44
45
  # Default distributions for various platforms
45
46
  DISTRIBUTIONS = {
@@ -114,10 +115,10 @@ class ColorDist(ColorTable):
114
115
  return text.split('-', 1)[0]
115
116
 
116
117
 
117
- def unexpanduser(path: Path, *, home=Path.home()) -> Path:
118
+ def unexpanduser(path: Path) -> Path:
118
119
  "Return path name, with $HOME replaced by ~ (opposite of Path.expanduser())"
119
- if path.parts[: len(home.parts)] == home.parts:
120
- return Path('~', *path.parts[len(home.parts) :])
120
+ if path.parts[: len(HOME.parts)] == HOME.parts:
121
+ return Path('~', *path.parts[len(HOME.parts) :])
121
122
 
122
123
  return path
123
124
 
@@ -215,23 +216,6 @@ def rm_path(path: Path) -> bool:
215
216
  return True
216
217
 
217
218
 
218
- def register_zst() -> None:
219
- "Register custom zstandard unpacker"
220
- import tarfile
221
-
222
- from zstandard import ZstdDecompressor
223
-
224
- def unpack_zst(filename: str, extract_dir: str) -> None:
225
- "Unpack a zstandard compressed tar"
226
- with open(filename, 'rb') as compressed:
227
- dctx = ZstdDecompressor()
228
- with dctx.stream_reader(compressed) as reader:
229
- with tarfile.open(fileobj=reader, mode='r|') as tar:
230
- tar.extractall(path=extract_dir)
231
-
232
- shutil.register_unpack_format('zst', ['.zst'], unpack_zst)
233
-
234
-
235
219
  def fetch(args: Namespace, release: str, url: str, tdir: Path) -> str | None:
236
220
  "Fetch and unpack a release file"
237
221
  from urllib.parse import unquote, urlparse
@@ -256,9 +240,12 @@ def fetch(args: Namespace, release: str, url: str, tdir: Path) -> str | None:
256
240
  if error:
257
241
  rm_path(cache_file)
258
242
  else:
259
- # Register custom zstandard handler (only if Python < 3.14 which has built-in support)
260
- if filename.endswith('.zst') and sys.version_info < (3, 14):
261
- register_zst()
243
+ # Register external zstd handler (only if Python < 3.14 which has
244
+ # built-in support)
245
+ if filename.lower().endswith('.zst') and sys.version_info < (3, 14):
246
+ from backports.zstd import register_shutil # type: ignore
247
+
248
+ register_shutil()
262
249
 
263
250
  try:
264
251
  shutil.unpack_archive(cache_file, tmpdir)
@@ -296,20 +283,26 @@ class VersionMatcher:
296
283
  def __init__(self, seq: Iterable[str]) -> None:
297
284
  self.seq = sorted(seq, key=parse_version, reverse=True)
298
285
 
299
- def match(self, version: str | None, *, upgrade: bool = False) -> str | None:
286
+ def match(
287
+ self,
288
+ version: str | None,
289
+ *,
290
+ upgrade: bool = False,
291
+ allow_prelease: bool = False,
292
+ ) -> str | None:
300
293
  "Return full version string given a [possibly] part version prefix"
301
294
 
302
295
  # If no version specified, return the latest release version
303
296
  if not version:
304
- for version in self.seq:
305
- if is_release_version(version):
306
- return version
297
+ for ver in self.seq:
298
+ if is_release_version(ver):
299
+ return ver
307
300
  return None
308
301
 
309
302
  if version in self.seq:
310
303
  return version
311
304
 
312
- is_release = is_release_version(version)
305
+ is_release = not allow_prelease and is_release_version(version)
313
306
  major_only = '.' not in version
314
307
 
315
308
  if major_only:
@@ -323,9 +316,10 @@ class VersionMatcher:
323
316
  # Only allow upgrade of formal release to another formal
324
317
  # release.
325
318
  for full_version in self.seq:
326
- if full_version.startswith(version):
327
- if not upgrade or not is_release or is_release_version(full_version):
328
- return full_version
319
+ if full_version.startswith(version) and (
320
+ not upgrade or not is_release or is_release_version(full_version)
321
+ ):
322
+ return full_version
329
323
 
330
324
  return None
331
325
 
@@ -356,7 +350,7 @@ def get_version_names(args: Namespace) -> list[str]:
356
350
  if not args.version:
357
351
  args.parser.error('Must specify at least one version, or --all.')
358
352
 
359
- all_names = set(f.name for f in iter_versions(args))
353
+ all_names = {f.name for f in iter_versions(args)}
360
354
 
361
355
  # Upconvert all user specified partial version names to full version names
362
356
  matcher = VersionMatcher(all_names)
@@ -486,7 +480,7 @@ def get_release_files(args, tag) -> dict[str, Any]:
486
480
  try:
487
481
  release = gh.get_repo(GITHUB_REPO).get_release(tag)
488
482
  except Exception as e:
489
- print(f'Error: {str(e)}', file=sys.stderr)
483
+ print(f'Error: {e}', file=sys.stderr)
490
484
  return {}
491
485
 
492
486
  # Iterate over the release assets and store pertinent files in a
@@ -521,7 +515,7 @@ def update_version_symlinks(args: Namespace) -> None:
521
515
 
522
516
  # Create a map of all the new major version links
523
517
  newlinks_all = defaultdict(set)
524
- pre_releases = set(v for v in vers if not is_release_version(v))
518
+ pre_releases = {v for v in vers if not is_release_version(v)}
525
519
  for namevers in vers:
526
520
  while '.' in namevers[:-1]:
527
521
  namevers_major = namevers.rsplit('.', maxsplit=1)[0]
@@ -540,7 +534,7 @@ def update_version_symlinks(args: Namespace) -> None:
540
534
  if ver in pre_releases and (rels := (cands - pre_releases)):
541
535
  cands = rels
542
536
 
543
- newlinks[ver] = sorted(cands, key=parse_version)[-1]
537
+ newlinks[ver] = max(cands, key=parse_version)
544
538
 
545
539
  # Remove all old or invalid existing links
546
540
  for name, tgt in oldlinks.items():
@@ -595,7 +589,7 @@ def show_list(args: Namespace) -> None:
595
589
  "Show a list of available releases"
596
590
  latest = parse_version(args._release)
597
591
  releases = fetch_tags(args)
598
- cached = set(p.name for p in args._releases.iterdir())
592
+ cached = {p.name for p in args._releases.iterdir()}
599
593
  for release in sorted(cached.union(releases)):
600
594
  if args.re_match and not re.search(args.re_match, release):
601
595
  continue
@@ -820,7 +814,7 @@ def main() -> str | None:
820
814
  )
821
815
  opt.add_argument(
822
816
  '--purge-days',
823
- default=90,
817
+ default=30,
824
818
  type=int,
825
819
  help='cache YYYYMMDD release file lists and downloads for '
826
820
  'this number of days after last version referencing that '
@@ -861,7 +855,7 @@ def main() -> str | None:
861
855
  else:
862
856
  return f'Must define a docstring for command class "{name}".'
863
857
 
864
- aliases = cls.aliases if hasattr(cls, 'aliases') else []
858
+ aliases = cls.aliases if hasattr(cls, 'aliases') else ()
865
859
  title = get_title(desc)
866
860
  cmdopt = cmd.add_parser(name, description=desc, help=title, aliases=aliases)
867
861
 
@@ -927,7 +921,7 @@ def main() -> str | None:
927
921
  # COMMAND
928
922
  class install_:
929
923
  doc = f'Install one, more, or all versions from a {REPO} release.'
930
- aliases = ['i']
924
+ aliases = ('i',)
931
925
 
932
926
  @staticmethod
933
927
  def init(parser: ArgumentParser) -> None:
@@ -966,7 +960,7 @@ class install_:
966
960
  help='also install source files if available in distribution download',
967
961
  )
968
962
  parser.add_argument(
969
- 'version', nargs='*', help='version to install. E.g. 3.12 or 3.12.3'
963
+ 'version', nargs='*', help=f'version to install. E.g. {VER} or {VER}.1'
970
964
  )
971
965
 
972
966
  @staticmethod
@@ -987,7 +981,7 @@ class install_:
987
981
  'Can not specify versions with --all unless also specifying --skip.'
988
982
  )
989
983
 
990
- skips = set(v for ver in args.version if (v := matcher.match(ver)))
984
+ skips = {v for ver in args.version if (v := matcher.match(ver))}
991
985
 
992
986
  args.version = [
993
987
  v
@@ -1027,7 +1021,7 @@ class install_:
1027
1021
  class update_:
1028
1022
  "Update one, more, or all versions to another release."
1029
1023
 
1030
- aliases = ['u', 'up']
1024
+ aliases = ('u', 'up')
1031
1025
 
1032
1026
  @staticmethod
1033
1027
  def init(parser: ArgumentParser) -> None:
@@ -1040,6 +1034,11 @@ class update_:
1040
1034
  parser.add_argument(
1041
1035
  '-a', '--all', action='store_true', help='update ALL versions'
1042
1036
  )
1037
+ parser.add_argument(
1038
+ '--pre-release',
1039
+ action='store_true',
1040
+ help='update release version to a later superceding pre-release',
1041
+ )
1043
1042
  parser.add_argument(
1044
1043
  '--skip',
1045
1044
  action='store_true',
@@ -1065,6 +1064,7 @@ class update_:
1065
1064
  return f'Release "{release_target}" not found.'
1066
1065
 
1067
1066
  matcher = VersionMatcher(files)
1067
+
1068
1068
  for version in get_version_names(args):
1069
1069
  vdir = args._versions / version
1070
1070
  if not (data := get_json(vdir / args._data)):
@@ -1073,7 +1073,10 @@ class update_:
1073
1073
  if (release := data.get('release')) == release_target:
1074
1074
  continue
1075
1075
 
1076
- if not (nextver := matcher.match(version, upgrade=True)):
1076
+ nextver = matcher.match(
1077
+ version, upgrade=True, allow_prelease=args.pre_release
1078
+ )
1079
+ if not nextver:
1077
1080
  continue
1078
1081
 
1079
1082
  distribution = data.get('distribution')
@@ -1114,7 +1117,7 @@ class update_:
1114
1117
  class remove_:
1115
1118
  "Remove/uninstall one, more, or all versions."
1116
1119
 
1117
- aliases = ['r', 'rm']
1120
+ aliases = ('r', 'rm')
1118
1121
 
1119
1122
  @staticmethod
1120
1123
  def init(parser: ArgumentParser) -> None:
@@ -1155,7 +1158,7 @@ class remove_:
1155
1158
  class list_:
1156
1159
  "List installed versions and show which have an update available."
1157
1160
 
1158
- aliases = ['l']
1161
+ aliases = ('l',)
1159
1162
 
1160
1163
  @staticmethod
1161
1164
  def init(parser: ArgumentParser) -> None:
@@ -1245,7 +1248,7 @@ class show_:
1245
1248
  View available releases and their distributions at
1246
1249
  {GITHUB_SITE}/releases.
1247
1250
  """
1248
- aliases = ['s']
1251
+ aliases = ('s',)
1249
1252
 
1250
1253
  @staticmethod
1251
1254
  def init(parser: ArgumentParser) -> None:
@@ -1320,7 +1323,7 @@ class show_:
1320
1323
  class path_:
1321
1324
  "Show path prefix to installed version base directory."
1322
1325
 
1323
- aliases = ['p']
1326
+ aliases = ('p',)
1324
1327
 
1325
1328
  @staticmethod
1326
1329
  def init(parser: ArgumentParser) -> None:
@@ -1373,7 +1376,7 @@ class path_:
1373
1376
  class cache_:
1374
1377
  "Show size of release download caches."
1375
1378
 
1376
- aliases = ['c']
1379
+ aliases = ('c',)
1377
1380
 
1378
1381
  @staticmethod
1379
1382
  def init(parser: ArgumentParser) -> None:
@@ -1421,9 +1424,7 @@ class cache_:
1421
1424
  )
1422
1425
 
1423
1426
  keep = keeplist(args)
1424
- releases = set(
1425
- p.name for p in args._downloads.iterdir() if p.name.isdigit()
1426
- )
1427
+ releases = {p.name for p in args._downloads.iterdir() if p.name.isdigit()}
1427
1428
  releases.update(
1428
1429
  p.name for p in args._releases.iterdir() if p.name.isdigit()
1429
1430
  )
@@ -1477,7 +1478,7 @@ class uv_:
1477
1478
  parser.add_argument(
1478
1479
  '-p',
1479
1480
  '--python',
1480
- help='version of python to use, e.g. "3.12", default is latest release version',
1481
+ help=f'version of python to use, e.g. "{VER}", default is latest release version',
1481
1482
  )
1482
1483
 
1483
1484
  parser.add_argument('command', help='uv command to run')
@@ -1507,7 +1508,7 @@ class uvx_:
1507
1508
  parser.add_argument(
1508
1509
  '-p',
1509
1510
  '--python',
1510
- help='version of python to use, e.g. "3.12", default is latest release version',
1511
+ help=f'version of python to use, e.g. "{VER}", default is latest release version',
1511
1512
  )
1512
1513
 
1513
1514
  parser.add_argument('program', help='uvx program to run')
File without changes
File without changes
File without changes