pystand 2.39__tar.gz → 2.41__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.39
3
+ Version: 2.41
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
@@ -143,7 +143,7 @@ usage: pystand [-h] [-D DISTRIBUTION] [-P PREFIX_DIR] [-C CACHE_DIR]
143
143
  [-M CACHE_MINUTES] [--purge-days PURGE_DAYS]
144
144
  [--github-access-token GITHUB_ACCESS_TOKEN] [--no-strip]
145
145
  [--no-color] [--cert {system,certifi,none}] [-V]
146
- {install,i,update,u,up,remove,r,rm,list,l,show,s,path,p,cache,c,uv,uvx} ...
146
+ {install,i,update,u,up,remove,r,rm,list,l,show,s,path,p,cache,c,man,m,uv,uvx} ...
147
147
 
148
148
  Command line tool to download, install, and update pre-built Python versions
149
149
  from the python-build-standalone project at https://github.com/astral-
@@ -183,7 +183,7 @@ options:
183
183
  -V, --version just show pystand version
184
184
 
185
185
  Commands:
186
- {install,i,update,u,up,remove,r,rm,list,l,show,s,path,p,cache,c,uv,uvx}
186
+ {install,i,update,u,up,remove,r,rm,list,l,show,s,path,p,cache,c,man,m,uv,uvx}
187
187
  install (i) Install one, more, or all versions from a python-
188
188
  build-standalone release.
189
189
  update (u, up) Update one, more, or all versions to another release.
@@ -193,6 +193,7 @@ Commands:
193
193
  show (s) Show versions available from a release.
194
194
  path (p) Show path prefix to installed version base directory.
195
195
  cache (c) Show size of release download caches.
196
+ man (m) Show installed man page for latest or given version.
196
197
  uv Run a uv command using a version of python installed
197
198
  by pystand.
198
199
  uvx Run a program using uvx and a version of python
@@ -372,6 +373,22 @@ options:
372
373
  aliases: c
373
374
  ```
374
375
 
376
+ ### Command `man`
377
+
378
+ ```
379
+ usage: pystand man [-h] [version]
380
+
381
+ Show installed man page for latest or given version.
382
+
383
+ positional arguments:
384
+ version installed version to show man page for, default is latest
385
+
386
+ options:
387
+ -h, --help show this help message and exit
388
+
389
+ aliases: m
390
+ ```
391
+
375
392
  ### Command `uv`
376
393
 
377
394
  ```
@@ -125,7 +125,7 @@ usage: pystand [-h] [-D DISTRIBUTION] [-P PREFIX_DIR] [-C CACHE_DIR]
125
125
  [-M CACHE_MINUTES] [--purge-days PURGE_DAYS]
126
126
  [--github-access-token GITHUB_ACCESS_TOKEN] [--no-strip]
127
127
  [--no-color] [--cert {system,certifi,none}] [-V]
128
- {install,i,update,u,up,remove,r,rm,list,l,show,s,path,p,cache,c,uv,uvx} ...
128
+ {install,i,update,u,up,remove,r,rm,list,l,show,s,path,p,cache,c,man,m,uv,uvx} ...
129
129
 
130
130
  Command line tool to download, install, and update pre-built Python versions
131
131
  from the python-build-standalone project at https://github.com/astral-
@@ -165,7 +165,7 @@ options:
165
165
  -V, --version just show pystand version
166
166
 
167
167
  Commands:
168
- {install,i,update,u,up,remove,r,rm,list,l,show,s,path,p,cache,c,uv,uvx}
168
+ {install,i,update,u,up,remove,r,rm,list,l,show,s,path,p,cache,c,man,m,uv,uvx}
169
169
  install (i) Install one, more, or all versions from a python-
170
170
  build-standalone release.
171
171
  update (u, up) Update one, more, or all versions to another release.
@@ -175,6 +175,7 @@ Commands:
175
175
  show (s) Show versions available from a release.
176
176
  path (p) Show path prefix to installed version base directory.
177
177
  cache (c) Show size of release download caches.
178
+ man (m) Show installed man page for latest or given version.
178
179
  uv Run a uv command using a version of python installed
179
180
  by pystand.
180
181
  uvx Run a program using uvx and a version of python
@@ -354,6 +355,22 @@ options:
354
355
  aliases: c
355
356
  ```
356
357
 
358
+ ### Command `man`
359
+
360
+ ```
361
+ usage: pystand man [-h] [version]
362
+
363
+ Show installed man page for latest or given version.
364
+
365
+ positional arguments:
366
+ version installed version to show man page for, default is latest
367
+
368
+ options:
369
+ -h, --help show this help message and exit
370
+
371
+ aliases: m
372
+ ```
373
+
357
374
  ### Command `uv`
358
375
 
359
376
  ```
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pystand
3
- Version: 2.39
3
+ Version: 2.41
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
@@ -143,7 +143,7 @@ usage: pystand [-h] [-D DISTRIBUTION] [-P PREFIX_DIR] [-C CACHE_DIR]
143
143
  [-M CACHE_MINUTES] [--purge-days PURGE_DAYS]
