pystand 2.26__tar.gz → 2.28__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.26
3
+ Version: 2.28
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
@@ -9,7 +9,6 @@ Keywords: python-build-standalone,pyenv,hatch,pdm
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Requires-Python: >=3.8
11
11
  Description-Content-Type: text/markdown
12
- Requires-Dist: argcomplete
13
12
  Requires-Dist: packaging
14
13
  Requires-Dist: platformdirs
15
14
  Requires-Dist: argparse-from-file
@@ -35,6 +34,9 @@ provided:
35
34
  |`list`|List installed versions and show which have an update available.|
36
35
  |`show`|Show versions available from a release.|
37
36
  |`path`|Show path prefix to installed version base directory.|
37
+ |`cache`|Show size of release download caches.|
38
+ |`uv`|Run a uv command using a version of python installed by pystand.|
39
+ |`uvx`|Run a program using uvx and a version of python installed by pystand.|
38
40
 
39
41
  By default, Python versions are sourced from the latest
40
42
  `python-build-standalone` [release][pbs-rel] available (e.g.
@@ -102,11 +104,11 @@ Version 3.12.3 is already installed.
102
104
  Here are some examples showing how to use an installed version ..
103
105
 
104
106
  ```sh
105
- # Use uv to create a virtual environment to be run with latest pystand
107
+ # Use uv to create a virtual environment to be run with pystand
106
108
  # installed python 3.12:
107
109
  $ uv venv -p $(pystand path 3.12) myenv
108
110
 
109
- # Create a regular virtual environment to be run with latest pystand
111
+ # Create a regular virtual environment to be run with pystand
110
112
  # installed python 3.12:
111
113
  $ $(pystand path -p 3.12) -m venv myenv
112
114
 
@@ -142,7 +144,7 @@ usage: pystand [-h] [-D DISTRIBUTION] [-P PREFIX_DIR] [-C CACHE_DIR]
142
144
  [-M CACHE_MINUTES] [--purge-days PURGE_DAYS]
143
145
  [--github-access-token GITHUB_ACCESS_TOKEN] [--no-strip]
144
146
  [--no-color] [--cert {system,certifi,none}] [-V]
145
- {install,update,upgrade,remove,uninstall,list,show,path,cache} ...
147
+ {install,i,update,u,upgrade,remove,r,uninstall,list,l,show,s,path,p,cache,c,uv,uvx} ...
146
148
 
147
149
  Command line tool to download, install, and update pre-built Python versions
148
150
  from the python-build-standalone project at https://github.com/astral-
@@ -159,10 +161,10 @@ options:
159
161
  standalone/main/
160
162
  -P, --prefix-dir PREFIX_DIR
161
163
  specify prefix dir for storing versions. Default is
162
- "$HOME/.local/share/pystand".
164
+ "~/.local/share/pystand".
163
165
  -C, --cache-dir CACHE_DIR
164
166
  specify cache dir for downloads. Default is
165
- "$HOME/.cache/pystand".
167
+ "~/.cache/pystand".
166
168
  -M, --cache-minutes CACHE_MINUTES
167
169
  cache latest YYYYMMDD release tag fetch for this many
168
170
  minutes, before rechecking for latest. Default is 60
@@ -182,16 +184,22 @@ options:
182
184
  -V, --version just show pystand version
183
185
 
184
186
  Commands:
185
- {install,update,upgrade,remove,uninstall,list,show,path,cache}
186
- install Install one, more, or all versions from a python-
187
+ {install,i,update,u,upgrade,remove,r,uninstall,list,l,show,s,path,p,cache,c,uv,uvx}
188
+ install (i) Install one, more, or all versions from a python-
187
189
  build-standalone release.
188
- update (upgrade) Update one, more, or all versions to another release.
189
- remove (uninstall) Remove/uninstall one, more, or all versions.
190
- list List installed versions and show which have an update
190
+ update (u, upgrade)
191
+ Update one, more, or all versions to another release.
192
+ remove (r, uninstall)
193
+ Remove/uninstall one, more, or all versions.
194
+ list (l) List installed versions and show which have an update
191
195
  available.
192
- show Show versions available from a release.
193
- path Show path prefix to installed version base directory.
194
- cache Show size of release download caches.
196
+ show (s) Show versions available from a release.
197
+ path (p) Show path prefix to installed version base directory.
198
+ cache (c) Show size of release download caches.
199
+ uv Run a uv command using a version of python installed
200
+ by pystand.
201
+ uvx Run a program using uvx and a version of python
202
+ installed by pystand.
195
203
 
196
204
  Some commands offer aliases as shown in parentheses above. Note you can set
197
205
  default starting global options in ~/.config/pystand-flags.conf.
@@ -225,6 +233,8 @@ options:
225
233
  -f, --force force install even if already installed
226
234
  -s, --include-source also install source files if available in distribution
227
235
  download
236
+
237
+ aliases: i
228
238
  ```
229
239
 
230
240
  ### Command `update`
@@ -248,7 +258,7 @@ options:
248
258
  -k, --keep keep old version after updating (but only if different
249
259
  version number)
250
260
 
251
- aliases: upgrade
261
+ aliases: u, upgrade
252
262
  ```
253
263
 
254
264
  ### Command `remove`
@@ -270,7 +280,7 @@ options:
270
280
  only remove versions if from specified YYYMMDD release
271
281
  (e.g. 20240415)
272
282
 
273
- aliases: uninstall
283
+ aliases: r, uninstall
274
284
  ```
275
285
 
276
286
  ### Command `list`
@@ -290,6 +300,8 @@ options:
290
300
  -r, --release RELEASE
291
301
  use specified YYYYMMDD release (e.g. 20240415) for
292
302
  verbose compare, default is latest release
303
+
304
+ aliases: l
293
305
  ```
294
306
 
295
307
  ### Command `show`
@@ -313,6 +325,8 @@ options:
313
325
  20240415), default is latest release
314
326
  -a, --all show all available distributions for each version from
315
327
  the release
328
+
329
+ aliases: s
316
330
  ```
317
331
 
318
332
  ### Command `path`
@@ -330,6 +344,8 @@ options:
330
344
  -p, --python-path add path to python executable
331
345
  -r, --resolve fully resolve given version
332
346
  -c, --cache-path just show path to cache dir
347
+
348
+ aliases: p
333
349
  ```
334
350
 
335
351
  ### Command `cache`
@@ -351,6 +367,46 @@ options:
351
367
  -R, --remove-all-unused
352
368
  remove caches for all currently unused releases
353
369
  instead of showing size
370
+
371
+ aliases: c
372
+ ```
373
+
374
+ ### Command `uv`
375
+
376
+ ```
377
+ usage: pystand uv [-h] [-p PYTHON]
378
+ command [subcommand] [uv_args_for_command ...]
379
+
380
+ Run a uv command using a version of python installed by pystand.
381
+
382
+ positional arguments:
383
+ command uv command to run
384
+ subcommand optional uv sub-command
385
+ uv_args_for_command optional extra arguments to pass to uv command [sub-
386
+ command], start any options with "-- "
387
+
388
+ options:
389
+ -h, --help show this help message and exit
390
+ -p, --python PYTHON version of python to use, e.g. "3.12", default is
391
+ latest release version
392
+ ```
393
+
394
+ ### Command `uvx`
395
+
396
+ ```
397
+ usage: pystand uvx [-h] [-p PYTHON] program [uvx_args_for_program ...]
398
+
399
+ Run a program using uvx and a version of python installed by pystand.
400
+
401
+ positional arguments:
402
+ program uvx program to run
403
+ uvx_args_for_program optional extra arguments to pass to uvx program, start
404
+ any options with "-- "
405
+
406
+ options:
407
+ -h, --help show this help message and exit
408
+ -p, --python PYTHON version of python to use, e.g. "3.12", default is
409
+ latest release version
354
410
  ```
355
411
 
356
412
  ## Installation and Upgrade
@@ -590,7 +646,8 @@ supported options.
590
646
 
591
647
  The global options: `--distribution`, `--prefix-dir`, `--cache-dir`,
592
648
  `--cache-minutes`, `--purge-days`, `--github-access-token`, `--no-strip`,
593
- `--cert` are the only sensible candidates to consider setting as defaults.
649
+ `--no-color`, and `--cert` are the only sensible candidates to consider setting
650
+ as defaults.
594
651
 
595
652
  ## Github API Rate Limiting
596
653
 
@@ -623,14 +680,53 @@ The available options are:
623
680
  Specify the option on the command line with `--cert`, or set that as a [default
624
681
  option](#command-default-options).
625
682
 
626
- ## Command Line Tab Completion
683
+ ## Direct Usage with UV Tool
684
+
685
+ Many [`uv`][uv] commands accept a `-p/--python` option to specify a Python
686
+ version or path. To use a `pystand` installed Python version, instead of the
687
+ `uv` maintained or system python, you can use one of the following approaches:
688
+
689
+ E.g. To create a `uv venv` using `pystand` installed 3.12, just hard code the
690
+ path directly, e.g. for a Linux platform:
691
+
692
+ ```sh
693
+ uv venv -p ~/.local/share/pystand/3.12
694
+ ```
695
+
696
+ Or, specify the path using pystand itself:
697
+
698
+ ```sh
699
+ uv venv -p $(pystand path 3.12)
700
+ ```
701
+
702
+ Or, use the `pystand uv` wrapper command:
703
+
704
+ ```sh
705
+ pystand uv venv -p 3.12
706
+ ```
707
+
708
+ For the common case where you simply want to use the latest `pystand` Python
709
+ release you can omit the `-p` option (and `pystand` will specify it to `uv`
710
+ under the hood): :
711
+
712
+ ```sh
713
+ pystand uv venv
714
+ ```
715
+
716
+ Note if you use the `pystand uv` wrapper, and want to specify switches to the
717
+ `uv` command, you must use `--` to separate `uv` arguments from `pystand uv`
718
+ arguments. E.g.:
719
+
720
+ ```sh
721
+ pystand uv tool install -p 3.12 cowsay -- --verbose
722
+ ```
723
+
724
+ `pystand` also provides a similar wrapper command `pystand uvx` for [`uvx`][uvx]
725
+ commands.
627
726
 
628
- Command line shell [tab
629
- completion](https://en.wikipedia.org/wiki/Command-line_completion) is
630
- automatically enabled on `pystand` commands and options using
631
- [`argcomplete`](https://github.com/kislyuk/argcomplete). You may need to
632
- first (once-only) [activate argcomplete global
633
- completion](https://github.com/kislyuk/argcomplete#global-completion).
727
+ An example where this functionality may be handy is to conveniently test
728
+ various tools against free-threaded or other Python builds from Python Build
729
+ Standalone releases.
634
730
 
635
731
  ## License
636
732
 
@@ -649,6 +745,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at
649
745
  [pbs-rel]: https://github.com/astral-sh/python-build-standalone/releases
650
746
  [pipx]: https://github.com/pypa/pipx
651
747
  [pipxu]: https://github.com/bulletmark/pipxu
748
+ [uv]: https://docs.astral.sh/uv
749
+ [uvx]: https://docs.astral.sh/uv/guides/tools/#running-tools
652
750
  [uvtool]: https://docs.astral.sh/uv/guides/tools/#installing-tools
653
751
  [pyenv]: https://github.com/pyenv/pyenv
654
752
  [pdm]: https://pdm-project.org/
@@ -15,6 +15,9 @@ provided:
15
15
  |`list`|List installed versions and show which have an update available.|
16
16
  |`show`|Show versions available from a release.|
17
17
  |`path`|Show path prefix to installed version base directory.|
18
+ |`cache`|Show size of release download caches.|
19
+ |`uv`|Run a uv command using a version of python installed by pystand.|
20
+ |`uvx`|Run a program using uvx and a version of python installed by pystand.|
18
21
 
19
22
  By default, Python versions are sourced from the latest
20
23
  `python-build-standalone` [release][pbs-rel] available (e.g.
@@ -82,11 +85,11 @@ Version 3.12.3 is already installed.
82
85
  Here are some examples showing how to use an installed version ..
83
86
 
84
87
  ```sh
85
- # Use uv to create a virtual environment to be run with latest pystand
88
+ # Use uv to create a virtual environment to be run with pystand
86
89
  # installed python 3.12:
87
90
  $ uv venv -p $(pystand path 3.12) myenv
88
91
 
89
- # Create a regular virtual environment to be run with latest pystand
92
+ # Create a regular virtual environment to be run with pystand
90
93
  # installed python 3.12:
91
94
  $ $(pystand path -p 3.12) -m venv myenv
92
95
 
@@ -122,7 +125,7 @@ usage: pystand [-h] [-D DISTRIBUTION] [-P PREFIX_DIR] [-C CACHE_DIR]
122
125
  [-M CACHE_MINUTES] [--purge-days PURGE_DAYS]
123
126
  [--github-access-token GITHUB_ACCESS_TOKEN] [--no-strip]
124
127
  [--no-color] [--cert {system,certifi,none}] [-V]
125
- {install,update,upgrade,remove,uninstall,list,show,path,cache} ...
128
+ {install,i,update,u,upgrade,remove,r,uninstall,list,l,show,s,path,p,cache,c,uv,uvx} ...
126
129
 
127
130
  Command line tool to download, install, and update pre-built Python versions
128
131
  from the python-build-standalone project at https://github.com/astral-
@@ -139,10 +142,10 @@ options:
139
142
  standalone/main/
140
143
  -P, --prefix-dir PREFIX_DIR
141
144
  specify prefix dir for storing versions. Default is
142
- "$HOME/.local/share/pystand".
145
+ "~/.local/share/pystand".
143
146
  -C, --cache-dir CACHE_DIR
144
147
  specify cache dir for downloads. Default is
145
- "$HOME/.cache/pystand".
148
+ "~/.cache/pystand".
146
149
  -M, --cache-minutes CACHE_MINUTES
147
150
  cache latest YYYYMMDD release tag fetch for this many
148
151
  minutes, before rechecking for latest. Default is 60
@@ -162,16 +165,22 @@ options:
162
165
  -V, --version just show pystand version
163
166
 
164
167
  Commands:
165
- {install,update,upgrade,remove,uninstall,list,show,path,cache}
166
- install Install one, more, or all versions from a python-
168
+ {install,i,update,u,upgrade,remove,r,uninstall,list,l,show,s,path,p,cache,c,uv,uvx}
169
+ install (i) Install one, more, or all versions from a python-
167
170
  build-standalone release.
168
- update (upgrade) Update one, more, or all versions to another release.
169
- remove (uninstall) Remove/uninstall one, more, or all versions.
170
- list List installed versions and show which have an update
171
+ update (u, upgrade)
172
+ Update one, more, or all versions to another release.
173
+ remove (r, uninstall)
174
+ Remove/uninstall one, more, or all versions.
175
+ list (l) List installed versions and show which have an update
171
176
  available.
172
- show Show versions available from a release.
173
- path Show path prefix to installed version base directory.
174
- cache Show size of release download caches.
177
+ show (s) Show versions available from a release.
178
+ path (p) Show path prefix to installed version base directory.
179
+ cache (c) Show size of release download caches.
180
+ uv Run a uv command using a version of python installed
181
+ by pystand.
182
+ uvx Run a program using uvx and a version of python
183
+ installed by pystand.
175
184
 
176
185
  Some commands offer aliases as shown in parentheses above. Note you can set
177
186
  default starting global options in ~/.config/pystand-flags.conf.
@@ -205,6 +214,8 @@ options:
205
214
  -f, --force force install even if already installed
206
215
  -s, --include-source also install source files if available in distribution
207
216
  download
217
+
218
+ aliases: i
208
219
  ```
209
220
 
210
221
  ### Command `update`
@@ -228,7 +239,7 @@ options:
228
239
  -k, --keep keep old version after updating (but only if different
229
240
  version number)
230
241
 
231
- aliases: upgrade
242
+ aliases: u, upgrade
232
243
  ```
233
244
 
234
245
  ### Command `remove`
@@ -250,7 +261,7 @@ options:
250
261
  only remove versions if from specified YYYMMDD release
251
262
  (e.g. 20240415)
252
263
 
253
- aliases: uninstall
264
+ aliases: r, uninstall
254
265
  ```
255
266
 
256
267
  ### Command `list`
@@ -270,6 +281,8 @@ options:
270
281
  -r, --release RELEASE
271
282
  use specified YYYYMMDD release (e.g. 20240415) for
272
283
  verbose compare, default is latest release
284
+
285
+ aliases: l
273
286
  ```
274
287
 
275
288
  ### Command `show`
@@ -293,6 +306,8 @@ options:
293
306
  20240415), default is latest release
294
307
  -a, --all show all available distributions for each version from
295
308
  the release
309
+
310
+ aliases: s
296
311
  ```
297
312
 
298
313
  ### Command `path`
@@ -310,6 +325,8 @@ options:
310
325
  -p, --python-path add path to python executable
311
326
  -r, --resolve fully resolve given version
312
327
  -c, --cache-path just show path to cache dir
328
+
329
+ aliases: p
313
330
  ```
314
331
 
315
332
  ### Command `cache`
@@ -331,6 +348,46 @@ options:
331
348
  -R, --remove-all-unused
332
349
  remove caches for all currently unused releases
333
350
  instead of showing size
351
+
352
+ aliases: c
353
+ ```
354
+
355
+ ### Command `uv`
356
+
357
+ ```
358
+ usage: pystand uv [-h] [-p PYTHON]
359
+ command [subcommand] [uv_args_for_command ...]
360
+
361
+ Run a uv command using a version of python installed by pystand.
362
+
363
+ positional arguments:
364
+ command uv command to run
365
+ subcommand optional uv sub-command
366
+ uv_args_for_command optional extra arguments to pass to uv command [sub-
367
+ command], start any options with "-- "
368
+
369
+ options:
370
+ -h, --help show this help message and exit
371
+ -p, --python PYTHON version of python to use, e.g. "3.12", default is
372
+ latest release version
373
+ ```
374
+
375
+ ### Command `uvx`
376
+
377
+ ```
378
+ usage: pystand uvx [-h] [-p PYTHON] program [uvx_args_for_program ...]
379
+
380
+ Run a program using uvx and a version of python installed by pystand.
381
+
382
+ positional arguments:
383
+ program uvx program to run
384
+ uvx_args_for_program optional extra arguments to pass to uvx program, start
385
+ any options with "-- "
386
+
387
+ options:
388
+ -h, --help show this help message and exit
389
+ -p, --python PYTHON version of python to use, e.g. "3.12", default is
390
+ latest release version
334
391
  ```
335
392
 
336
393
  ## Installation and Upgrade
@@ -570,7 +627,8 @@ supported options.
570
627
 
571
628
  The global options: `--distribution`, `--prefix-dir`, `--cache-dir`,
572
629
  `--cache-minutes`, `--purge-days`, `--github-access-token`, `--no-strip`,
573
- `--cert` are the only sensible candidates to consider setting as defaults.
630
+ `--no-color`, and `--cert` are the only sensible candidates to consider setting
631
+ as defaults.
574
632
 
575
633
  ## Github API Rate Limiting
576
634
 
@@ -603,14 +661,53 @@ The available options are:
603
661
  Specify the option on the command line with `--cert`, or set that as a [default
604
662
  option](#command-default-options).
605
663
 
606
- ## Command Line Tab Completion
664
+ ## Direct Usage with UV Tool
665
+
666
+ Many [`uv`][uv] commands accept a `-p/--python` option to specify a Python
667
+ version or path. To use a `pystand` installed Python version, instead of the
668
+ `uv` maintained or system python, you can use one of the following approaches:
669
+
670
+ E.g. To create a `uv venv` using `pystand` installed 3.12, just hard code the
671
+ path directly, e.g. for a Linux platform:
672
+
673
+ ```sh
674
+ uv venv -p ~/.local/share/pystand/3.12
675
+ ```
676
+
677
+ Or, specify the path using pystand itself:
678
+
679
+ ```sh
680
+ uv venv -p $(pystand path 3.12)
681
+ ```
682
+
683
+ Or, use the `pystand uv` wrapper command:
684
+
685
+ ```sh
686
+ pystand uv venv -p 3.12
687
+ ```
688
+
689
+ For the common case where you simply want to use the latest `pystand` Python
690
+ release you can omit the `-p` option (and `pystand` will specify it to `uv`
691
+ under the hood): :
692
+
693
+ ```sh
694
+ pystand uv venv
695
+ ```
696
+
697
+ Note if you use the `pystand uv` wrapper, and want to specify switches to the
698
+ `uv` command, you must use `--` to separate `uv` arguments from `pystand uv`
699
+ arguments. E.g.:
700
+
701
+ ```sh
702
+ pystand uv tool install -p 3.12 cowsay -- --verbose
703
+ ```
704
+
705
+ `pystand` also provides a similar wrapper command `pystand uvx` for [`uvx`][uvx]
706
+ commands.
607
707
 
608
- Command line shell [tab
609
- completion](https://en.wikipedia.org/wiki/Command-line_completion) is
610
- automatically enabled on `pystand` commands and options using
611
- [`argcomplete`](https://github.com/kislyuk/argcomplete). You may need to
612
- first (once-only) [activate argcomplete global
613
- completion](https://github.com/kislyuk/argcomplete#global-completion).
708
+ An example where this functionality may be handy is to conveniently test
709
+ various tools against free-threaded or other Python builds from Python Build
710
+ Standalone releases.
614
711
 
615
712
  ## License
616
713
 
@@ -629,6 +726,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at
629
726
  [pbs-rel]: https://github.com/astral-sh/python-build-standalone/releases
630
727
  [pipx]: https://github.com/pypa/pipx
631
728
  [pipxu]: https://github.com/bulletmark/pipxu
729
+ [uv]: https://docs.astral.sh/uv
730
+ [uvx]: https://docs.astral.sh/uv/guides/tools/#running-tools
632
731
  [uvtool]: https://docs.astral.sh/uv/guides/tools/#installing-tools
633
732
  [pyenv]: https://github.com/pyenv/pyenv
634
733
  [pdm]: https://pdm-project.org/
@@ -1,4 +1,4 @@
1
- PYFILES := file_name(justfile_dir()) + '.py'
1
+ PYFILES := file_name(justfile_directory()) + '.py'
2
2
 
3
3
  check:
4
4
  ruff check {{PYFILES}}
@@ -14,7 +14,6 @@ classifiers = [
14
14
  ]
15
15
  dynamic = ["version"]
16
16
  dependencies = [
17
- "argcomplete",
18
17
  "packaging",
19
18
  "platformdirs",
20
19
  "argparse-from-file",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pystand
3
- Version: 2.26
3
+ Version: 2.28
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
@@ -9,7 +9,6 @@ Keywords: python-build-standalone,pyenv,hatch,pdm
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Requires-Python: >=3.8
11
11
  Description-Content-Type: text/markdown
12
- Requires-Dist: argcomplete
13
12
  Requires-Dist: packaging
14
13
  Requires-Dist: platformdirs
15
14
  Requires-Dist: argparse-from-file
@@ -35,6 +34,9 @@ provided:
35
34
  |`list`|List installed versions and show which have an update available.|
36
35
  |`show`|Show versions available from a release.|
37
36
  |`path`|Show path prefix to installed version base directory.|
37
+ |`cache`|Show size of release download caches.|
38
+ |`uv`|Run a uv command using a version of python installed by pystand.|
39
+ |`uvx`|Run a program using uvx and a version of python installed by pystand.|
38
40
 
39
41
  By default, Python versions are sourced from the latest
40
42
  `python-build-standalone` [release][pbs-rel] available (e.g.
@@ -102,11 +104,11 @@ Version 3.12.3 is already installed.
102
104
  Here are some examples showing how to use an installed version ..
103
105
 
104
106
  ```sh
105
- # Use uv to create a virtual environment to be run with latest pystand
107
+ # Use uv to create a virtual environment to be run with pystand
106
108
  # installed python 3.12:
107
109
  $ uv venv -p $(pystand path 3.12) myenv
108
110
 
109
- # Create a regular virtual environment to be run with latest pystand
111
+ # Create a regular virtual environment to be run with pystand
110
112
  # installed python 3.12:
111
113
  $ $(pystand path -p 3.12) -m venv myenv
112
114
 
@@ -142,7 +144,7 @@ usage: pystand [-h] [-D DISTRIBUTION] [-P PREFIX_DIR] [-C CACHE_DIR]
142
144
  [-M CACHE_MINUTES] [--purge-days PURGE_DAYS]
143
145
  [--github-access-token GITHUB_ACCESS_TOKEN] [--no-strip]
144
146
  [--no-color] [--cert {system,certifi,none}] [-V]
145
- {install,update,upgrade,remove,uninstall,list,show,path,cache} ...
147
+ {install,i,update,u,upgrade,remove,r,uninstall,list,l,show,s,path,p,cache,c,uv,uvx} ...
146
148
 
147
149
  Command line tool to download, install, and update pre-built Python versions
148
150
  from the python-build-standalone project at https://github.com/astral-
@@ -159,10 +161,10 @@ options:
159
161
  standalone/main/
160
162
  -P, --prefix-dir PREFIX_DIR
161
163
  specify prefix dir for storing versions. Default is
162
- "$HOME/.local/share/pystand".
164
+ "~/.local/share/pystand".
163
165
  -C, --cache-dir CACHE_DIR
164
166
  specify cache dir for downloads. Default is
165
- "$HOME/.cache/pystand".
167
+ "~/.cache/pystand".
166
168
  -M, --cache-minutes CACHE_MINUTES
167
169
  cache latest YYYYMMDD release tag fetch for this many
168
170
  minutes, before rechecking for latest. Default is 60
@@ -182,16 +184,22 @@ options:
182
184
  -V, --version just show pystand version
183
185
 
184
186
  Commands:
185
- {install,update,upgrade,remove,uninstall,list,show,path,cache}
186
- install Install one, more, or all versions from a python-
187
+ {install,i,update,u,upgrade,remove,r,uninstall,list,l,show,s,path,p,cache,c,uv,uvx}
188
+ install (i) Install one, more, or all versions from a python-
187
189
  build-standalone release.
188
- update (upgrade) Update one, more, or all versions to another release.
189
- remove (uninstall) Remove/uninstall one, more, or all versions.
190
- list List installed versions and show which have an update
190
+ update (u, upgrade)
191
+ Update one, more, or all versions to another release.
192
+ remove (r, uninstall)
193
+ Remove/uninstall one, more, or all versions.
194
+ list (l) List installed versions and show which have an update
191
195
  available.
192
- show Show versions available from a release.
193
- path Show path prefix to installed version base directory.
194
- cache Show size of release download caches.
196
+ show (s) Show versions available from a release.
197
+ path (p) Show path prefix to installed version base directory.
198
+ cache (c) Show size of release download caches.
199
+ uv Run a uv command using a version of python installed
200
+ by pystand.
201
+ uvx Run a program using uvx and a version of python
202
+ installed by pystand.
195
203
 
196
204
  Some commands offer aliases as shown in parentheses above. Note you can set
197
205
  default starting global options in ~/.config/pystand-flags.conf.
@@ -225,6 +233,8 @@ options:
225
233
  -f, --force force install even if already installed
226
234
  -s, --include-source also install source files if available in distribution
227
235
  download
236
+
237
+ aliases: i
228
238
  ```
229
239
 
230
240
  ### Command `update`
@@ -248,7 +258,7 @@ options:
248
258
  -k, --keep keep old version after updating (but only if different
249
259
  version number)
250
260
 
251
- aliases: upgrade
261
+ aliases: u, upgrade
252
262
  ```
253
263
 
254
264
  ### Command `remove`
@@ -270,7 +280,7 @@ options:
270
280
  only remove versions if from specified YYYMMDD release
271
281
  (e.g. 20240415)
272
282
 
273
- aliases: uninstall
283
+ aliases: r, uninstall
274
284
  ```
275
285
 
276
286
  ### Command `list`
@@ -290,6 +300,8 @@ options:
290
300
  -r, --release RELEASE
291
301
  use specified YYYYMMDD release (e.g. 20240415) for
292
302
  verbose compare, default is latest release
303
+
304
+ aliases: l
293
305
  ```
294
306
 
295
307
  ### Command `show`
@@ -313,6 +325,8 @@ options:
313
325
  20240415), default is latest release
314
326
  -a, --all show all available distributions for each version from
315
327
  the release
328
+
329
+ aliases: s
316
330
  ```
317
331
 
318
332
  ### Command `path`
@@ -330,6 +344,8 @@ options:
330
344
  -p, --python-path add path to python executable
331
345
  -r, --resolve fully resolve given version
332
346
  -c, --cache-path just show path to cache dir
347
+
348
+ aliases: p
333
349
  ```
334
350
 
335
351
  ### Command `cache`
@@ -351,6 +367,46 @@ options:
351
367
  -R, --remove-all-unused
352
368
  remove caches for all currently unused releases
353
369
  instead of showing size
370
+
371
+ aliases: c
372
+ ```
373
+
374
+ ### Command `uv`
375
+
376
+ ```
377
+ usage: pystand uv [-h] [-p PYTHON]
378
+ command [subcommand] [uv_args_for_command ...]
379
+
380
+ Run a uv command using a version of python installed by pystand.
381
+
382
+ positional arguments:
383
+ command uv command to run
384
+ subcommand optional uv sub-command
385
+ uv_args_for_command optional extra arguments to pass to uv command [sub-
386
+ command], start any options with "-- "
387
+
388
+ options:
389
+ -h, --help show this help message and exit
390
+ -p, --python PYTHON version of python to use, e.g. "3.12", default is
391
+ latest release version
392
+ ```
393
+
394
+ ### Command `uvx`
395
+
396
+ ```
397
+ usage: pystand uvx [-h] [-p PYTHON] program [uvx_args_for_program ...]
398
+
399
+ Run a program using uvx and a version of python installed by pystand.
400
+
401
+ positional arguments:
402
+ program uvx program to run
403
+ uvx_args_for_program optional extra arguments to pass to uvx program, start
404
+ any options with "-- "
405
+
406
+ options:
407
+ -h, --help show this help message and exit
408
+ -p, --python PYTHON version of python to use, e.g. "3.12", default is
409
+ latest release version
354
410
  ```
355
411
 
356
412
  ## Installation and Upgrade
@@ -590,7 +646,8 @@ supported options.
590
646
 
591
647
  The global options: `--distribution`, `--prefix-dir`, `--cache-dir`,
592
648
  `--cache-minutes`, `--purge-days`, `--github-access-token`, `--no-strip`,
593
- `--cert` are the only sensible candidates to consider setting as defaults.
649
+ `--no-color`, and `--cert` are the only sensible candidates to consider setting
650
+ as defaults.
594
651
 
595
652
  ## Github API Rate Limiting
596
653
 
@@ -623,14 +680,53 @@ The available options are:
623
680
  Specify the option on the command line with `--cert`, or set that as a [default
624
681
  option](#command-default-options).
625
682
 
626
- ## Command Line Tab Completion
683
+ ## Direct Usage with UV Tool
684
+
685
+ Many [`uv`][uv] commands accept a `-p/--python` option to specify a Python
686
+ version or path. To use a `pystand` installed Python version, instead of the
687
+ `uv` maintained or system python, you can use one of the following approaches:
688
+
689
+ E.g. To create a `uv venv` using `pystand` installed 3.12, just hard code the
690
+ path directly, e.g. for a Linux platform:
691
+
692
+ ```sh
693
+ uv venv -p ~/.local/share/pystand/3.12
694
+ ```
695
+
696
+ Or, specify the path using pystand itself:
697
+
698
+ ```sh
699
+ uv venv -p $(pystand path 3.12)
700
+ ```
701
+
702
+ Or, use the `pystand uv` wrapper command:
703
+
704
+ ```sh
705
+ pystand uv venv -p 3.12
706
+ ```
707
+
708
+ For the common case where you simply want to use the latest `pystand` Python
709
+ release you can omit the `-p` option (and `pystand` will specify it to `uv`
710
+ under the hood): :
711
+
712
+ ```sh
713
+ pystand uv venv
714
+ ```
715
+
716
+ Note if you use the `pystand uv` wrapper, and want to specify switches to the
717
+ `uv` command, you must use `--` to separate `uv` arguments from `pystand uv`
718
+ arguments. E.g.:
719
+
720
+ ```sh
721
+ pystand uv tool install -p 3.12 cowsay -- --verbose
722
+ ```
723
+
724
+ `pystand` also provides a similar wrapper command `pystand uvx` for [`uvx`][uvx]
725
+ commands.
627
726
 
628
- Command line shell [tab
629
- completion](https://en.wikipedia.org/wiki/Command-line_completion) is
630
- automatically enabled on `pystand` commands and options using
631
- [`argcomplete`](https://github.com/kislyuk/argcomplete). You may need to
632
- first (once-only) [activate argcomplete global
633
- completion](https://github.com/kislyuk/argcomplete#global-completion).
727
+ An example where this functionality may be handy is to conveniently test
728
+ various tools against free-threaded or other Python builds from Python Build
729
+ Standalone releases.
634
730
 
635
731
  ## License
636
732
 
@@ -649,6 +745,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at
649
745
  [pbs-rel]: https://github.com/astral-sh/python-build-standalone/releases
650
746
  [pipx]: https://github.com/pypa/pipx
651
747
  [pipxu]: https://github.com/bulletmark/pipxu
748
+ [uv]: https://docs.astral.sh/uv
749
+ [uvx]: https://docs.astral.sh/uv/guides/tools/#running-tools
652
750
  [uvtool]: https://docs.astral.sh/uv/guides/tools/#installing-tools
653
751
  [pyenv]: https://github.com/pyenv/pyenv
654
752
  [pdm]: https://pdm-project.org/
@@ -1,4 +1,3 @@
1
- argcomplete
2
1
  packaging
3
2
  platformdirs
4
3
  argparse-from-file
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/python3
2
- # PYTHON_ARGCOMPLETE_OK
3
2
  """
4
3
  Command line tool to download, install, and update pre-built Python
5
4
  versions from the python-build-standalone project at
@@ -14,6 +13,7 @@ import platform
14
13
  import re
15
14
  import shutil
16
15
  import ssl
16
+ import subprocess
17
17
  import sys
18
18
  import time
19
19
  from collections import defaultdict
@@ -23,10 +23,10 @@ from pathlib import Path
23
23
  from typing import Any
24
24
  from urllib.request import urlopen
25
25
 
26
- import argcomplete
27
26
  import filelock
28
27
  import platformdirs
29
28
  from argparse_from_file import ArgumentParser, Namespace
29
+ from packaging.version import InvalidVersion
30
30
  from packaging.version import parse as parse_version
31
31
 
32
32
  REPO = 'python-build-standalone'
@@ -114,6 +114,14 @@ class ColorDist(ColorTable):
114
114
  return text.split('-', 1)[0]
115
115
 
116
116
 
117
+ def unexpanduser(path: Path, *, home=Path.home()) -> Path:
118
+ "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) :])
121
+
122
+ return path
123
+
124
+
117
125
  def is_admin() -> bool:
118
126
  "Check if we are running as root"
119
127
  if platform.system() == 'Windows':
@@ -136,6 +144,12 @@ def get_version() -> str:
136
144
  return ver
137
145
 
138
146
 
147
+ def get_major_version(args: Namespace) -> str | None:
148
+ '"Return the latest major version installed"'
149
+ vers = sorted(f.name for f in args._versions.glob('[3-9]'))
150
+ return vers[-1] if vers else None
151
+
152
+
139
153
  def get_json(file: Path) -> dict[str, Any]:
140
154
  from json import load
141
155
 
@@ -582,6 +596,12 @@ def show_list(args: Namespace) -> None:
582
596
  if args.re_match and not re.search(args.re_match, release):
583
597
  continue
584
598
 
599
+ # Ignore any bogus releases that don't parse as versions
600
+ try:
601
+ this_version = parse_version(release)
602
+ except InvalidVersion:
603
+ continue
604
+
585
605
  if dt_str := releases.get(release):
586
606
  dts = (
587
607
  datetime.fromisoformat(dt_str)
@@ -598,8 +618,7 @@ def show_list(args: Namespace) -> None:
598
618
  else:
599
619
  app = ''
600
620
 
601
- pre = ' pre-release' if parse_version(release) > latest else ''
602
-
621
+ pre = ' pre-release' if this_version > latest else ''
603
622
  print(f'{release} {dts}{app}{pre}')
604
623
 
605
624
 
@@ -631,7 +650,6 @@ def remove(args: Namespace, version: str) -> None:
631
650
 
632
651
  def strip_binaries(vdir: Path, distribution: str) -> bool:
633
652
  "Strip binaries from files in a version directory"
634
- from subprocess import DEVNULL, run
635
653
 
636
654
  # Only run the strip command on Linux hosts and for Linux distributions
637
655
  was_stripped = False
@@ -645,7 +663,7 @@ def strip_binaries(vdir: Path, distribution: str) -> bool:
645
663
  if not file.is_symlink() and file.is_file():
646
664
  cmd = f'strip -p --strip-unneeded {file}'.split()
647
665
  try:
648
- run(cmd, stderr=DEVNULL)
666
+ subprocess.run(cmd, stderr=subprocess.DEVNULL)
649
667
  except Exception:
650
668
  pass
651
669
  else:
@@ -734,14 +752,31 @@ def create_cert(option: str) -> ssl.SSLContext | None:
734
752
  return ssl._create_unverified_context()
735
753
 
736
754
 
755
+ def run_uv(args: Namespace, cmd: list[str], cmdopts: list[str]) -> str | None:
756
+ "Run a uv command with the specified or latest installed python version"
757
+ if not (vers := (args.python or get_major_version(args))):
758
+ return 'No installed python version found.'
759
+
760
+ py = args._versions / vers
761
+ if not py.is_dir():
762
+ return f'No installed python {py.name} version found.'
763
+
764
+ # Resolve to at least minor version if only major version specified
765
+ if '.' not in py.name:
766
+ py = py.resolve()
767
+ py = py.with_name(py.stem)
768
+
769
+ subprocess.run(cmd + ['-p', py] + cmdopts)
770
+
771
+
737
772
  def main() -> str | None:
738
773
  "Main code"
739
774
  distro_default = DISTRIBUTIONS.get((platform.system(), platform.machine()))
740
775
  distro_help = distro_default or '?unknown?'
741
776
 
742
777
  p = '/opt' if is_admin() else platformdirs.user_data_dir()
743
- prefix_dir = str(Path(p, PROG))
744
- cache_dir = platformdirs.user_cache_path() / PROG
778
+ prefix_dir = unexpanduser(Path(p, PROG))
779
+ cache_dir = unexpanduser(platformdirs.user_cache_path() / PROG)
745
780
 
746
781
  # Parse arguments
747
782
  opt = ArgumentParser(
@@ -760,7 +795,7 @@ def main() -> str | None:
760
795
  opt.add_argument(
761
796
  '-P',
762
797
  '--prefix-dir',
763
- default=prefix_dir,
798
+ default=str(prefix_dir),
764
799
  help='specify prefix dir for storing versions. Default is "%(default)s".',
765
800
  )
766
801
  opt.add_argument(
@@ -832,8 +867,6 @@ def main() -> str | None:
832
867
  # Set the function to call
833
868
  cmdopt.set_defaults(func=cls.run, name=name, parser=cmdopt)
834
869
 
835
- # Command arguments are now defined, so we can set up argcomplete
836
- argcomplete.autocomplete(opt)
837
870
  args = opt.parse_args()
838
871
 
839
872
  if 'func' not in args:
@@ -889,6 +922,7 @@ def main() -> str | None:
889
922
  # COMMAND
890
923
  class install_:
891
924
  doc = f'Install one, more, or all versions from a {REPO} release.'
925
+ aliases = ['i']
892
926
 
893
927
  @staticmethod
894
928
  def init(parser: ArgumentParser) -> None:
@@ -988,7 +1022,7 @@ class install_:
988
1022
  class update_:
989
1023
  "Update one, more, or all versions to another release."
990
1024
 
991
- aliases = ['upgrade']
1025
+ aliases = ['u', 'upgrade']
992
1026
 
993
1027
  @staticmethod
994
1028
  def init(parser: ArgumentParser) -> None:
@@ -1075,7 +1109,7 @@ class update_:
1075
1109
  class remove_:
1076
1110
  "Remove/uninstall one, more, or all versions."
1077
1111
 
1078
- aliases = ['uninstall']
1112
+ aliases = ['r', 'uninstall']
1079
1113
 
1080
1114
  @staticmethod
1081
1115
  def init(parser: ArgumentParser) -> None:
@@ -1116,6 +1150,8 @@ class remove_:
1116
1150
  class list_:
1117
1151
  "List installed versions and show which have an update available."
1118
1152
 
1153
+ aliases = ['l']
1154
+
1119
1155
  @staticmethod
1120
1156
  def init(parser: ArgumentParser) -> None:
1121
1157
  parser.add_argument(
@@ -1204,6 +1240,7 @@ class show_:
1204
1240
  View available releases and their distributions at
1205
1241
  {GITHUB_SITE}/releases.
1206
1242
  """
1243
+ aliases = ['s']
1207
1244
 
1208
1245
  @staticmethod
1209
1246
  def init(parser: ArgumentParser) -> None:
@@ -1278,6 +1315,8 @@ class show_:
1278
1315
  class path_:
1279
1316
  "Show path prefix to installed version base directory."
1280
1317
 
1318
+ aliases = ['p']
1319
+
1281
1320
  @staticmethod
1282
1321
  def init(parser: ArgumentParser) -> None:
1283
1322
  parser.add_argument(
@@ -1329,6 +1368,8 @@ class path_:
1329
1368
  class cache_:
1330
1369
  "Show size of release download caches."
1331
1370
 
1371
+ aliases = ['c']
1372
+
1332
1373
  @staticmethod
1333
1374
  def init(parser: ArgumentParser) -> None:
1334
1375
  parser.add_argument(
@@ -1395,5 +1436,59 @@ class cache_:
1395
1436
  show_cache_size(args._downloads, args)
1396
1437
 
1397
1438
 
1439
+ # COMMAND
1440
+ class uv_:
1441
+ __doc__ = f'Run a uv command using a version of python installed by {PROG}.'
1442
+
1443
+ @staticmethod
1444
+ def init(parser: ArgumentParser) -> None:
1445
+ parser.add_argument(
1446
+ '-p',
1447
+ '--python',
1448
+ help='version of python to use, e.g. "3.12", default is latest release version',
1449
+ )
1450
+
1451
+ parser.add_argument('command', help='uv command to run')
1452
+ parser.add_argument('subcommand', nargs='?', help='optional uv sub-command')
1453
+
1454
+ parser.add_argument(
1455
+ 'uv_args_for_command',
1456
+ nargs='*',
1457
+ help='optional extra arguments to pass to uv command [sub-command], start any options with "-- "',
1458
+ )
1459
+
1460
+ @staticmethod
1461
+ def run(args: Namespace) -> str | None:
1462
+ cmd = ['uv', args.command]
1463
+ if args.subcommand:
1464
+ cmd.append(args.subcommand)
1465
+
1466
+ return run_uv(args, cmd, args.uv_args_for_command)
1467
+
1468
+
1469
+ # COMMAND
1470
+ class uvx_:
1471
+ __doc__ = f'Run a program using uvx and a version of python installed by {PROG}.'
1472
+
1473
+ @staticmethod
1474
+ def init(parser: ArgumentParser) -> None:
1475
+ parser.add_argument(
1476
+ '-p',
1477
+ '--python',
1478
+ help='version of python to use, e.g. "3.12", default is latest release version',
1479
+ )
1480
+
1481
+ parser.add_argument('program', help='uvx program to run')
1482
+ parser.add_argument(
1483
+ 'uvx_args_for_program',
1484
+ nargs='*',
1485
+ help='optional extra arguments to pass to uvx program, start any options with "-- "',
1486
+ )
1487
+
1488
+ @staticmethod
1489
+ def run(args: Namespace) -> str | None:
1490
+ return run_uv(args, ['uvx'], [args.program] + args.uvx_args_for_program)
1491
+
1492
+
1398
1493
  if __name__ == '__main__':
1399
1494
  sys.exit(main())
File without changes
File without changes