144
144
  [--github-access-token GITHUB_ACCESS_TOKEN] [--no-strip]
145
145
  [--no-color] [--cert {system,certifi,none}] [-V]
146
- {install,i,update,u,up,remove,r,rm,list,l,show,s,path,p,cache,c,uv,uvx} ...
146
+ {install,i,update,u,up,remove,r,rm,list,l,show,s,path,p,cache,c,man,m,uv,uvx} ...
147
147
 
148
148
  Command line tool to download, install, and update pre-built Python versions
149
149
  from the python-build-standalone project at https://github.com/astral-
@@ -183,7 +183,7 @@ options:
183
183
  -V, --version just show pystand version
184
184
 
185
185
  Commands:
186
- {install,i,update,u,up,remove,r,rm,list,l,show,s,path,p,cache,c,uv,uvx}
186
+ {install,i,update,u,up,remove,r,rm,list,l,show,s,path,p,cache,c,man,m,uv,uvx}
187
187
  install (i) Install one, more, or all versions from a python-
188
188
  build-standalone release.
189
189
  update (u, up) Update one, more, or all versions to another release.
@@ -193,6 +193,7 @@ Commands:
193
193
  show (s) Show versions available from a release.
194
194
  path (p) Show path prefix to installed version base directory.
195
195
  cache (c) Show size of release download caches.
196
+ man (m) Show installed man page for latest or given version.
196
197
  uv Run a uv command using a version of python installed
197
198
  by pystand.
198
199
  uvx Run a program using uvx and a version of python
@@ -372,6 +373,22 @@ options:
372
373
  aliases: c
373
374
  ```
374
375
 
376
+ ### Command `man`
377
+
378
+ ```
379
+ usage: pystand man [-h] [version]
380
+
381
+ Show installed man page for latest or given version.
382
+
383
+ positional arguments:
384
+ version installed version to show man page for, default is latest
385
+
386
+ options:
387
+ -h, --help show this help message and exit
388
+
389
+ aliases: m
390
+ ```
391
+
375
392
  ### Command `uv`
376
393
 
377
394
  ```
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "2.41",
3
+ "distance": 0,
4
+ "node": "gdec583e581b565992eeeaae95cb1cd013866f115",
5
+ "dirty": false,
6
+ "branch": "main",
7
+ "node_date": "2026-10-20"
8
+ }
@@ -6,25 +6,24 @@ https://github.com/astral-sh/python-build-standalone.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- import itertools
9
+ import sys
10
+
11
+ if sys.version_info >= (3, 15):
12
+ sys.set_lazy_imports('all')
13
+
10
14
  import os
11
15
  import platform
12
16
  import re
13
- import shlex
14
17
  import shutil
15
18
  import ssl
16
19
  import subprocess
17
- import sys
18
20
  import time
19
- from collections import defaultdict
20
21
  from collections.abc import Iterable, Iterator
21
- from datetime import date, datetime
22
22
  from pathlib import Path
23
23
  from typing import Any
24
24
  from urllib.request import urlopen
25
25
 
26
26
  import filelock
27
- import platformdirs
28
27
  from argparse_from_file import ArgumentParser, Namespace
29
28
  from packaging.version import InvalidVersion
30
29
  from packaging.version import parse as parse_version
@@ -45,6 +44,7 @@ SAMPL_RELEASE = '20260807'
45
44
 
46
45
  PROG = Path(__file__).stem
47
46
  HOME = Path.home()
47
+ MANPATH = Path('share', 'man', 'man1', 'python.1')
48
48
 
49
49
  # Default distributions for various platforms
50
50
  DISTRIBUTIONS = {
@@ -82,6 +82,8 @@ class ColorTable:
82
82
  "Base class for color tables"
83
83
 
84
84
  def __init__(self, initval: str, no_color: bool) -> None:
85
+ import itertools
86
+
85
87
  self.table = None if no_color else {self.parse_key(initval): COLORS[0]}
86
88
  self.next = itertools.cycle(COLORS[1:-1])
87
89
 
@@ -377,6 +379,8 @@ def get_version_names(args: Namespace) -> list[str]:
377
379
 
378
380
  def check_release_tag(release: str) -> str | None:
379
381
  "Check the specified release tag is valid"
382
+ from datetime import date
383
+
380
384
  if not release.isdigit() or len(release) != len(SAMPL_RELEASE):
381
385
  return 'Release must be a YYYYMMDD string.'
382
386
 
@@ -514,6 +518,8 @@ def get_release_files(args, tag) -> dict[str, Any]:
514
518
 
515
519
  def update_version_symlinks(args: Namespace) -> None:
516
520
  "Create/update symlinks pointing to latest version"
521
+ from collections import defaultdict
522
+
517
523
  base = args._versions
518
524
  if not base.exists():
519
525
  return
@@ -602,6 +608,8 @@ def purge_unused_releases(args: Namespace) -> None:
602
608
 
603
609
  def show_list(args: Namespace, re_match: re.Pattern | None) -> None:
604
610
  "Show a list of available releases"
611
+ from datetime import datetime
612
+
605
613
  try:
606
614
  latest = parse_version(args._release)
607
615
  except InvalidVersion:
@@ -719,6 +727,18 @@ def compile_bytecode(srcdir: Path, tgtdir: Path) -> str | None:
719
727
  return None
720
728
 
721
729
 
730
+ def ensure_manpage_link(vdir: Path) -> None:
731
+ "Ensure a symlink to the man page for this version exists"
732
+ manpath = vdir / MANPATH
733
+ if manpath.is_symlink() or manpath.exists():
734
+ return
735
+
736
+ for path in manpath.parent.iterdir():
737
+ if not path.is_symlink() and path.name.startswith('python'):
738
+ manpath.symlink_to(path.name)
739
+ break
740
+
741
+
722
742
  def install_version(
723
743
  args: Namespace, vdir: Path, release: str, distribution: str, files: dict[str, Any]
724
744
  ) -> str | None:
@@ -749,6 +769,7 @@ def install_version(
749
769
  if error:
750
770
  shutil.rmtree(tmpdir)
751
771
  else:
772
+ ensure_manpage_link(tmpdir)
752
773
  remove_version(args, version)
753
774
  tmpdir.replace(vdir)
754
775
 
@@ -804,6 +825,8 @@ def create_cert(option: str) -> ssl.SSLContext | None:
804
825
 
805
826
  def run_uv(args: Namespace, cmd: list[str], cmdopts: list[str]) -> str | None:
806
827
  "Run a uv command with the specified or latest installed python version"
828
+ import shlex
829
+
807
830
  if not (vers := (args.python or get_major_version(args))):
808
831
  return 'No installed python version found.'
809
832
 
@@ -828,6 +851,8 @@ commands = []
828
851
 
829
852
  def main() -> str | None:
830
853
  "Main code"
854
+ import platformdirs
855
+
831
856
  distro_default = DISTRIBUTIONS.get((platform.system(), platform.machine()))
832
857
  distro_help = distro_default or '?unknown?'
833
858
 
@@ -977,6 +1002,15 @@ def main() -> str | None:
977
1002
  except filelock.Timeout:
978
1003
  return f'ERROR: Another instance of {PROG} is already running.'
979
1004
 
1005
+ # If the command returned a tuple, treat it as a subprocess command to run
1006
+ if isinstance(result, tuple):
1007
+ try:
1008
+ subprocess.run(result)
1009
+ except Exception as e:
1010
+ result = f'Error running command: {e}'
1011
+ else:
1012
+ result = None
1013
+
980
1014
  return result
981
1015
 
982
1016
 
@@ -1548,6 +1582,36 @@ class cache:
1548
1582
  show_cache_size(args._downloads, args)
1549
1583
 
1550
1584
 
1585
+ @Command
1586
+ class man:
1587
+ "Show installed man page for latest or given version."
1588
+
1589
+ aliases = ('m',)
1590
+
1591
+ @staticmethod
1592
+ def init(parser: ArgumentParser) -> None:
1593
+ parser.add_argument(
1594
+ 'version',
1595
+ nargs='?',
1596
+ help='installed version to show man page for, default is latest',
1597
+ )
1598
+
1599
+ @staticmethod
1600
+ def run(args: Namespace) -> str | tuple | None:
1601
+ if not (version := args.version):
1602
+ version = get_major_version(args)
1603
+
1604
+ vdir = (args._versions / version).resolve()
1605
+ if not vdir.exists():
1606
+ return f'Version {version} is not installed.'
1607
+
1608
+ man_path = (vdir / MANPATH).parent.parent
1609
+ if not man_path.is_dir():
1610
+ return f'No man page found for version {version}.'
1611
+
1612
+ return ('man', '-M', str(man_path), 'python')
1613
+
1614
+
1551
1615
  @Command
1552
1616
  class uv:
1553
1617
  __doc__ = f'Run a uv command using a version of python installed by {PROG}.'
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "2.39",
3
- "distance": 0,
4
- "node": "g3bfced01900026625a7fe977f022eed41afa2c53",
5
- "dirty": false,
6
- "branch": "main",
7
- "node_date": "2026-09-24"
8
- }
File without changes
File without changes
File without changes
File without changes
File without changes